diff --git a/DEPS b/DEPS
index 57ea51f..a9c7ca5 100644
--- a/DEPS
+++ b/DEPS
@@ -245,11 +245,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': 'b292c30aa0c63fe858d8b68393629ebd4ca734c4',
+  'skia_revision': 'd7f7cc87910800232c5900ebb64c0c00781cd0c2',
   # 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': 'ef9b5c3a6d0ca76cb2a034abbe40da7caa33c84a',
+  'v8_revision': '63def35d81d668ee5eedd970616fa0f421813dc1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
@@ -261,7 +261,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': '2c57ad8aa8bf4f7769f4d14f1b49235a8a3d87f8',
+  'pdfium_revision': '900c5fb79d3606ed5e25640d7443af4a470e3ac3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -320,7 +320,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': 'a16760e710a0f22595b5cde2555d96d4df7e6e88',
+  'devtools_frontend_revision': '47cb034b7a90184550e656850e98a760f55dcea2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -360,11 +360,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '9fb7a5146ab6102dbcd73bb7e9053f5f14e4dd98',
+  'dawn_revision': '377ead9d448eb42342c0a957e6e3e4b485c4f7c7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': 'cfb0cce5c3c0be76e9baf5950a6fff393ba0c158',
+  'quiche_revision': '935f2c21ecea07b03c1e4798ef8022da5bd5a344',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -408,7 +408,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'libunwind_revision':    '659c7d91af58bfeada9f3ed5bf1a192059b68b86',
+  'libunwind_revision':    'f2ef96ecb8ecba64489f0412d345698ffb38e094',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -851,7 +851,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 't0lRUsrauVSL4BzBBgnA0MPocUJborjdNnEoHgNwX8oC',
+          'version': '_S6ob5k5orx8r5rKoBr0CShQ93YDTrBntP3CxBaF2oQC',
       },
     ],
     'condition': 'checkout_android',
@@ -1090,7 +1090,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '91d2a5db01e886afa0ffdbe1b73ad6ac6aa3ee95',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '66c9784478053eebdfefb6c2d17b093de4079262',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1694,7 +1694,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '729be85c2f01876a1ea075c523d542ebaaa76301',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'ff246c1c0479d8a5af172c179aa01c327daeb222',
+    Var('webrtc_git') + '/src.git' + '@' + '6cd64b6bd52703159c9290a22e599ca9bbeb0d1d',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1764,7 +1764,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@27a3a9e84c95c36df6803db7b70b0d9961bb0559',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b6f15c40f717eb764baa7b0d93f4ad449c89158a',
     'condition': 'checkout_src_internal',
   },
 
@@ -1805,7 +1805,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'ys03EtngWhLQQ7994Y64lxbHzdOBnnobHlw2b37ou94C',
+        'version': 'Tav_AojO1FUuEVe0sykGdSBfmtp2L1exqF9u1Ls_XQoC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1816,7 +1816,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'uYHeCyvV2v2hhOPtVpE12ZFyS8tmPfzsa-CvXvP7J4MC',
+        'version': 'onbq--a_fylirE0vjfVJtDAsMf0DUJ9O8CdpaKmFgCQC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 1718b27..a2c11d1 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -2115,6 +2115,7 @@
     "//chromeos/ui/frame",
     "//chromeos/ui/wm",
     "//components/account_id",
+    "//components/app_constants",
     "//components/app_restore",
     "//components/country_codes",
     "//components/desks_storage",
@@ -2825,6 +2826,7 @@
     "//chromeos/ui/vector_icons",
     "//chromeos/ui/wm",
     "//components/account_id",
+    "//components/app_constants",
     "//components/app_restore",
     "//components/desks_storage",
     "//components/global_media_controls",
diff --git a/ash/DEPS b/ash/DEPS
index 922ac86..6930b31d 100644
--- a/ash/DEPS
+++ b/ash/DEPS
@@ -4,6 +4,7 @@
   "+cc/output",
   "+cc/paint",
   "+components/account_id",
+  "+components/app_constants",
   "+components/app_restore",
   "+components/desks_storage",
   "+components/discardable_memory/public",
diff --git a/ash/app_list/app_list_test_api.cc b/ash/app_list/app_list_test_api.cc
index d743465..ba144a5 100644
--- a/ash/app_list/app_list_test_api.cc
+++ b/ash/app_list/app_list_test_api.cc
@@ -32,10 +32,12 @@
 #include "ash/test/layer_animation_stopped_waiter.h"
 #include "base/callback.h"
 #include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/window_observer.h"
 #include "ui/compositor/layer.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/controls/scroll_view.h"
 #include "ui/views/view_model.h"
 
 namespace ash {
@@ -100,6 +102,34 @@
       ->reorder_undo_container_for_test();
 }
 
+// AppListVisibilityChangedWaiter ----------------------------------------------
+
+// Waits until the app list visibility changes.
+class AppListVisibilityChangedWaiter : public AppListControllerObserver {
+ public:
+  AppListVisibilityChangedWaiter() = default;
+  AppListVisibilityChangedWaiter(const AppListVisibilityChangedWaiter&) =
+      delete;
+  AppListVisibilityChangedWaiter& operator=(
+      const AppListVisibilityChangedWaiter&) = delete;
+  ~AppListVisibilityChangedWaiter() override {
+    AppListController::Get()->RemoveObserver(this);
+  }
+
+  void Wait() {
+    AppListController::Get()->AddObserver(this);
+    run_loop_.Run();
+  }
+
+  // AppListControllerObserver:
+  void OnAppListVisibilityChanged(bool shown, int64_t display_id) override {
+    run_loop_.Quit();
+  }
+
+ private:
+  base::RunLoop run_loop_;
+};
+
 // WindowAddedWaiter -----------------------------------------------------------
 
 // Waits until a child window is added to a container window.
@@ -187,9 +217,18 @@
 }
 
 void AppListTestApi::WaitForAppListShowAnimation(bool is_bubble_window) {
+  // Ensure that the app list is visible before waiting for animations.
+  AppListController* controller = AppListControllerImpl::Get();
+  if (!controller->IsVisible()) {
+    AppListVisibilityChangedWaiter waiter;
+    waiter.Wait();
+    if (!controller->IsVisible()) {
+      ADD_FAILURE() << "Launcher is not visible.";
+    }
+  }
+
   // Wait for the app list window animation.
-  aura::Window* app_list_window =
-      Shell::Get()->app_list_controller()->GetWindow();
+  aura::Window* app_list_window = controller->GetWindow();
   DCHECK(app_list_window);
   LayerAnimationStoppedWaiter().Wait(app_list_window->layer());
 
@@ -204,7 +243,17 @@
   if (!scrollable_apps_grid_view->layer())
     return;
 
-  // Wait for the apps grid animation.
+  // Wait for the animation to show the bubble view.
+  LayerAnimationStoppedWaiter().Wait(GetAppListBubbleView()->layer());
+
+  // Wait for the animation to show the apps page.
+  LayerAnimationStoppedWaiter().Wait(GetAppListBubbleView()
+                                         ->apps_page_for_test()
+                                         ->scroll_view()
+                                         ->contents()
+                                         ->layer());
+
+  // Wait for the apps grid slide animation.
   LayerAnimationStoppedWaiter().Wait(scrollable_apps_grid_view->layer());
 }
 
@@ -242,8 +291,8 @@
   DCHECK_GE(apps.size(), 2u);
 
   AppListModel* model = GetAppListModel();
-  // Create a folder using the first two apps, and add the others to the folder
-  // iteratively.
+  // Create a folder using the first two apps, and add the others to the
+  // folder iteratively.
   std::string folder_id = model->MergeItems(apps[0], apps[1]);
   // Return early if MergeItems failed.
   if (folder_id.empty())
diff --git a/ash/assistant/ui/base/assistant_button.cc b/ash/assistant/ui/base/assistant_button.cc
index f6ffbeb5..6b537c4 100644
--- a/ash/assistant/ui/base/assistant_button.cc
+++ b/ash/assistant/ui/base/assistant_button.cc
@@ -12,12 +12,10 @@
 #include "base/bind.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/gfx/canvas.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
-#include "ui/views/animation/ink_drop.h"
-#include "ui/views/animation/ink_drop_impl.h"
 #include "ui/views/controls/highlight_path_generator.h"
 #include "ui/views/view.h"
 
@@ -26,7 +24,7 @@
 namespace {
 
 // Appearance.
-constexpr int kInkDropInset = 2;
+constexpr int kFocusRingStrokeWidth = 2;
 
 }  // namespace
 
@@ -44,40 +42,13 @@
                                              base::Unretained(this))),
       listener_(listener),
       id_(button_id) {
-  // Avoid drawing default focus rings since Assistant buttons use
-  // a custom highlight on focus.
+  // Avoid drawing default dashed focus and draw customized focus.
   SetInstallFocusRingOnFocus(false);
 
   // Image.
   SetFlipCanvasOnPaintForRTLUI(false);
   SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
   SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
-
-  // Ink drop.
-  views::InkDrop::Get(this)->SetMode(views::InkDropHost::InkDropMode::ON);
-  SetHasInkDropActionOnClick(true);
-  UpdateInkDropColors();
-  views::InstallCircleHighlightPathGenerator(this, gfx::Insets(kInkDropInset));
-  views::InkDrop::UseInkDropForFloodFillRipple(views::InkDrop::Get(this));
-  views::InkDrop::Get(this)->SetCreateHighlightCallback(base::BindRepeating(
-      [](Button* host) {
-        auto highlight = std::make_unique<views::InkDropHighlight>(
-            gfx::SizeF(host->size()),
-            views::InkDrop::Get(host)->GetBaseColor());
-        highlight->set_visible_opacity(
-            views::InkDrop::Get(host)->GetVisibleOpacity());
-        return highlight;
-      },
-      this));
-  views::InkDrop::Get(this)->SetCreateRippleCallback(base::BindRepeating(
-      [](Button* host) -> std::unique_ptr<views::InkDropRipple> {
-        return std::make_unique<views::FloodFillInkDropRipple>(
-            host->size(), gfx::Insets(kInkDropInset),
-            views::InkDrop::Get(host)->GetInkDropCenterBasedOnLastEvent(),
-            views::InkDrop::Get(host)->GetBaseColor(),
-            views::InkDrop::Get(host)->GetVisibleOpacity());
-      },
-      this));
 }
 
 AssistantButton::~AssistantButton() = default;
@@ -123,18 +94,37 @@
   return button;
 }
 
+void AssistantButton::OnBlur() {
+  views::ImageButton::OnBlur();
+  SchedulePaint();
+}
+
 void AssistantButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
   // Note that the current assumption is that button bounds are square.
   DCHECK_EQ(width(), height());
-  UpdateFocusPainter();
+}
+
+void AssistantButton::OnFocus() {
+  views::ImageButton::OnFocus();
+  SchedulePaint();
+}
+
+void AssistantButton::OnPaintBackground(gfx::Canvas* canvas) {
+  if (HasFocus()) {
+    cc::PaintFlags circle_flags;
+    circle_flags.setAntiAlias(true);
+    circle_flags.setColor(ColorProvider::Get()->GetControlsLayerColor(
+        ColorProvider::ControlsLayerType::kFocusRingColor));
+    circle_flags.setStyle(cc::PaintFlags::kStroke_Style);
+    circle_flags.setStrokeWidth(kFocusRingStrokeWidth);
+    canvas->DrawCircle(GetLocalBounds().CenterPoint(),
+                       width() / 2 - kFocusRingStrokeWidth, circle_flags);
+  }
 }
 
 void AssistantButton::OnThemeChanged() {
   views::View::OnThemeChanged();
 
-  UpdateFocusPainter();
-  UpdateInkDropColors();
-
   if (!icon_color_type_.has_value() || !icon_description_.has_value())
     return;
 
@@ -150,25 +140,6 @@
   listener_->OnButtonPressed(id_);
 }
 
-void AssistantButton::UpdateFocusPainter() {
-  ScopedAssistantLightModeAsDefault scoped_assistant_light_mode_as_default;
-  std::pair<SkColor, float> base_color_and_opacity =
-      ColorProvider::Get()->GetInkDropBaseColorAndOpacity();
-  SetFocusPainter(views::Painter::CreateSolidRoundRectPainter(
-      SkColorSetA(base_color_and_opacity.first,
-                  0xff * base_color_and_opacity.second),
-      width() / 2 - kInkDropInset, gfx::Insets(kInkDropInset)));
-}
-
-void AssistantButton::UpdateInkDropColors() {
-  ScopedAssistantLightModeAsDefault scoped_assistant_light_mode_as_default;
-
-  std::pair<SkColor, float> base_color_and_opacity =
-      ColorProvider::Get()->GetInkDropBaseColorAndOpacity();
-  views::InkDrop::Get(this)->SetBaseColor(base_color_and_opacity.first);
-  views::InkDrop::Get(this)->SetVisibleOpacity(base_color_and_opacity.second);
-}
-
 BEGIN_METADATA(AssistantButton, views::ImageButton)
 END_METADATA
 
diff --git a/ash/assistant/ui/base/assistant_button.h b/ash/assistant/ui/base/assistant_button.h
index c97cbdf..a2043501 100644
--- a/ash/assistant/ui/base/assistant_button.h
+++ b/ash/assistant/ui/base/assistant_button.h
@@ -26,6 +26,7 @@
 
 namespace ash {
 
+class AssistantButton;
 class AssistantButtonListener;
 enum class AssistantButtonId;
 
@@ -76,15 +77,16 @@
   AssistantButtonId GetAssistantButtonId() const { return id_; }
 
   // views::ImageButton:
+  void OnBlur() override;
   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
+  void OnFocus() override;
 
   // views::View:
+  void OnPaintBackground(gfx::Canvas* canvas) override;
   void OnThemeChanged() override;
 
  private:
   void OnButtonPressed();
-  void UpdateFocusPainter();
-  void UpdateInkDropColors();
 
   AssistantButtonListener* listener_;
   const AssistantButtonId id_;
diff --git a/ash/assistant/ui/base/assistant_button_unittest.cc b/ash/assistant/ui/base/assistant_button_unittest.cc
index f46764a..98d25f7 100644
--- a/ash/assistant/ui/base/assistant_button_unittest.cc
+++ b/ash/assistant/ui/base/assistant_button_unittest.cc
@@ -27,7 +27,6 @@
 #include "ui/gfx/image/image_unittest_util.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/vector_icon_types.h"
-#include "ui/views/animation/ink_drop.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/painter.h"
 #include "ui/views/widget/widget.h"
@@ -39,7 +38,7 @@
 constexpr int kSizeInDip = 32;
 constexpr int kIconSizeInDip = 24;
 constexpr int kIconOffset = 4;
-constexpr int kInkDropInset = 2;
+constexpr int kFocusRingStrokeWidth = 2;
 
 SkBitmap CreateExpectedImageWithFocus(SkColor icon_color, SkColor focus_color) {
   gfx::Canvas expected(gfx::Size(kSizeInDip, kSizeInDip), /*image_scale=*/1.0f,
@@ -47,9 +46,15 @@
   expected.DrawImageInt(
       gfx::CreateVectorIcon(kKeyboardIcon, kIconSizeInDip, icon_color),
       kIconOffset, kIconOffset);
-  views::Painter::CreateSolidRoundRectPainter(
-      focus_color, kSizeInDip / 2 - kInkDropInset, gfx::Insets(kInkDropInset))
-      ->Paint(&expected, gfx::Size(kSizeInDip, kSizeInDip));
+
+  cc::PaintFlags circle_flags;
+  circle_flags.setAntiAlias(true);
+  circle_flags.setColor(focus_color);
+  circle_flags.setStyle(cc::PaintFlags::kStroke_Style);
+  circle_flags.setStrokeWidth(kFocusRingStrokeWidth);
+  expected.DrawCircle(gfx::Point(kSizeInDip / 2, kSizeInDip / 2),
+                      kSizeInDip / 2 - kFocusRingStrokeWidth, circle_flags);
+
   return expected.GetBitmap();
 }
 
@@ -157,10 +162,9 @@
   EXPECT_TRUE(gfx::test::AreBitmapsEqual(
       CreateExpectedImageWithFocus(
           /*icon_color=*/gfx::kGoogleGrey900,
-          /*focus_color=*/SkColorSetA(SK_ColorBLACK, 0xff * 0.06f)),
+          /*focus_color=*/ColorProvider::Get()->GetControlsLayerColor(
+              ColorProvider::ControlsLayerType::kFocusRingColor)),
       canvas.GetBitmap()));
-  EXPECT_EQ(views::InkDrop::Get(button)->GetBaseColor(), SK_ColorBLACK);
-  EXPECT_EQ(views::InkDrop::Get(button)->GetVisibleOpacity(), 0.06f);
 }
 
 TEST_F(AssistantButtonTest, FocusAndHoverColorDarkLightMode) {
@@ -192,10 +196,9 @@
   EXPECT_TRUE(gfx::test::AreBitmapsEqual(
       CreateExpectedImageWithFocus(
           /*icon_color=*/gfx::kGoogleGrey900,
-          /*focus_color=*/SkColorSetA(SK_ColorBLACK, 0xff * 0.06f)),
+          /*focus_color=*/ColorProvider::Get()->GetControlsLayerColor(
+              ColorProvider::ControlsLayerType::kFocusRingColor)),
       canvas.GetBitmap()));
-  EXPECT_EQ(views::InkDrop::Get(button)->GetBaseColor(), SK_ColorBLACK);
-  EXPECT_EQ(views::InkDrop::Get(button)->GetVisibleOpacity(), 0.06f);
 
   // Switch to dark mode
   Shell::Get()->session_controller()->GetActivePrefService()->SetBoolean(
@@ -208,9 +211,8 @@
   EXPECT_TRUE(gfx::test::AreBitmapsEqual(
       CreateExpectedImageWithFocus(
           /*icon_color=*/gfx::kGoogleGrey200,
-          /*focus_color=*/SkColorSetA(SK_ColorWHITE, 0xff * 0.08f)),
+          /*focus_color=*/ColorProvider::Get()->GetControlsLayerColor(
+              ColorProvider::ControlsLayerType::kFocusRingColor)),
       canvas.GetBitmap()));
-  EXPECT_EQ(views::InkDrop::Get(button)->GetBaseColor(), SK_ColorWHITE);
-  EXPECT_EQ(views::InkDrop::Get(button)->GetVisibleOpacity(), 0.08f);
 }
 }  // namespace ash
diff --git a/ash/components/arc/compat_mode/arc_resize_lock_manager.cc b/ash/components/arc/compat_mode/arc_resize_lock_manager.cc
index 29dd67c..a834a6b 100644
--- a/ash/components/arc/compat_mode/arc_resize_lock_manager.cc
+++ b/ash/components/arc/compat_mode/arc_resize_lock_manager.cc
@@ -289,19 +289,21 @@
   const bool is_fully_locked =
       window->GetProperty(ash::kArcResizeLockTypeKey) ==
       ash::ArcResizeLockType::RESIZE_DISABLED_NONTOGGLABLE;
-  // The state is |ArcResizeLockState::READY| only when we enable the resize
-  // lock for an app for the first time.
-  if (pref_delegate_->GetResizeLockState(*app_id) ==
-      mojom::ArcResizeLockState::READY) {
-    if (ShouldShowSplashScreenDialog(pref_delegate_)) {
-      WindowActivationObserver::RunOnActivated(
-          window, base::BindOnce(&ArcSplashScreenDialogView::Show, window,
-                                 is_fully_locked));
-    }
-  }
 
+  // The state is |ArcResizeLockState::READY| only when we enable the resize
+  // lock for an app for the first time. UpdateResizeLockState() may overwrite
+  // the ResizeLockState so this check must be done before it's called.
+  const bool is_first_launch = pref_delegate_->GetResizeLockState(*app_id) ==
+                               mojom::ArcResizeLockState::READY;
   UpdateResizeLockState(window);
 
+  if (is_first_launch && ShouldShowSplashScreenDialog(pref_delegate_)) {
+    // UpdateResizeLockState() must be called beforehand as compat-mode button
+    // must exist before showing the splash dialog because it's used as the
+    // anchoring target.
+    ShowSplashScreenDialog(window, is_fully_locked);
+  }
+
   if (!is_fully_locked &&
       base::FeatureList::IsEnabled(arc::kCompatSnapFeature)) {
     window->SetProperty(ash::kUnresizableSnappedSizeKey,
@@ -380,4 +382,11 @@
   }
 }
 
+void ArcResizeLockManager::ShowSplashScreenDialog(aura::Window* window,
+                                                  bool is_fully_locked) {
+  WindowActivationObserver::RunOnActivated(
+      window, base::BindOnce(&ArcSplashScreenDialogView::Show, window,
+                             is_fully_locked));
+}
+
 }  // namespace arc
diff --git a/ash/components/arc/compat_mode/arc_resize_lock_manager.h b/ash/components/arc/compat_mode/arc_resize_lock_manager.h
index 67afd57..be87d47 100644
--- a/ash/components/arc/compat_mode/arc_resize_lock_manager.h
+++ b/ash/components/arc/compat_mode/arc_resize_lock_manager.h
@@ -65,6 +65,10 @@
   void UpdateResizeLockState(aura::Window* window);
   void UpdateShadow(aura::Window* window);
 
+  // virtual for unittest.
+  virtual void ShowSplashScreenDialog(aura::Window* window,
+                                      bool is_fully_locked);
+
   ArcResizeLockPrefDelegate* pref_delegate_{nullptr};
 
   // Using unique_ptr to allow unittest to override.
diff --git a/ash/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc b/ash/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc
index dfd7eeb9..0a1c5991 100644
--- a/ash/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc
+++ b/ash/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc
@@ -74,6 +74,25 @@
   base::flat_set<const aura::Window*> update_compat_mode_button_called;
 };
 
+class TestArcResizeLockManager : public ArcResizeLockManager {
+ public:
+  TestArcResizeLockManager() : ArcResizeLockManager(nullptr, nullptr) {}
+  ~TestArcResizeLockManager() override = default;
+
+  // ArcResizeLockManager:
+  void ShowSplashScreenDialog(aura::Window* window, bool) override {
+    show_splash_callback_.Run(window);
+  }
+
+  void set_show_splash_callback(
+      base::RepeatingCallback<void(aura::Window*)> callback) {
+    show_splash_callback_ = std::move(callback);
+  }
+
+ private:
+  base::RepeatingCallback<void(aura::Window*)> show_splash_callback_;
+};
+
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kNonInterestedPropKey, false)
 
 constexpr std::array<ash::ArcResizeLockType, 4> kArcResizeLockTypes{
@@ -122,8 +141,13 @@
     test_compat_mode_button_controller_->ResetUpdateCompatModeButtonCalled();
   }
 
+  void SetShowSplashCallback(
+      base::RepeatingCallback<void(aura::Window*)> callback) {
+    arc_resize_lock_manager_.set_show_splash_callback(std::move(callback));
+  }
+
  private:
-  ArcResizeLockManager arc_resize_lock_manager_{nullptr, nullptr};
+  TestArcResizeLockManager arc_resize_lock_manager_;
 
   // Owned by |arc_resize_lock_manager_|.
   TestCompatModeButtonController* test_compat_mode_button_controller_;
@@ -473,4 +497,28 @@
   EXPECT_EQ(arc_window->GetProperty(ash::kUnresizableSnappedSizeKey), nullptr);
 }
 
+// Test that the splash screen dialog is shown properly.
+TEST_F(ArcResizeLockManagerTest, ShowSplashScreen) {
+  auto arc_window = CreateFakeWindow(true);
+  std::string app_id = "app-id";
+  arc_window->SetProperty(ash::kAppIDKey, app_id);
+  pref_delegate()->SetResizeLockState(app_id, mojom::ArcResizeLockState::READY);
+  pref_delegate()->SetShowSplashScreenDialogCount(1);
+
+  EXPECT_FALSE(IsResizeLockEnabled(arc_window.get()));
+
+  bool show_splash_called = false;
+  SetShowSplashCallback(base::BindLambdaForTesting([&](aura::Window* window) {
+    show_splash_called = true;
+    // The compat-mode button must exist at the time of showing the splash.
+    EXPECT_TRUE(IsUpdateCompatModeButtonCalled(window));
+  }));
+
+  // Enable resize-lock.
+  arc_window->SetProperty(ash::kArcResizeLockTypeKey,
+                          ash::ArcResizeLockType::RESIZE_DISABLED_TOGGLABLE);
+
+  EXPECT_TRUE(show_splash_called);
+}
+
 }  // namespace arc
diff --git a/ash/login/ui/smart_lock_auth_factor_model.cc b/ash/login/ui/smart_lock_auth_factor_model.cc
index 12835e4..bce4bb2 100644
--- a/ash/login/ui/smart_lock_auth_factor_model.cc
+++ b/ash/login/ui/smart_lock_auth_factor_model.cc
@@ -87,8 +87,15 @@
 
 int SmartLockAuthFactorModel::GetLabelId() const {
   if (auth_result_.has_value()) {
-    return auth_result_.value() ? IDS_SMART_LOCK_LABEL_PHONE_LOCKED
-                                : IDS_AUTH_FACTOR_LABEL_CANNOT_UNLOCK;
+    if (auth_result_.value()) {
+      return IDS_SMART_LOCK_LABEL_PHONE_LOCKED;
+    }
+
+    // Once the Smart Lock error message has timed out, prompt the
+    // user to enter their password (since Smart Lock has permanently failed).
+    return has_permanent_error_display_timed_out_
+               ? IDS_AUTH_FACTOR_LABEL_PASSWORD_REQUIRED
+               : IDS_AUTH_FACTOR_LABEL_CANNOT_UNLOCK;
   }
 
   switch (state_) {
diff --git a/ash/login/ui/smart_lock_auth_factor_model_unittest.cc b/ash/login/ui/smart_lock_auth_factor_model_unittest.cc
index b5d3dfa..573a548 100644
--- a/ash/login/ui/smart_lock_auth_factor_model_unittest.cc
+++ b/ash/login/ui/smart_lock_auth_factor_model_unittest.cc
@@ -231,4 +231,13 @@
   }
 }
 
+TEST_F(SmartLockAuthFactorModelUnittest, GetLabelAfterPermanentErrorTimeout) {
+  smart_lock_model_->NotifySmartLockAuthResult(/*result=*/false);
+  EXPECT_TRUE(on_state_changed_called_);
+  EXPECT_EQ(AuthFactorState::kErrorPermanent, model_->GetAuthFactorState());
+  EXPECT_EQ(IDS_AUTH_FACTOR_LABEL_CANNOT_UNLOCK, model_->GetLabelId());
+  model_->HandleErrorTimeout();
+  EXPECT_EQ(IDS_AUTH_FACTOR_LABEL_PASSWORD_REQUIRED, model_->GetLabelId());
+}
+
 }  // namespace ash
diff --git a/ash/metrics/demo_session_metrics_recorder.cc b/ash/metrics/demo_session_metrics_recorder.cc
index a288e60..61c17eae 100644
--- a/ash/metrics/demo_session_metrics_recorder.cc
+++ b/ash/metrics/demo_session_metrics_recorder.cc
@@ -18,6 +18,7 @@
 #include "base/scoped_multi_source_observation.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "components/app_constants/constants.h"
 #include "extensions/common/constants.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/window_types.h"
@@ -59,7 +60,7 @@
     return DemoModeApp::kScreensaver;
   }
 
-  if (app_id == extension_misc::kChromeAppId)
+  if (app_id == app_constants::kChromeAppId)
     return DemoModeApp::kBrowser;
   if (app_id == extension_misc::kFilesManagerAppId)
     return DemoModeApp::kFiles;
@@ -187,7 +188,7 @@
   std::string app_id = GetShelfID(window).app_id;
 
   // The Chrome "app" in the shelf is just the browser.
-  if (app_id == extension_misc::kChromeAppId)
+  if (app_id == app_constants::kChromeAppId)
     return DemoModeApp::kBrowser;
 
   // If the window is the "browser" type, having an app ID other than the
diff --git a/ash/metrics/demo_session_metrics_recorder_unittest.cc b/ash/metrics/demo_session_metrics_recorder_unittest.cc
index ce71d9cf..b830ecb6 100644
--- a/ash/metrics/demo_session_metrics_recorder_unittest.cc
+++ b/ash/metrics/demo_session_metrics_recorder_unittest.cc
@@ -15,6 +15,7 @@
 #include "ash/wm/window_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/timer/mock_timer.h"
+#include "components/app_constants/constants.h"
 #include "extensions/common/constants.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/window_types.h"
@@ -517,7 +518,7 @@
   wm::ActivateWindow(chrome_app_window.get());
 
   std::unique_ptr<aura::Window> chrome_browser_window =
-      CreateChromeAppWindow(extension_misc::kChromeAppId);
+      CreateChromeAppWindow(app_constants::kChromeAppId);
   wm::ActivateWindow(chrome_browser_window.get());
   wm::DeactivateWindow(chrome_browser_window.get());
   wm::ActivateWindow(chrome_browser_window.get());
@@ -601,7 +602,7 @@
 
   // Chrome browser window
   std::unique_ptr<aura::Window> chrome_browser_window =
-      CreateChromeAppWindow(extension_misc::kChromeAppId);
+      CreateChromeAppWindow(app_constants::kChromeAppId);
   wm::ActivateWindow(chrome_browser_window.get());
   wm::DeactivateWindow(chrome_browser_window.get());
   wm::ActivateWindow(chrome_browser_window.get());
diff --git a/ash/public/cpp/test/app_list_test_api.h b/ash/public/cpp/test/app_list_test_api.h
index cdaf640..3aecf33 100644
--- a/ash/public/cpp/test/app_list_test_api.h
+++ b/ash/public/cpp/test/app_list_test_api.h
@@ -32,13 +32,14 @@
   AppListModel* GetAppListModel();
 
   // Waits for the bubble launcher window to open on the primary display.
-  // `wait_for_opening_animation` indicates whether to wait for the window
-  // opening animation. See AppListBubblePresenter::Show(). Only used with
-  // productivity launcher in clamshell mode.
+  // `wait_for_opening_animation` indicates whether to wait for the bubble
+  // launcher show animations (including the app list window animation, the
+  // bubble apps page animation, the bubble view animation and apps grid
+  // animation). Only used with productivity launcher in clamshell mode.
   void WaitForBubbleWindow(bool wait_for_opening_animation);
 
-  // Waits until the animation to show the app list becomes idle. No operations
-  // if the app list widget is already idle.
+  // Waits until all the animations to show the app list become idle. No
+  // operations if the app list is already idle.
   void WaitForAppListShowAnimation(bool is_bubble_window);
 
   // Returns whether there is an item for |app_id|.
diff --git a/ash/wm/desks/templates/desks_templates_icon_container.cc b/ash/wm/desks/templates/desks_templates_icon_container.cc
index 796c0fd..cc3d7e6 100644
--- a/ash/wm/desks/templates/desks_templates_icon_container.cc
+++ b/ash/wm/desks/templates/desks_templates_icon_container.cc
@@ -12,9 +12,9 @@
 #include "ash/style/ash_color_provider.h"
 #include "ash/wm/desks/templates/desks_templates_icon_view.h"
 #include "base/containers/contains.h"
+#include "components/app_constants/constants.h"
 #include "components/app_restore/app_launch_info.h"
 #include "components/app_restore/app_restore_utils.h"
-#include "extensions/common/constants.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/color/color_provider.h"
@@ -93,7 +93,7 @@
     // id so to determine whether `restore_data` is an SWA we need to check
     // whether it's a browser.
     const bool is_browser =
-        app_id == extension_misc::kChromeAppId &&
+        app_id == app_constants::kChromeAppId &&
         (!restore_data.second->app_type_browser.has_value() ||
          !restore_data.second->app_type_browser.value());
     const int activation_index = restore_data.second->activation_index.value();
@@ -115,7 +115,7 @@
       // their app id from their app name if possible.
       std::string new_app_id = app_id;
       absl::optional<std::string> app_name = restore_data.second->app_name;
-      if (app_id == extension_misc::kChromeAppId && app_name.has_value())
+      if (app_id == app_constants::kChromeAppId && app_name.has_value())
         new_app_id = app_restore::GetAppIdFromAppName(app_name.value());
 
       InsertIdentifierInfo(new_app_id, activation_index, out_identifier_info);
diff --git a/ash/wm/desks/templates/desks_templates_metrics_util.cc b/ash/wm/desks/templates/desks_templates_metrics_util.cc
index d9d5dbb..0597b86 100644
--- a/ash/wm/desks/templates/desks_templates_metrics_util.cc
+++ b/ash/wm/desks/templates/desks_templates_metrics_util.cc
@@ -5,9 +5,9 @@
 #include "ash/wm/desks/templates/desks_templates_metrics_util.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "components/app_constants/constants.h"
 #include "components/app_restore/restore_data.h"
 #include "components/desks_storage/core/desk_model.h"
-#include "extensions/common/constants.h"
 
 namespace ash {
 
@@ -52,7 +52,7 @@
   for (const auto& iter : launch_list) {
     // Since apps aren't guaranteed to have the url field set up correctly, this
     // is necessary to ensure things are not double-counted.
-    if (iter.first != extension_misc::kChromeAppId) {
+    if (iter.first != app_constants::kChromeAppId) {
       ++window_count;
       ++total_count;
       continue;
diff --git a/ash/wm/desks/templates/desks_templates_unittest.cc b/ash/wm/desks/templates/desks_templates_unittest.cc
index 045c0d7..2b74268e 100644
--- a/ash/wm/desks/templates/desks_templates_unittest.cc
+++ b/ash/wm/desks/templates/desks_templates_unittest.cc
@@ -49,12 +49,12 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
+#include "components/app_constants/constants.h"
 #include "components/app_restore/app_launch_info.h"
 #include "components/app_restore/full_restore_utils.h"
 #include "components/app_restore/window_info.h"
 #include "components/app_restore/window_properties.h"
 #include "components/prefs/pref_service.h"
-#include "extensions/common/constants.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
@@ -926,13 +926,13 @@
 // Tests that icons are ordered such that active tabs and windows are ordered
 // before inactive tabs.
 TEST_F(DesksTemplatesTest, IconsOrderWithInactiveTabs) {
-  const std::string kAppId1 = extension_misc::kChromeAppId;
+  const std::string kAppId1 = app_constants::kChromeAppId;
   constexpr int kWindowId1 = 1;
   constexpr int kActiveTabIndex1 = 1;
   const std::vector<GURL> kTabs1{GURL("http://a.com"), GURL("http://b.com"),
                                  GURL("http://c.com")};
 
-  const std::string kAppId2 = extension_misc::kChromeAppId;
+  const std::string kAppId2 = app_constants::kChromeAppId;
   constexpr int kWindowId2 = 2;
   constexpr int kActiveTabIndex2 = 2;
   const std::vector<GURL> kTabs2{GURL("http://d.com"), GURL("http://e.com"),
@@ -2185,13 +2185,13 @@
 // Tests that the window and tab counts are properly recorded in their
 // resepctive metrics.
 TEST_F(DesksTemplatesTest, SaveDeskRecordsWindowAndTabCountMetrics) {
-  const std::string kAppId1 = extension_misc::kChromeAppId;
+  const std::string kAppId1 = app_constants::kChromeAppId;
   constexpr int kWindowId1 = 1;
   constexpr int kActiveTabIndex1 = 1;
   const std::vector<GURL> kTabs1{GURL("http://a.com"), GURL("http://b.com"),
                                  GURL("http://c.com")};
 
-  const std::string kAppId2 = extension_misc::kChromeAppId;
+  const std::string kAppId2 = app_constants::kChromeAppId;
   constexpr int kWindowId2 = 2;
   constexpr int kActiveTabIndex2 = 2;
   const std::vector<GURL> kTabs2{GURL("http://d.com"), GURL("http://e.com"),
diff --git a/base/BUILD.gn b/base/BUILD.gn
index d39a293..c464d7f 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -3783,16 +3783,9 @@
       "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
     ]
 
-    # TODO(crbug.com/1256502): Switch back to CFv2 and delete the .test-cmx once
-    # the bug is fixed.
-    use_cfv2 = false
-    if (use_cfv2) {
-      additional_manifest_fragments =
-          [ "//build/config/fuchsia/test/logger.shard.test-cml" ]
-    } else {
-      additional_manifest_fragments =
-          [ "//build/config/fuchsia/test/test_logger_capabilities.test-cmx" ]
-    }
+    use_cfv2 = true
+    additional_manifest_fragments =
+        [ "//build/config/fuchsia/test/logger.shard.test-cml" ]
   }
 
   if (!is_fuchsia && !is_ios) {
@@ -4423,6 +4416,7 @@
       "android/junit/src/org/chromium/base/NonThreadSafeTest.java",
       "android/junit/src/org/chromium/base/PiiEliderTest.java",
       "android/junit/src/org/chromium/base/PromiseTest.java",
+      "android/junit/src/org/chromium/base/TraceEventTest.java",
       "android/junit/src/org/chromium/base/UnownedUserDataHostTest.java",
       "android/junit/src/org/chromium/base/UnownedUserDataKeyTest.java",
       "android/junit/src/org/chromium/base/jank_tracker/FrameMetricsListenerTest.java",
diff --git a/base/android/java/src/org/chromium/base/TraceEvent.java b/base/android/java/src/org/chromium/base/TraceEvent.java
index 14aa874..f278273 100644
--- a/base/android/java/src/org/chromium/base/TraceEvent.java
+++ b/base/android/java/src/org/chromium/base/TraceEvent.java
@@ -17,6 +17,7 @@
 import androidx.annotation.AnyThread;
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
+import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
@@ -48,6 +49,7 @@
     private static volatile boolean sEnabled; // True when tracing into Chrome's tracing service.
     private static AtomicBoolean sNativeTracingReady = new AtomicBoolean();
     private static AtomicBoolean sUiThreadReady = new AtomicBoolean();
+    private static boolean sEventNameFilteringEnabled;
 
     // Trace tags replicated from android.os.Trace.
     public static final long ATRACE_TAG_WEBVIEW = 1L << 4;
@@ -381,8 +383,12 @@
 
     private static ATrace sATrace;
 
-    private static class BasicLooperMonitor implements Printer {
-        private static final String LOOPER_TASK_PREFIX = "Looper.dispatch: ";
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    static class BasicLooperMonitor implements Printer {
+        @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+        static final String LOOPER_TASK_PREFIX = "Looper.dispatch: ";
+        @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+        static final String FILTERED_EVENT_NAME = LOOPER_TASK_PREFIX + "EVENT_NAME_FILTERED";
         private static final int SHORTEST_LOG_PREFIX_LENGTH = "<<<<< Finished to ".length();
         private String mCurrentTarget;
 
@@ -424,7 +430,11 @@
             mCurrentTarget = null;
         }
 
-        private static String getTraceEventName(String line) {
+        @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+        static String getTraceEventName(String line) {
+            if (sEventNameFilteringEnabled) {
+                return FILTERED_EVENT_NAME;
+            }
             return LOOPER_TASK_PREFIX + getTarget(line) + "(" + getTargetName(line) + ")";
         }
 
@@ -636,6 +646,14 @@
         }
     }
 
+    public static void setEventNameFilteringEnabled(boolean enabled) {
+        sEventNameFilteringEnabled = enabled;
+    }
+
+    public static boolean eventNameFilteringEnabled() {
+        return sEventNameFilteringEnabled;
+    }
+
     /**
      * May enable early tracing depending on the environment.
      *
diff --git a/base/android/junit/src/org/chromium/base/TraceEventTest.java b/base/android/junit/src/org/chromium/base/TraceEventTest.java
new file mode 100644
index 0000000..bcb30b7
--- /dev/null
+++ b/base/android/junit/src/org/chromium/base/TraceEventTest.java
@@ -0,0 +1,69 @@
+// Copyright 2022 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.base;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.Feature;
+
+/**
+ * Tests for {@link TraceEvent}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+public class TraceEventTest {
+    @Test
+    @SmallTest
+    @Feature({"Android-AppBase"})
+    public void testDisableEventNameFiltering() {
+        TraceEvent.setEventNameFilteringEnabled(false);
+        Assert.assertFalse(TraceEvent.eventNameFilteringEnabled());
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"Android-AppBase"})
+    public void testEnableEventNameFiltering() {
+        TraceEvent.setEventNameFilteringEnabled(true);
+        Assert.assertTrue(TraceEvent.eventNameFilteringEnabled());
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"Android-AppBase"})
+    public void testEventNameUnfiltered() {
+        TraceEvent.setEventNameFilteringEnabled(false);
+        Assert.assertFalse(TraceEvent.eventNameFilteringEnabled());
+
+        // Input string format:
+        // ">>>>> Finished to (TARGET) {HASH_CODE} TARGET_NAME: WHAT"
+        String realEventName = ">>>>> Finished to (org.chromium.myClass.myMethod) "
+                + "{HASH_CODE} org.chromium.myOtherClass.instance: message";
+
+        // Output string format:
+        // "{TraceEvent.BasicLooperMonitor.LOOPER_TASK_PREFIX} TARGET(TARGET_NAME)"
+        String realEventNameExpected = TraceEvent.BasicLooperMonitor.LOOPER_TASK_PREFIX
+                + "org.chromium.myClass.myMethod(org.chromium.myOtherClass.instance)";
+        Assert.assertEquals(TraceEvent.BasicLooperMonitor.getTraceEventName(realEventName),
+                realEventNameExpected);
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"Android-AppBase"})
+    public void testEventNameFiltered() {
+        TraceEvent.setEventNameFilteringEnabled(true);
+        Assert.assertTrue(TraceEvent.eventNameFilteringEnabled());
+
+        String realEventName = TraceEvent.BasicLooperMonitor.LOOPER_TASK_PREFIX
+                + "org.chromium.myClass.myMethod(org.chromium.myOtherClass.instance)";
+        Assert.assertEquals(TraceEvent.BasicLooperMonitor.getTraceEventName(realEventName),
+                TraceEvent.BasicLooperMonitor.FILTERED_EVENT_NAME);
+    }
+}
\ No newline at end of file
diff --git a/base/fuchsia/test_component_context_for_process_unittest.cc b/base/fuchsia/test_component_context_for_process_unittest.cc
index 1de931a..7d83eb61 100644
--- a/base/fuchsia/test_component_context_for_process_unittest.cc
+++ b/base/fuchsia/test_component_context_for_process_unittest.cc
@@ -110,9 +110,8 @@
   // Use the Loader to verify that it was the system service that was connected.
   // Load the component containing this test since we know it exists.
   // TODO(https://fxbug.dev/51490): Use a programmatic mechanism to obtain this.
-  // TODO(crbug.com/1256502): Switch back to `.cm` once the bug is fixed.
   const char kComponentUrl[] =
-      "fuchsia-pkg://fuchsia.com/base_unittests#meta/base_unittests.cmx";
+      "fuchsia-pkg://fuchsia.com/base_unittests#meta/base_unittests.cm";
   loader->LoadUrl(kComponentUrl, [quit_loop = wait_loop.QuitClosure(),
                                   expected_path = kComponentUrl](
                                      ::fuchsia::sys::PackagePtr package) {
diff --git a/base/pending_task.cc b/base/pending_task.cc
index 9221c02..6fae760 100644
--- a/base/pending_task.cc
+++ b/base/pending_task.cc
@@ -27,24 +27,6 @@
 
 PendingTask& PendingTask::operator=(PendingTask&& other) = default;
 
-bool PendingTask::operator>(const PendingTask& other) const {
-  if (delayed_run_time != other.delayed_run_time)
-    return delayed_run_time > other.delayed_run_time;
-
-  // If the times happen to match, then we use the sequence number to decide.
-  // Compare the difference to support integer roll-over.
-  return (sequence_num - other.sequence_num) > 0;
-}
-
-bool PendingTask::operator<(const PendingTask& other) const {
-  if (delayed_run_time != other.delayed_run_time)
-    return delayed_run_time < other.delayed_run_time;
-
-  // If the times happen to match, then we use the sequence number to decide.
-  // Compare the difference to support integer roll-over.
-  return (sequence_num - other.sequence_num) < 0;
-}
-
 TimeTicks PendingTask::GetDesiredExecutionTime() const {
   if (!delayed_run_time.is_null())
     return delayed_run_time;
diff --git a/base/pending_task.h b/base/pending_task.h
index 59345917..d023bc101 100644
--- a/base/pending_task.h
+++ b/base/pending_task.h
@@ -33,12 +33,6 @@
 
   PendingTask& operator=(PendingTask&& other);
 
-  // Used for a min-heap.
-  bool operator>(const PendingTask& other) const;
-
-  // Used for sorting.
-  bool operator<(const PendingTask& other) const;
-
   // Returns the time at which this task should run. This is |delayed_run_time|
   // for a delayed task, |queue_time| otherwise.
   base::TimeTicks GetDesiredExecutionTime() const;
diff --git a/base/task/sequence_manager/sequence_manager.h b/base/task/sequence_manager/sequence_manager.h
index 4581f56a..e08e8998 100644
--- a/base/task/sequence_manager/sequence_manager.h
+++ b/base/task/sequence_manager/sequence_manager.h
@@ -178,9 +178,9 @@
   virtual TimeTicks NowTicks() const = 0;
 
   // Returns a wake-up for the next delayed task which is not ripe for
-  // execution. If there are no such tasks (immediate tasks don't count), it
+  // execution. If there are no such tasks (immediate tasks don't count),
   // returns nullopt.
-  virtual absl::optional<WakeUp> GetNextWakeUp() const = 0;
+  virtual absl::optional<WakeUp> GetNextDelayedWakeUp() const = 0;
 
   // Sets the SingleThreadTaskRunner that will be returned by
   // ThreadTaskRunnerHandle::Get on the main thread.
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc
index 10446d8..bb6ecd3 100644
--- a/base/task/sequence_manager/sequence_manager_impl.cc
+++ b/base/task/sequence_manager/sequence_manager_impl.cc
@@ -28,6 +28,7 @@
 #include "base/task/sequence_manager/wake_up_queue.h"
 #include "base/task/sequence_manager/work_queue.h"
 #include "base/task/sequence_manager/work_queue_sets.h"
+#include "base/task/task_features.h"
 #include "base/threading/thread_id_name_manager.h"
 #include "base/threading/thread_local.h"
 #include "base/time/default_tick_clock.h"
@@ -150,6 +151,7 @@
 // Note: An atomic is used here because some tests can initialize two different
 //       sequence managers on different threads (e.g. by using base::Thread).
 std::atomic_bool g_no_wake_ups_for_canceled_tasks{false};
+std::atomic<TimeDelta> g_task_leeway{WakeUp::kDefaultLeeway};
 
 }  // namespace
 
@@ -321,6 +323,7 @@
 void SequenceManagerImpl::InitializeFeatures() {
   ApplyNoWakeUpsForCanceledTasks();
   TaskQueueImpl::InitializeFeatures();
+  g_task_leeway.store(kTaskLeewayParam.Get(), std::memory_order_relaxed);
 }
 
 // static
@@ -528,11 +531,11 @@
 
 void SequenceManagerImpl::SetNextWakeUp(LazyNow* lazy_now,
                                         absl::optional<WakeUp> wake_up) {
-  TimeTicks wake_up_time = AdjustWakeUp(wake_up, lazy_now);
-  if (wake_up_time.is_null()) {
+  auto next_wake_up = AdjustWakeUp(wake_up, lazy_now);
+  if (next_wake_up && next_wake_up->is_immediate()) {
     ScheduleWork();
   } else {
-    controller_->SetNextDelayedDoWork(lazy_now, wake_up_time);
+    controller_->SetNextDelayedDoWork(lazy_now, next_wake_up);
   }
 }
 
@@ -743,8 +746,9 @@
           lazy_now);
 }
 
-TimeTicks SequenceManagerImpl::GetNextTaskTime(LazyNow* lazy_now,
-                                               SelectTaskOption option) const {
+absl::optional<WakeUp> SequenceManagerImpl::GetPendingWakeUp(
+    LazyNow* lazy_now,
+    SelectTaskOption option) const {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
 
   if (auto priority =
@@ -753,8 +757,8 @@
     // work to be done. However we may want to yield to native work if it is
     // more important.
     if (UNLIKELY(!ShouldRunTaskOfPriority(*priority)))
-      return AdjustWakeUp(GetNextWakeUpWithOption(option), lazy_now);
-    return TimeTicks();
+      return AdjustWakeUp(GetNextDelayedWakeUpWithOption(option), lazy_now);
+    return WakeUp{};
   }
 
   // There may be some incoming immediate work which we haven't accounted for.
@@ -765,47 +769,52 @@
   if (auto priority =
           main_thread_only().selector.GetHighestPendingPriority(option)) {
     if (UNLIKELY(!ShouldRunTaskOfPriority(*priority)))
-      return AdjustWakeUp(GetNextWakeUpWithOption(option), lazy_now);
-    return TimeTicks();
+      return AdjustWakeUp(GetNextDelayedWakeUpWithOption(option), lazy_now);
+    return WakeUp{};
   }
 
   // Otherwise we need to find the shortest delay, if any.  NB we don't need to
   // call MoveReadyDelayedTasksToWorkQueues because it's assumed
   // DelayTillNextTask will return TimeDelta>() if the delayed task is due to
   // run now.
-  return AdjustWakeUp(GetNextWakeUpWithOption(option), lazy_now);
+  return AdjustWakeUp(GetNextDelayedWakeUpWithOption(option), lazy_now);
 }
 
-absl::optional<WakeUp> SequenceManagerImpl::GetNextWakeUp() const {
+absl::optional<WakeUp> SequenceManagerImpl::GetNextDelayedWakeUp() const {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
-
-  return main_thread_only().wake_up_queue->GetNextWakeUp();
+  return main_thread_only().wake_up_queue->GetNextDelayedWakeUp();
 }
 
-absl::optional<WakeUp> SequenceManagerImpl::GetNextWakeUpWithOption(
+absl::optional<WakeUp> SequenceManagerImpl::GetNextDelayedWakeUpWithOption(
     SelectTaskOption option) const {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
 
   if (option == SelectTaskOption::kSkipDelayedTask)
     return absl::nullopt;
-  return GetNextWakeUp();
+  return GetNextDelayedWakeUp();
 }
 
-TimeTicks SequenceManagerImpl::AdjustWakeUp(absl::optional<WakeUp> wake_up,
-                                            LazyNow* lazy_now) const {
+absl::optional<WakeUp> SequenceManagerImpl::AdjustWakeUp(
+    absl::optional<WakeUp> wake_up,
+    LazyNow* lazy_now) const {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
   if (!wake_up)
-    return TimeTicks::Max();
+    return absl::nullopt;
   // Overdue work needs to be run immediately.
-  if (lazy_now->Now() >= wake_up->time)
-    return TimeTicks();
+  if (lazy_now->Now() >= wake_up->earliest_time())
+    return WakeUp{};
   // If |time_domain| is present, we don't want an actual OS level delayed wake
   // up scheduled, so pretend we have no more work. This will result in
   // appearing idle and |time_domain| will decide what to do in
   // MaybeFastForwardToWakeUp().
   if (main_thread_only().time_domain)
-    return TimeTicks::Max();
-  return wake_up->time;
+    return absl::nullopt;
+  return *wake_up;
+}
+
+void SequenceManagerImpl::MaybeAddLeewayToTask(Task& task) const {
+  if (!main_thread_only().time_domain)
+    task.leeway = g_task_leeway.load(std::memory_order_relaxed);
 }
 
 bool SequenceManagerImpl::HasPendingHighResolutionTasks() {
@@ -815,7 +824,7 @@
 }
 
 bool SequenceManagerImpl::OnSystemIdle() {
-  auto wakeup = main_thread_only().wake_up_queue->GetNextWakeUp();
+  auto wakeup = main_thread_only().wake_up_queue->GetNextDelayedWakeUp();
   bool have_work_to_do = false;
   if (main_thread_only().time_domain) {
     have_work_to_do = main_thread_only().time_domain->MaybeFastForwardToWakeUp(
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h
index 9dab16c4..70128f0 100644
--- a/base/task/sequence_manager/sequence_manager_impl.h
+++ b/base/task/sequence_manager/sequence_manager_impl.h
@@ -143,14 +143,14 @@
   void PrioritizeYieldingToNative(base::TimeTicks prioritize_until) override;
   void AddTaskObserver(TaskObserver* task_observer) override;
   void RemoveTaskObserver(TaskObserver* task_observer) override;
-  absl::optional<WakeUp> GetNextWakeUp() const override;
+  absl::optional<WakeUp> GetNextDelayedWakeUp() const override;
 
   // SequencedTaskSource implementation:
   absl::optional<SelectedTask> SelectNextTask(
       SelectTaskOption option = SelectTaskOption::kDefault) override;
   void DidRunTask() override;
   void RemoveAllCanceledDelayedTasksFromFront(LazyNow* lazy_now) override;
-  TimeTicks GetNextTaskTime(
+  absl::optional<WakeUp> GetPendingWakeUp(
       LazyNow* lazy_now,
       SelectTaskOption option = SelectTaskOption::kDefault) const override;
   bool HasPendingHighResolutionTasks() override;
@@ -359,8 +359,10 @@
   // metadata to |pending_task| before it is moved into the queue.
   void WillQueueTask(Task* pending_task, const char* task_queue_name);
 
-  // Delayed Tasks with run_times <= Now() are enqueued onto the work queue and
-  // reloads any empty work queues.
+  // Enqueues onto delayed WorkQueues all delayed tasks which must run now
+  // (cannot be postponed) and possibly some delayed tasks which can run now but
+  // could be postponed (due to how tasks are stored, it is not possible to
+  // retrieve all such tasks efficiently) and reloads any empty work queues.
   void MoveReadyDelayedTasksToWorkQueues(LazyNow* lazy_now);
 
   void NotifyWillProcessTask(ExecutingTask* task, LazyNow* time_before_task);
@@ -419,14 +421,17 @@
   // Returns a wake-up for the next delayed task which is not ripe for
   // execution, or nullopt if `option` is `kSkipDelayedTask` or there
   // are no such tasks (immediate tasks don't count).
-  absl::optional<WakeUp> GetNextWakeUpWithOption(SelectTaskOption option) const;
+  absl::optional<WakeUp> GetNextDelayedWakeUpWithOption(
+      SelectTaskOption option) const;
 
   // Given a `wake_up` describing when the next delayed task should run, returns
-  // the time at which the thread should wake up. is_immediate() if the next
-  // task can run immediately, or nullopt if there are no delayed tasks or a
-  // `time_domain` is used.
-  TimeTicks AdjustWakeUp(absl::optional<WakeUp> wake_up,
-                         LazyNow* lazy_now) const;
+  // a wake up that should be scheduled on the thread. `is_immediate()` if the
+  // wake up should run immediately. `nullopt` if no wake up is required because
+  // `wake_up` is `nullopt` or a `time_domain` is used.
+  absl::optional<WakeUp> AdjustWakeUp(absl::optional<WakeUp> wake_up,
+                                      LazyNow* lazy_now) const;
+
+  void MaybeAddLeewayToTask(Task& task) const;
 
 #if DCHECK_IS_ON()
   void LogTaskDebugInfo(const internal::WorkQueue* work_queue) const;
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
index 49e75e0..1988ed82 100644
--- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc
+++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -103,6 +103,8 @@
   *os << ToString(type);
 }
 
+constexpr TimeDelta kLeeway = sequence_manager::WakeUp::kDefaultLeeway;
+
 using MockTask = MockCallback<base::RepeatingCallback<void()>>;
 
 // This class abstracts the details of how the SequenceManager runs tasks.
@@ -343,7 +345,7 @@
       // Advance time if we've run out of immediate work to do.
       if (!sequence_manager()->HasImmediateWork()) {
         LazyNow lazy_now(mock_tick_clock());
-        auto wake_up = sequence_manager()->GetNextWakeUp();
+        auto wake_up = sequence_manager()->GetNextDelayedWakeUp();
         if (wake_up.has_value()) {
           AdvanceMockTickClock(wake_up->time - lazy_now.Now());
           per_run_time_callback.Run();
@@ -852,6 +854,68 @@
   EXPECT_FALSE(queue->HasTaskToRunImmediatelyOrReadyDelayedTask());
 }
 
+TEST_P(SequenceManagerTest, DelayedTaskAtPosting_FlexiblePreferEarly) {
+  auto queue = CreateTaskQueue();
+
+  TimeTicks start_time = sequence_manager()->NowTicks();
+  std::vector<EnqueueOrder> run_order;
+  constexpr TimeDelta kDelay(Milliseconds(10));
+  auto handle = queue->task_runner()->PostCancelableDelayedTaskAt(
+      subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
+      BindOnce(&TestTask, 1, &run_order),
+      sequence_manager()->NowTicks() + kDelay,
+      subtle::DelayPolicy::kFlexiblePreferEarly);
+  EXPECT_EQ(kDelay, NextPendingTaskDelay());
+  EXPECT_FALSE(queue->HasTaskToRunImmediatelyOrReadyDelayedTask());
+  EXPECT_TRUE(run_order.empty());
+  LazyNow lazy_now(mock_tick_clock());
+  EXPECT_EQ((WakeUp{start_time + kDelay, kLeeway, WakeUpResolution::kLow,
+                    subtle::DelayPolicy::kFlexiblePreferEarly}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
+
+  // The task doesn't run before the delay has completed.
+  FastForwardBy(kDelay - WakeUp::kDefaultLeeway - Milliseconds(1));
+  EXPECT_TRUE(run_order.empty());
+
+  // After the delay has completed, the task runs normally.
+  FastForwardBy(WakeUp::kDefaultLeeway + Milliseconds(1));
+  EXPECT_THAT(run_order, ElementsAre(1u));
+  EXPECT_FALSE(queue->HasTaskToRunImmediatelyOrReadyDelayedTask());
+}
+
+TEST_P(SequenceManagerTest, DelayedTaskAtPosting_MixedDelayPolicy) {
+  auto queue = CreateTaskQueue();
+
+  TimeTicks start_time = sequence_manager()->NowTicks();
+  std::vector<EnqueueOrder> run_order;
+  auto handle1 = queue->task_runner()->PostCancelableDelayedTaskAt(
+      subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
+      BindOnce(&TestTask, 2, &run_order),
+      sequence_manager()->NowTicks() + Milliseconds(8),
+      subtle::DelayPolicy::kFlexibleNoSooner);
+  auto handle2 = queue->task_runner()->PostCancelableDelayedTaskAt(
+      subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
+      BindOnce(&TestTask, 1, &run_order),
+      sequence_manager()->NowTicks() + Milliseconds(10),
+      subtle::DelayPolicy::kPrecise);
+  EXPECT_EQ(Milliseconds(10), NextPendingTaskDelay());
+  EXPECT_FALSE(queue->HasTaskToRunImmediatelyOrReadyDelayedTask());
+  EXPECT_TRUE(run_order.empty());
+  LazyNow lazy_now(mock_tick_clock());
+  EXPECT_EQ((WakeUp{start_time + Milliseconds(10), kLeeway,
+                    WakeUpResolution::kLow, subtle::DelayPolicy::kPrecise}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
+
+  // The task doesn't run before the delay has completed.
+  FastForwardBy(Milliseconds(10) - Milliseconds(1));
+  EXPECT_TRUE(run_order.empty());
+
+  // After the delay has completed, the task runs normally.
+  FastForwardBy(Milliseconds(1));
+  EXPECT_THAT(run_order, ElementsAre(1u, 2u));
+  EXPECT_FALSE(queue->HasTaskToRunImmediatelyOrReadyDelayedTask());
+}
+
 TEST_P(SequenceManagerTest, DelayedTaskAtPosting_Immediate) {
   auto queue = CreateTaskQueue();
 
@@ -1777,47 +1841,47 @@
   EXPECT_TRUE(queue->task_runner()->RunsTasksInCurrentSequence());
 }
 
-TEST_P(SequenceManagerTest, GetNextWakeUp) {
+TEST_P(SequenceManagerTest, GetNextDelayedWakeUp) {
   auto queues = CreateTaskQueues(2u);
   AdvanceMockTickClock(Microseconds(10000));
   LazyNow lazy_now_1(mock_tick_clock());
 
   // With no delayed tasks.
-  EXPECT_FALSE(sequence_manager()->GetNextWakeUp());
+  EXPECT_FALSE(sequence_manager()->GetNextDelayedWakeUp());
 
   // With a non-delayed task.
   queues[0]->task_runner()->PostTask(FROM_HERE, BindOnce(&NopTask));
-  EXPECT_FALSE(sequence_manager()->GetNextWakeUp());
+  EXPECT_FALSE(sequence_manager()->GetNextDelayedWakeUp());
 
   // With a delayed task.
   TimeDelta expected_delay = Milliseconds(50);
   queues[0]->task_runner()->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
                                             expected_delay);
   EXPECT_EQ(lazy_now_1.Now() + expected_delay,
-            sequence_manager()->GetNextWakeUp()->time);
+            sequence_manager()->GetNextDelayedWakeUp()->time);
 
   // With another delayed task in the same queue with a longer delay.
   queues[0]->task_runner()->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
                                             Milliseconds(100));
   EXPECT_EQ(lazy_now_1.Now() + expected_delay,
-            sequence_manager()->GetNextWakeUp()->time);
+            sequence_manager()->GetNextDelayedWakeUp()->time);
 
   // With another delayed task in the same queue with a shorter delay.
   expected_delay = Milliseconds(20);
   queues[0]->task_runner()->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
                                             expected_delay);
   EXPECT_EQ(lazy_now_1.Now() + expected_delay,
-            sequence_manager()->GetNextWakeUp()->time);
+            sequence_manager()->GetNextDelayedWakeUp()->time);
 
   // With another delayed task in a different queue with a shorter delay.
   expected_delay = Milliseconds(10);
   queues[1]->task_runner()->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
                                             expected_delay);
   EXPECT_EQ(lazy_now_1.Now() + expected_delay,
-            sequence_manager()->GetNextWakeUp()->time);
+            sequence_manager()->GetNextDelayedWakeUp()->time);
 }
 
-TEST_P(SequenceManagerTest, GetNextWakeUp_MultipleQueues) {
+TEST_P(SequenceManagerTest, GetNextDelayedWakeUp_MultipleQueues) {
   auto queues = CreateTaskQueues(3u);
 
   TimeDelta delay1 = Milliseconds(50);
@@ -1832,7 +1896,8 @@
   queues[0]->task_runner()->PostTask(FROM_HERE, BindOnce(&NopTask));
 
   LazyNow lazy_now(mock_tick_clock());
-  EXPECT_EQ(lazy_now.Now() + delay2, sequence_manager()->GetNextWakeUp()->time);
+  EXPECT_EQ(lazy_now.Now() + delay2,
+            sequence_manager()->GetNextDelayedWakeUp()->time);
 }
 
 TEST(SequenceManagerWithTaskRunnerTest, DeleteSequenceManagerInsideATask) {
@@ -2270,12 +2335,12 @@
   queue->task_runner()->PostDelayedTask(
       FROM_HERE, BindOnce(&TestTask, 1, &run_order), Milliseconds(10));
   LazyNow lazy_now1(domain.get());
-  EXPECT_EQ(TimeTicks::Max(), sequence_manager()->GetNextTaskTime(&lazy_now1));
+  EXPECT_EQ(absl::nullopt, sequence_manager()->GetPendingWakeUp(&lazy_now1));
   EXPECT_EQ(TimeDelta::Max(), NextPendingTaskDelay());
 
   domain->SetNowTicks(sequence_manager()->NowTicks() + Milliseconds(10));
   LazyNow lazy_now2(domain.get());
-  EXPECT_EQ(TimeTicks(), sequence_manager()->GetNextTaskTime(&lazy_now2));
+  EXPECT_EQ(WakeUp{}, sequence_manager()->GetPendingWakeUp(&lazy_now2));
 
   queue->ShutdownTaskQueue();
 }
@@ -2478,13 +2543,13 @@
   Mock::VerifyAndClearExpectations(&throttler);
   // Expect throttled wake up.
   LazyNow lazy_now(mock_tick_clock());
-  EXPECT_EQ(start_time + delay10s,
-            sequence_manager()->GetNextTaskTime(&lazy_now));
+  WakeUp expected_wake_up{start_time + delay10s};
+  EXPECT_EQ(expected_wake_up, sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   queue->ResetThrottler();
   // Next wake up should be back to normal.
-  EXPECT_EQ(start_time + delay1s,
-            sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ((WakeUp{start_time + delay1s, kLeeway}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   // Tidy up.
   queue->ShutdownTaskQueue();
@@ -3370,10 +3435,10 @@
   auto queue = CreateTaskQueue();
   constexpr TimeDelta kDelay(Milliseconds(10));
   LazyNow lazy_now(mock_tick_clock());
-  EXPECT_EQ(TimeTicks::Max(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(absl::nullopt, sequence_manager()->GetPendingWakeUp(&lazy_now));
   EXPECT_EQ(
-      TimeTicks::Max(),
-      sequence_manager()->GetNextTaskTime(
+      absl::nullopt,
+      sequence_manager()->GetPendingWakeUp(
           &lazy_now, SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
 
   queue->task_runner()->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), kDelay);
@@ -3384,11 +3449,11 @@
   EXPECT_FALSE(sequence_manager()->SelectNextTask(
       SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
 
-  EXPECT_EQ(lazy_now.Now() + kDelay,
-            sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ((WakeUp{lazy_now.Now() + kDelay, kLeeway}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
   EXPECT_EQ(
-      TimeTicks::Max(),
-      sequence_manager()->GetNextTaskTime(
+      absl::nullopt,
+      sequence_manager()->GetPendingWakeUp(
           &lazy_now, SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
 
   AdvanceMockTickClock(kDelay);
@@ -3399,15 +3464,15 @@
   EXPECT_FALSE(sequence_manager()->SelectNextTask(
       SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
   EXPECT_EQ(
-      TimeTicks::Max(),
-      sequence_manager()->GetNextTaskTime(
+      absl::nullopt,
+      sequence_manager()->GetPendingWakeUp(
           &lazy_now2, SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
 
   // Execute the delayed task.
   EXPECT_TRUE(sequence_manager()->SelectNextTask(
       SequencedTaskSource::SelectTaskOption::kDefault));
   sequence_manager()->DidRunTask();
-  EXPECT_EQ(TimeTicks::Max(), sequence_manager()->GetNextTaskTime(&lazy_now2));
+  EXPECT_EQ(absl::nullopt, sequence_manager()->GetPendingWakeUp(&lazy_now2));
 
   // Tidy up.
   queue->ShutdownTaskQueue();
@@ -3418,20 +3483,20 @@
   constexpr TimeDelta kDelay(Milliseconds(10));
   LazyNow lazy_now(mock_tick_clock());
 
-  EXPECT_EQ(TimeTicks::Max(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(absl::nullopt, sequence_manager()->GetPendingWakeUp(&lazy_now));
   EXPECT_EQ(
-      TimeTicks::Max(),
-      sequence_manager()->GetNextTaskTime(
+      absl::nullopt,
+      sequence_manager()->GetPendingWakeUp(
           &lazy_now, SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
 
   // Post an immediate task.
   queue->task_runner()->PostTask(FROM_HERE, BindOnce(&NopTask));
   queue->task_runner()->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), kDelay);
 
-  EXPECT_EQ(TimeTicks(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(WakeUp{}, sequence_manager()->GetPendingWakeUp(&lazy_now));
   EXPECT_EQ(
-      TimeTicks(),
-      sequence_manager()->GetNextTaskTime(
+      WakeUp{},
+      sequence_manager()->GetPendingWakeUp(
           &lazy_now, SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
 
   AdvanceMockTickClock(kDelay);
@@ -3439,8 +3504,8 @@
 
   // An immediate task is present, even if we skip the delayed tasks.
   EXPECT_EQ(
-      TimeTicks(),
-      sequence_manager()->GetNextTaskTime(
+      WakeUp{},
+      sequence_manager()->GetPendingWakeUp(
           &lazy_now2, SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
 
   // Immediate task should be ready to execute, execute it.
@@ -3456,16 +3521,16 @@
   EXPECT_FALSE(sequence_manager()->SelectNextTask(
       SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
   EXPECT_EQ(
-      TimeTicks::Max(),
-      sequence_manager()->GetNextTaskTime(
+      absl::nullopt,
+      sequence_manager()->GetPendingWakeUp(
           &lazy_now2, SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
 
   // Execute the delayed task.
   EXPECT_TRUE(sequence_manager()->SelectNextTask(
       SequencedTaskSource::SelectTaskOption::kDefault));
   EXPECT_EQ(
-      TimeTicks::Max(),
-      sequence_manager()->GetNextTaskTime(
+      absl::nullopt,
+      sequence_manager()->GetPendingWakeUp(
           &lazy_now2, SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
   sequence_manager()->DidRunTask();
 
@@ -3495,16 +3560,16 @@
   LazyNow lazy_now(mock_tick_clock());
 
   EXPECT_EQ(
-      TimeTicks(),
-      sequence_manager()->GetNextTaskTime(
+      WakeUp{},
+      sequence_manager()->GetPendingWakeUp(
           &lazy_now, SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
 
   AdvanceMockTickClock(kDelay);
   LazyNow lazy_now2(mock_tick_clock());
 
   EXPECT_EQ(
-      TimeTicks(),
-      sequence_manager()->GetNextTaskTime(
+      WakeUp{},
+      sequence_manager()->GetPendingWakeUp(
           &lazy_now2, SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
 
   // Immediate tasks should be ready to execute, execute them.
@@ -3519,8 +3584,8 @@
   EXPECT_FALSE(sequence_manager()->SelectNextTask(
       SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
   EXPECT_EQ(
-      TimeTicks::Max(),
-      sequence_manager()->GetNextTaskTime(
+      absl::nullopt,
+      sequence_manager()->GetPendingWakeUp(
           &lazy_now2, SequencedTaskSource::SelectTaskOption::kSkipDelayedTask));
 
   // Execute delayed tasks.
@@ -3531,7 +3596,7 @@
 
   // No delayed tasks can be executed anymore.
   EXPECT_FALSE(sequence_manager()->SelectNextTask());
-  EXPECT_EQ(TimeTicks::Max(), sequence_manager()->GetNextTaskTime(&lazy_now2));
+  EXPECT_EQ(absl::nullopt, sequence_manager()->GetPendingWakeUp(&lazy_now2));
 
   // Tidy up.
   queues[0]->ShutdownTaskQueue();
@@ -3540,36 +3605,36 @@
   queues[3]->ShutdownTaskQueue();
 }
 
-TEST_P(SequenceManagerTest, GetNextTaskTime) {
+TEST_P(SequenceManagerTest, GetPendingWakeUp) {
   auto queues = CreateTaskQueues(2u);
 
   LazyNow lazy_now(mock_tick_clock());
-  EXPECT_EQ(TimeTicks::Max(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(absl::nullopt, sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   queues[0]->task_runner()->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
                                             Seconds(10));
 
-  EXPECT_EQ(lazy_now.Now() + Seconds(10),
-            sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ((WakeUp{lazy_now.Now() + Seconds(10), kLeeway}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   queues[1]->task_runner()->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
                                             Seconds(15));
 
-  EXPECT_EQ(lazy_now.Now() + Seconds(10),
-            sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ((WakeUp{lazy_now.Now() + Seconds(10), kLeeway}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   queues[1]->task_runner()->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
                                             Seconds(5));
 
-  EXPECT_EQ(lazy_now.Now() + Seconds(5),
-            sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ((WakeUp{lazy_now.Now() + Seconds(5), kLeeway}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   queues[0]->task_runner()->PostTask(FROM_HERE, BindOnce(&NopTask));
 
-  EXPECT_EQ(TimeTicks(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(WakeUp{}, sequence_manager()->GetPendingWakeUp(&lazy_now));
 }
 
-TEST_P(SequenceManagerTest, GetNextTaskTime_Disabled) {
+TEST_P(SequenceManagerTest, GetPendingWakeUp_Disabled) {
   auto queue = CreateTaskQueue();
 
   std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
@@ -3578,20 +3643,20 @@
   queue->task_runner()->PostTask(FROM_HERE, BindOnce(&NopTask));
 
   LazyNow lazy_now(mock_tick_clock());
-  EXPECT_EQ(TimeTicks::Max(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(absl::nullopt, sequence_manager()->GetPendingWakeUp(&lazy_now));
 }
 
-TEST_P(SequenceManagerTest, GetNextTaskTime_Fence) {
+TEST_P(SequenceManagerTest, GetPendingWakeUp_Fence) {
   auto queue = CreateTaskQueue();
 
   queue->InsertFence(TaskQueue::InsertFencePosition::kNow);
   queue->task_runner()->PostTask(FROM_HERE, BindOnce(&NopTask));
 
   LazyNow lazy_now(mock_tick_clock());
-  EXPECT_EQ(TimeTicks::Max(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(absl::nullopt, sequence_manager()->GetPendingWakeUp(&lazy_now));
 }
 
-TEST_P(SequenceManagerTest, GetNextTaskTime_FenceUnblocking) {
+TEST_P(SequenceManagerTest, GetPendingWakeUp_FenceUnblocking) {
   auto queue = CreateTaskQueue();
 
   queue->InsertFence(TaskQueue::InsertFencePosition::kNow);
@@ -3599,10 +3664,10 @@
   queue->InsertFence(TaskQueue::InsertFencePosition::kNow);
 
   LazyNow lazy_now(mock_tick_clock());
-  EXPECT_EQ(TimeTicks(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(WakeUp{}, sequence_manager()->GetPendingWakeUp(&lazy_now));
 }
 
-TEST_P(SequenceManagerTest, GetNextTaskTime_DelayedTaskReady) {
+TEST_P(SequenceManagerTest, GetPendingWakeUp_DelayedTaskReady) {
   auto queue = CreateTaskQueue();
 
   queue->task_runner()->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
@@ -3611,7 +3676,7 @@
   AdvanceMockTickClock(Seconds(10));
 
   LazyNow lazy_now(mock_tick_clock());
-  EXPECT_EQ(TimeTicks(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(WakeUp{}, sequence_manager()->GetPendingWakeUp(&lazy_now));
 }
 
 TEST_P(SequenceManagerTest, RemoveAllCanceledDelayedTasksFromFront) {
@@ -3627,19 +3692,19 @@
 
   // Ensure it is picked to calculate the next task time.
   LazyNow lazy_now(mock_tick_clock());
-  EXPECT_EQ(lazy_now.Now() + kDelay,
-            sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ((WakeUp{lazy_now.Now() + kDelay, kLeeway}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   // Canceling the task is not sufficient to ensure it is not considered for the
   // next task time.
   cancelable_closure.Cancel();
-  EXPECT_EQ(lazy_now.Now() + kDelay,
-            sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ((WakeUp{lazy_now.Now() + kDelay, kLeeway}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   // Removing the canceled task means it can't be considered for the next task
   // time.
   sequence_manager()->RemoveAllCanceledDelayedTasksFromFront(&lazy_now);
-  EXPECT_EQ(TimeTicks::Max(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(absl::nullopt, sequence_manager()->GetPendingWakeUp(&lazy_now));
 }
 
 TEST_P(SequenceManagerTest,
@@ -3662,22 +3727,22 @@
 
   // The task from the first queue is picked to calculate the next task time.
   LazyNow lazy_now(mock_tick_clock());
-  EXPECT_EQ(lazy_now.Now() + kDelay1,
-            sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ((WakeUp{lazy_now.Now() + kDelay1, kLeeway}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   // Test that calling RemoveAllCanceledDelayedTasksFromFront() works (and does
   // nothing) when no task is canceled.
   sequence_manager()->RemoveAllCanceledDelayedTasksFromFront(&lazy_now);
-  EXPECT_EQ(lazy_now.Now() + kDelay1,
-            sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ((WakeUp{lazy_now.Now() + kDelay1, kLeeway}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   // Canceling the first task which comes from the first queue.
   cancelable_closure_1.Cancel();
   sequence_manager()->RemoveAllCanceledDelayedTasksFromFront(&lazy_now);
 
   // Now the only task remaining is the one from the second queue.
-  EXPECT_EQ(lazy_now.Now() + kDelay2,
-            sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ((WakeUp{lazy_now.Now() + kDelay2, kLeeway}),
+            sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   // Cancel the remaining task.
   cancelable_closure_2.Cancel();
@@ -3685,12 +3750,12 @@
 
   // No more valid tasks in any queues.
   sequence_manager()->RemoveAllCanceledDelayedTasksFromFront(&lazy_now);
-  EXPECT_EQ(TimeTicks::Max(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(absl::nullopt, sequence_manager()->GetPendingWakeUp(&lazy_now));
 
   // Test that calling RemoveAllCanceledDelayedTasksFromFront() works (and does
   // nothing) when all queues are empty.
   sequence_manager()->RemoveAllCanceledDelayedTasksFromFront(&lazy_now);
-  EXPECT_EQ(TimeTicks::Max(), sequence_manager()->GetNextTaskTime(&lazy_now));
+  EXPECT_EQ(absl::nullopt, sequence_manager()->GetPendingWakeUp(&lazy_now));
 }
 
 namespace {
diff --git a/base/task/sequence_manager/sequenced_task_source.h b/base/task/sequence_manager/sequenced_task_source.h
index 456b796..770713b 100644
--- a/base/task/sequence_manager/sequenced_task_source.h
+++ b/base/task/sequence_manager/sequenced_task_source.h
@@ -55,15 +55,15 @@
   virtual void DidRunTask() = 0;
 
   // Removes all canceled delayed tasks from the front of the queue. After
-  // calling this, GetNextTaskTime() is guaranteed to return a ready time for a
+  // calling this, GetPendingWakeUp() is guaranteed to return a ready time for a
   // non-canceled task.
   virtual void RemoveAllCanceledDelayedTasksFromFront(LazyNow* lazy_now) = 0;
 
-  // Returns the ready time for the next pending task, is_null() if the next
-  // task can run immediately, or is_max() if there are no more immediate or
+  // Returns a WakeUp for the next pending task, is_immediate() if the
+  // next task can run immediately, or nullopt if there are no more immediate or
   // delayed tasks. |option| allows control on which kind of tasks can be
   // selected.
-  virtual TimeTicks GetNextTaskTime(
+  virtual absl::optional<WakeUp> GetPendingWakeUp(
       LazyNow* lazy_now,
       SelectTaskOption option = SelectTaskOption::kDefault) const = 0;
 
diff --git a/base/task/sequence_manager/task_order.h b/base/task/sequence_manager/task_order.h
index d1ebf1a..48734f2 100644
--- a/base/task/sequence_manager/task_order.h
+++ b/base/task/sequence_manager/task_order.h
@@ -29,9 +29,9 @@
 //    wake-up have the same `enqueue_order_` and their order is decided by
 //    `delayed_run_time_` and `sequence_num_`.
 //
-//  - `delayed_run_time_`: The time at which a delayed task's delay expires;
-//    only non-zero for delayed tasks. Delayed tasks enqueued as part of the
-//    same wake-up are ordered by `delayed_run_time`.
+//  - `delayed_run_time_`: The latest time at which a delayed task should run;
+//    only non-zero for delayed tasks. Before they become ripe, delayed tasks
+//    are maintained in a heap ordered by `latest_delayed_run_time`.
 //
 //  - `sequence_num_`: a strictly increasing number assigned at posting time for
 //    all tasks. This is used to order delayed tasks if their `enqueue_order_`
@@ -56,6 +56,7 @@
 
   int sequence_num() const { return sequence_num_; }
 
+  // TODO(1153139): Rename to latest_delayed_run_time() for clarity.
   TimeTicks delayed_run_time() const { return delayed_run_time_; }
 
   static TaskOrder CreateForTesting(EnqueueOrder enqueue_order,
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc
index ba5bba7..715f0ab 100644
--- a/base/task/sequence_manager/task_queue_impl.cc
+++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -485,8 +485,10 @@
 
   if (current_thread == CurrentThread::kMainThread) {
     LazyNow lazy_now(sequence_manager_->main_thread_clock());
+    Task pending_task = MakeDelayedTask(std::move(posted_task), &lazy_now);
+    sequence_manager_->MaybeAddLeewayToTask(pending_task);
     PushOntoDelayedIncomingQueueFromMainThread(
-        MakeDelayedTask(std::move(posted_task), &lazy_now), &lazy_now,
+        std::move(pending_task), &lazy_now,
         /* notify_task_annotator */ true);
   } else {
     LazyNow lazy_now(sequence_manager_->any_thread_clock());
@@ -534,10 +536,12 @@
 
 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
-  TimeTicks delayed_run_time = pending_task.delayed_run_time;
+  sequence_manager_->MaybeAddLeewayToTask(pending_task);
   TimeTicks now = sequence_manager_->main_thread_clock()->NowTicks();
   LazyNow lazy_now(now);
-  if (delayed_run_time <= now) {
+  // A delayed task is ready to run as soon as earliest_delayed_run_time() is
+  // reached.
+  if (pending_task.earliest_delayed_run_time() <= now) {
     // If |delayed_run_time| is in the past then push it onto the work queue
     // immediately. To ensure the right task ordering we need to temporarily
     // push it onto the |delayed_incoming_queue|.
@@ -655,7 +659,8 @@
           : WakeUpResolution::kLow;
 
   const auto& top_task = main_thread_only().delayed_incoming_queue.top();
-  return WakeUp{top_task.delayed_run_time, resolution};
+  return WakeUp{top_task.delayed_run_time, top_task.leeway, resolution,
+                top_task.delay_policy};
 }
 
 void TaskQueueImpl::OnWakeUp(LazyNow* lazy_now, EnqueueOrder enqueue_order) {
@@ -708,7 +713,7 @@
 
     // Leave the top task alone if it hasn't been canceled and it is not ready.
     const bool is_cancelled = task.task.IsCancelled();
-    if (!is_cancelled && task.delayed_run_time > lazy_now->Now())
+    if (!is_cancelled && task.earliest_delayed_run_time() > lazy_now->Now())
       break;
 
     Task ready_task = main_thread_only().delayed_incoming_queue.take_top();
@@ -1089,6 +1094,7 @@
     resolution = WakeUpResolution::kHigh;
   }
 #endif  // BUILDFLAG(IS_WIN)
+  // leeway isn't specified yet since this may be called from any thread.
   return Task(std::move(delayed_task), sequence_number, EnqueueOrder(),
               lazy_now->Now(), resolution);
 }
@@ -1538,7 +1544,7 @@
 
 Task TaskQueueImpl::DelayedIncomingQueue::take_top() {
   DCHECK(!empty());
-  if (top().is_high_res) {
+  if (queue_.top().is_high_res) {
     pending_high_res_tasks_--;
     DCHECK_GE(pending_high_res_tasks_, 0);
   }
@@ -1573,6 +1579,19 @@
   return state;
 }
 
+bool TaskQueueImpl::DelayedIncomingQueue::Compare::operator()(
+    const Task& lhs,
+    const Task& rhs) const {
+  // Delayed tasks are ordered by latest_delayed_run_time(). The top task may
+  // not be the first task eligible to run, but tasks will always become ripe
+  // before their latest_delayed_run_time().
+  const TimeTicks lhs_latest_delayed_run_time = lhs.latest_delayed_run_time();
+  const TimeTicks rhs_latest_delayed_run_time = rhs.latest_delayed_run_time();
+  if (lhs_latest_delayed_run_time == rhs_latest_delayed_run_time)
+    return lhs.sequence_num > rhs.sequence_num;
+  return lhs_latest_delayed_run_time > rhs_latest_delayed_run_time;
+}
+
 TaskQueueImpl::OnTaskPostedCallbackHandleImpl::OnTaskPostedCallbackHandleImpl(
     TaskQueueImpl* task_queue_impl,
     scoped_refptr<AssociatedThreadId> associated_thread)
diff --git a/base/task/sequence_manager/task_queue_impl.h b/base/task/sequence_manager/task_queue_impl.h
index c1b9de7e..02e18217 100644
--- a/base/task/sequence_manager/task_queue_impl.h
+++ b/base/task/sequence_manager/task_queue_impl.h
@@ -215,9 +215,10 @@
   // removed.
   bool RemoveAllCanceledDelayedTasksFromFront(LazyNow* lazy_now);
 
-  // Enqueues any delayed tasks which should be run now on the
-  // `delayed_work_queue`, setting each task's enqueue order to `enqueue_order`.
-  // Must be called from the main thread.
+  // Enqueues in `delayed_work_queue` all delayed tasks which must run now
+  // (cannot be postponed) and possibly some delayed tasks which can run now but
+  // could be postponed (due to how tasks are stored, it is not possible to
+  // retrieve all such tasks efficiently). Must be called from the main thread.
   void MoveReadyDelayedTasksToWorkQueue(LazyNow* lazy_now,
                                         EnqueueOrder enqueue_order);
 
@@ -410,7 +411,10 @@
     Value AsValue(TimeTicks now) const;
 
    private:
-    IntrusiveHeap<Task, std::greater<>> queue_;
+    struct Compare {
+      bool operator()(const Task& lhs, const Task& rhs) const;
+    };
+    IntrusiveHeap<Task, Compare> queue_;
 
     // Number of pending tasks in the queue that need high resolution timing.
     int pending_high_res_tasks_ = 0;
diff --git a/base/task/sequence_manager/tasks.cc b/base/task/sequence_manager/tasks.cc
index 9cea593..979965b 100644
--- a/base/task/sequence_manager/tasks.cc
+++ b/base/task/sequence_manager/tasks.cc
@@ -13,7 +13,8 @@
            EnqueueOrder sequence_order,
            EnqueueOrder enqueue_order,
            TimeTicks queue_time,
-           WakeUpResolution resolution)
+           WakeUpResolution resolution,
+           TimeDelta leeway)
     : PendingTask(posted_task.location,
                   std::move(posted_task.callback),
                   queue_time,
@@ -23,6 +24,10 @@
                             posted_task.delay_or_delayed_run_time)
                       : base::TimeTicks()),
       nestable(posted_task.nestable),
+      leeway(leeway),
+      delay_policy(posted_task.delay_policy
+                       ? *posted_task.delay_policy
+                       : subtle::DelayPolicy::kFlexibleNoSooner),
       task_type(posted_task.task_type),
       task_runner(std::move(posted_task.task_runner)),
       enqueue_order_(enqueue_order),
@@ -47,8 +52,20 @@
 
 Task& Task::operator=(Task&& other) = default;
 
+TimeTicks Task::earliest_delayed_run_time() const {
+  if (delay_policy == subtle::DelayPolicy::kFlexiblePreferEarly)
+    return delayed_run_time - leeway;
+  return delayed_run_time;
+}
+
+TimeTicks Task::latest_delayed_run_time() const {
+  if (delay_policy == subtle::DelayPolicy::kFlexibleNoSooner)
+    return delayed_run_time + leeway;
+  return delayed_run_time;
+}
+
 TaskOrder Task::task_order() const {
-  return TaskOrder(enqueue_order(), delayed_run_time, sequence_num);
+  return TaskOrder(enqueue_order(), latest_delayed_run_time(), sequence_num);
 }
 
 void Task::SetHeapHandle(HeapHandle heap_handle) {
@@ -87,6 +104,18 @@
   delayed_task_handle_delegate_->WillRunTask();
 }
 
+TimeTicks WakeUp::earliest_time() const {
+  if (delay_policy == subtle::DelayPolicy::kFlexiblePreferEarly)
+    return time - leeway;
+  return time;
+}
+
+TimeTicks WakeUp::latest_time() const {
+  if (delay_policy == subtle::DelayPolicy::kFlexibleNoSooner)
+    return time + leeway;
+  return time;
+}
+
 namespace internal {
 PostedTask::PostedTask(
     scoped_refptr<SequencedTaskRunner> task_runner,
diff --git a/base/task/sequence_manager/tasks.h b/base/task/sequence_manager/tasks.h
index cbe34e7..ee6c5a4 100644
--- a/base/task/sequence_manager/tasks.h
+++ b/base/task/sequence_manager/tasks.h
@@ -75,19 +75,26 @@
 
 // Represents a time at which a task wants to run.
 struct WakeUp {
+  static constexpr TimeDelta kDefaultLeeway = Milliseconds(8);
+
+  // is_null() for immediate wake up.
   TimeTicks time;
-  WakeUpResolution resolution;
+  // These are meaningless if is_immediate().
+  TimeDelta leeway;
+  WakeUpResolution resolution = WakeUpResolution::kLow;
+  subtle::DelayPolicy delay_policy = subtle::DelayPolicy::kFlexibleNoSooner;
 
   bool operator!=(const WakeUp& other) const {
-    return time != other.time || resolution != other.resolution;
+    return time != other.time || leeway != other.leeway ||
+           resolution != other.resolution || delay_policy != other.delay_policy;
   }
 
   bool operator==(const WakeUp& other) const { return !(*this != other); }
 
-  // Used for a min-heap.
-  bool operator>(const WakeUp& other) const {
-    return std::tie(time, resolution) > std::tie(other.time, other.resolution);
-  }
+  bool is_immediate() const { return time.is_null(); }
+
+  TimeTicks earliest_time() const;
+  TimeTicks latest_time() const;
 };
 
 // PendingTask with extra metadata for SequenceManager.
@@ -96,7 +103,8 @@
        EnqueueOrder sequence_order,
        EnqueueOrder enqueue_order = EnqueueOrder(),
        TimeTicks queue_time = TimeTicks(),
-       WakeUpResolution wake_up_resolution = WakeUpResolution::kLow);
+       WakeUpResolution wake_up_resolution = WakeUpResolution::kLow,
+       TimeDelta leeway = TimeDelta());
   Task(Task&& move_from);
   ~Task();
   Task& operator=(Task&& other);
@@ -115,11 +123,17 @@
 
   bool enqueue_order_set() const { return enqueue_order_; }
 
+  TimeTicks earliest_delayed_run_time() const;
+  TimeTicks latest_delayed_run_time() const;
+
   TaskOrder task_order() const;
 
   // OK to dispatch from a nested loop.
   Nestable nestable = Nestable::kNonNestable;
 
+  TimeDelta leeway;
+  subtle::DelayPolicy delay_policy = subtle::DelayPolicy::kFlexibleNoSooner;
+
   // Needs high resolution timers.
   bool is_high_res = false;
 
diff --git a/base/task/sequence_manager/thread_controller.h b/base/task/sequence_manager/thread_controller.h
index fabbdef..f5b7468 100644
--- a/base/task/sequence_manager/thread_controller.h
+++ b/base/task/sequence_manager/thread_controller.h
@@ -12,6 +12,7 @@
 #include "base/message_loop/message_pump.h"
 #include "base/run_loop.h"
 #include "base/task/sequence_manager/lazy_now.h"
+#include "base/task/sequence_manager/tasks.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -58,12 +59,13 @@
   virtual void ScheduleWork() = 0;
 
   // Notify the controller that SequencedTaskSource will have a delayed work
-  // ready to be run at |run_time|. This call cancels any previously
+  // ready to be run at |wake_up|. This call cancels any previously
   // scheduled delayed work. Can only be called from the main sequence.
-  // NOTE: DelayTillNextTask might return a different value as it also takes
+  // NOTE: GetPendingWakeUp might return a different value as it also takes
   // immediate work into account.
   // TODO(kraynov): Remove |lazy_now| parameter.
-  virtual void SetNextDelayedDoWork(LazyNow* lazy_now, TimeTicks run_time) = 0;
+  virtual void SetNextDelayedDoWork(LazyNow* lazy_now,
+                                    absl::optional<WakeUp> wake_up) = 0;
 
   // Sets the sequenced task source from which to take tasks after
   // a Schedule*Work() call is made.
diff --git a/base/task/sequence_manager/thread_controller_impl.cc b/base/task/sequence_manager/thread_controller_impl.cc
index a802403..16e6f6fe 100644
--- a/base/task/sequence_manager/thread_controller_impl.cc
+++ b/base/task/sequence_manager/thread_controller_impl.cc
@@ -94,18 +94,19 @@
   }
 }
 
-void ThreadControllerImpl::SetNextDelayedDoWork(LazyNow* lazy_now,
-                                                TimeTicks run_time) {
+void ThreadControllerImpl::SetNextDelayedDoWork(
+    LazyNow* lazy_now,
+    absl::optional<WakeUp> wake_up) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(associated_thread_->sequence_checker);
   DCHECK(sequence_);
-
-  if (main_sequence_only().next_delayed_do_work == run_time)
-    return;
+  DCHECK(!wake_up || !wake_up->is_immediate());
 
   // Cancel DoWork if it was scheduled and we set an "infinite" delay now.
-  if (run_time == TimeTicks::Max()) {
-    cancelable_delayed_do_work_closure_.Cancel();
-    main_sequence_only().next_delayed_do_work = TimeTicks::Max();
+  if (!wake_up) {
+    if (!main_sequence_only().next_delayed_do_work.is_max()) {
+      cancelable_delayed_do_work_closure_.Cancel();
+      main_sequence_only().next_delayed_do_work = TimeTicks::Max();
+    }
     return;
   }
 
@@ -114,12 +115,16 @@
     return;
   }
 
-  base::TimeDelta delay = std::max(TimeDelta(), run_time - lazy_now->Now());
+  if (main_sequence_only().next_delayed_do_work == wake_up->time)
+    return;
+
+  base::TimeDelta delay =
+      std::max(TimeDelta(), wake_up->time - lazy_now->Now());
   TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
                "ThreadControllerImpl::SetNextDelayedDoWork::PostDelayedTask",
                "delay_ms", delay.InMillisecondsF());
 
-  main_sequence_only().next_delayed_do_work = run_time;
+  main_sequence_only().next_delayed_do_work = wake_up->time;
   // Reset also causes cancellation of the previous DoWork task.
   cancelable_delayed_do_work_closure_.Reset(delayed_do_work_closure_);
   task_runner_->PostDelayedTask(
@@ -231,10 +236,11 @@
 
   LazyNow lazy_now(time_source_);
   sequence_->RemoveAllCanceledDelayedTasksFromFront(&lazy_now);
-  TimeTicks next_task_time = sequence_->GetNextTaskTime(&lazy_now);
+  absl::optional<WakeUp> next_wake_up = sequence_->GetPendingWakeUp(&lazy_now);
   // The OnSystemIdle callback allows the TimeDomains to advance virtual time
   // in which case we now have immediate work to do.
-  if (next_task_time.is_null() || sequence_->OnSystemIdle()) {
+  if ((next_wake_up && next_wake_up->is_immediate()) ||
+      sequence_->OnSystemIdle()) {
     // The next task needs to run immediately, post a continuation if
     // another thread didn't get there first.
     if (work_deduplicator_.DidCheckForMoreWork(
@@ -258,23 +264,25 @@
   main_sequence_only().run_level_tracker.OnIdle();
 
   // Any future work?
-  if (next_task_time.is_max()) {
+  if (!next_wake_up) {
     main_sequence_only().next_delayed_do_work = TimeTicks::Max();
     cancelable_delayed_do_work_closure_.Cancel();
     return;
   }
 
+  TimeTicks next_wake_up_time = next_wake_up->time;
   // Already requested next delay?
-  if (next_task_time == main_sequence_only().next_delayed_do_work)
+  if (next_wake_up_time == main_sequence_only().next_delayed_do_work)
     return;
 
   // Schedule a callback after |delay_till_next_task| and cancel any previous
   // callback.
-  main_sequence_only().next_delayed_do_work = next_task_time;
+  main_sequence_only().next_delayed_do_work = next_wake_up_time;
   cancelable_delayed_do_work_closure_.Reset(delayed_do_work_closure_);
+  // TODO(1153139): Use PostDelayedTaskAt().
   task_runner_->PostDelayedTask(FROM_HERE,
                                 cancelable_delayed_do_work_closure_.callback(),
-                                next_task_time - lazy_now.Now());
+                                next_wake_up_time - lazy_now.Now());
 }
 
 void ThreadControllerImpl::AddNestingObserver(
diff --git a/base/task/sequence_manager/thread_controller_impl.h b/base/task/sequence_manager/thread_controller_impl.h
index 417f36b..5cd8f5b7 100644
--- a/base/task/sequence_manager/thread_controller_impl.h
+++ b/base/task/sequence_manager/thread_controller_impl.h
@@ -48,7 +48,8 @@
                      const char* task_queue_name) override;
   void ScheduleWork() override;
   void BindToCurrentThread(std::unique_ptr<MessagePump> message_pump) override;
-  void SetNextDelayedDoWork(LazyNow* lazy_now, TimeTicks run_time) override;
+  void SetNextDelayedDoWork(LazyNow* lazy_now,
+                            absl::optional<WakeUp> wake_up) override;
   void SetSequencedTaskSource(SequencedTaskSource* sequence) override;
   void SetTimerSlack(TimerSlack timer_slack) override;
   bool RunsTasksInCurrentSequence() override;
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
index 8615fe6..caec4bd 100644
--- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
+++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
@@ -135,22 +135,23 @@
 
 void ThreadControllerWithMessagePumpImpl::SetNextDelayedDoWork(
     LazyNow* lazy_now,
-    TimeTicks run_time) {
+    absl::optional<WakeUp> wake_up) {
+  DCHECK(!wake_up || !wake_up->is_immediate());
+  TimeTicks run_time = wake_up.has_value() ? wake_up->time : TimeTicks::Max();
   DCHECK_LT(lazy_now->Now(), run_time);
 
   if (main_thread_only().next_delayed_do_work == run_time)
     return;
-
-  // Cap at one day but remember the exact time for the above equality check on
-  // the next round.
   main_thread_only().next_delayed_do_work = run_time;
-  if (!run_time.is_max())
-    run_time = CapAtOneDay(run_time, lazy_now);
 
   // It's very rare for PostDelayedTask to be called outside of a DoWork in
   // production, so most of the time this does nothing.
   if (work_deduplicator_.OnDelayedWorkRequested() ==
       ShouldScheduleWork::kScheduleImmediate) {
+    // Cap at one day but remember the exact time for the above equality check
+    // on the next round.
+    if (!run_time.is_max())
+      run_time = CapAtOneDay(run_time, lazy_now);
     // |pump_| can't be null as all postTasks are cross-thread before binding,
     // and delayed cross-thread postTasks do the thread hop through an immediate
     // task.
@@ -258,7 +259,7 @@
 
   work_deduplicator_.OnWorkStarted();
   LazyNow continuation_lazy_now(time_source_);
-  TimeTicks next_task_time = DoWorkImpl(&continuation_lazy_now);
+  absl::optional<WakeUp> next_wake_up = DoWorkImpl(&continuation_lazy_now);
 
   // If we are yielding after DoWorkImpl (a work batch) set the flag boolean.
   // This will inform the MessagePump to schedule a new continuation based on
@@ -271,8 +272,9 @@
   }
   // Schedule a continuation.
   WorkDeduplicator::NextTask next_task =
-      next_task_time.is_null() ? WorkDeduplicator::NextTask::kIsImmediate
-                               : WorkDeduplicator::NextTask::kIsDelayed;
+      (next_wake_up && next_wake_up->is_immediate())
+          ? WorkDeduplicator::NextTask::kIsImmediate
+          : WorkDeduplicator::NextTask::kIsDelayed;
   if (work_deduplicator_.DidCheckForMoreWork(next_task) ==
       ShouldScheduleWork::kScheduleImmediate) {
     // Need to run new work immediately, but due to the contract of DoWork
@@ -280,9 +282,8 @@
     return next_work_info;
   }
 
-  // While the math below would saturate when |delay_till_next_task.is_max()|;
-  // special-casing here avoids unnecessarily sampling Now() when out of work.
-  if (next_task_time.is_max()) {
+  // Special-casing here avoids unnecessarily sampling Now() when out of work.
+  if (!next_wake_up) {
     main_thread_only().next_delayed_do_work = TimeTicks::Max();
     next_work_info.delayed_run_time = TimeTicks::Max();
     return next_work_info;
@@ -290,7 +291,7 @@
 
   // The MessagePump will schedule the wake up on our behalf, so we need to
   // update |main_thread_only().next_delayed_do_work|.
-  main_thread_only().next_delayed_do_work = next_task_time;
+  main_thread_only().next_delayed_do_work = next_wake_up->time;
 
   // Don't request a run time past |main_thread_only().quit_runloop_after|.
   if (main_thread_only().next_delayed_do_work >
@@ -310,7 +311,7 @@
   return next_work_info;
 }
 
-TimeTicks ThreadControllerWithMessagePumpImpl::DoWorkImpl(
+absl::optional<WakeUp> ThreadControllerWithMessagePumpImpl::DoWorkImpl(
     LazyNow* continuation_lazy_now) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
                "ThreadControllerImpl::DoWork");
@@ -320,8 +321,8 @@
     // helps spot nested loops that intentionally starve application tasks.
     TRACE_EVENT0("base", "ThreadController: application tasks disallowed");
     if (main_thread_only().quit_runloop_after == TimeTicks::Max())
-      return TimeTicks::Max();
-    return main_thread_only().quit_runloop_after;
+      return absl::nullopt;
+    return WakeUp{main_thread_only().quit_runloop_after};
   }
 
   DCHECK(main_thread_only().task_source);
@@ -372,7 +373,7 @@
   }
 
   if (main_thread_only().quit_pending)
-    return TimeTicks::Max();
+    return absl::nullopt;
 
   work_deduplicator_.WillCheckForMoreWork();
 
@@ -384,8 +385,8 @@
           : SequencedTaskSource::SelectTaskOption::kDefault;
   main_thread_only().task_source->RemoveAllCanceledDelayedTasksFromFront(
       continuation_lazy_now);
-  return main_thread_only().task_source->GetNextTaskTime(continuation_lazy_now,
-                                                         select_task_option);
+  return main_thread_only().task_source->GetPendingWakeUp(continuation_lazy_now,
+                                                          select_task_option);
 }
 
 bool ThreadControllerWithMessagePumpImpl::DoIdleWork() {
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.h b/base/task/sequence_manager/thread_controller_with_message_pump_impl.h
index b94e3c6..d3d98b3 100644
--- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.h
+++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.h
@@ -59,7 +59,8 @@
   void WillQueueTask(PendingTask* pending_task,
                      const char* task_queue_name) override;
   void ScheduleWork() override;
-  void SetNextDelayedDoWork(LazyNow* lazy_now, TimeTicks run_time) override;
+  void SetNextDelayedDoWork(LazyNow* lazy_now,
+                            absl::optional<WakeUp> wake_up) override;
   void SetTimerSlack(TimerSlack timer_slack) override;
   void SetTickClock(const TickClock* clock) override;
   bool RunsTasksInCurrentSequence() override;
@@ -148,10 +149,10 @@
   friend class DoWorkScope;
   friend class RunScope;
 
-  // Returns the ready time for the next pending task, is_null() if the next
-  // task can run immediately, or is_max() if there are no more immediate or
-  // delayed tasks.
-  TimeTicks DoWorkImpl(LazyNow* continuation_lazy_now);
+  // Returns a WakeUp for the next pending task, is_immediate() if the next task
+  // can run immediately, or nullopt if there are no more immediate or delayed
+  // tasks.
+  absl::optional<WakeUp> DoWorkImpl(LazyNow* continuation_lazy_now);
 
   void InitializeThreadTaskRunnerHandle()
       EXCLUSIVE_LOCKS_REQUIRED(task_runner_lock_);
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc
index 7e6558c..cd6081e 100644
--- a/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc
+++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc
@@ -131,19 +131,20 @@
 
   void RemoveAllCanceledDelayedTasksFromFront(LazyNow* lazy_now) override {}
 
-  TimeTicks GetNextTaskTime(LazyNow* lazy_now,
-                            SelectTaskOption option) const override {
+  absl::optional<WakeUp> GetPendingWakeUp(
+      LazyNow* lazy_now,
+      SelectTaskOption option) const override {
     if (tasks_.empty())
-      return TimeTicks::Max();
+      return absl::nullopt;
     if (option == SequencedTaskSource::SelectTaskOption::kSkipDelayedTask &&
         !tasks_.front().delayed_run_time.is_null()) {
-      return TimeTicks::Max();
+      return absl::nullopt;
     }
     if (tasks_.front().delayed_run_time.is_null())
-      return TimeTicks();
+      return WakeUp{};
     if (lazy_now->Now() > tasks_.front().delayed_run_time)
-      return TimeTicks();
-    return tasks_.front().delayed_run_time;
+      return WakeUp{};
+    return WakeUp{tasks_.front().delayed_run_time};
   }
 
   void AddTask(Location posted_from,
@@ -270,14 +271,14 @@
   EXPECT_CALL(*message_pump_, ScheduleDelayedWork(Seconds(123)));
 
   LazyNow lazy_now(&clock_);
-  thread_controller_.SetNextDelayedDoWork(&lazy_now, Seconds(123));
+  thread_controller_.SetNextDelayedDoWork(&lazy_now, WakeUp{Seconds(123)});
 }
 
 TEST_F(ThreadControllerWithMessagePumpTest, SetNextDelayedDoWork_CapAtOneDay) {
   EXPECT_CALL(*message_pump_, ScheduleDelayedWork(Days(1)));
 
   LazyNow lazy_now(&clock_);
-  thread_controller_.SetNextDelayedDoWork(&lazy_now, Days(2));
+  thread_controller_.SetNextDelayedDoWork(&lazy_now, WakeUp{Days(2)});
 }
 
 TEST_F(ThreadControllerWithMessagePumpTest, DelayedWork_CapAtOneDay) {
diff --git a/base/task/sequence_manager/wake_up_queue.cc b/base/task/sequence_manager/wake_up_queue.cc
index ffd84e25..5e51c26 100644
--- a/base/task/sequence_manager/wake_up_queue.cc
+++ b/base/task/sequence_manager/wake_up_queue.cc
@@ -47,10 +47,8 @@
   DCHECK_EQ(queue->wake_up_queue(), this);
   DCHECK(queue->IsQueueEnabled() || !wake_up);
 
-  absl::optional<TimeTicks> previous_wake_up;
+  absl::optional<WakeUp> previous_wake_up = GetNextDelayedWakeUp();
   absl::optional<WakeUpResolution> previous_queue_resolution;
-  if (!wake_up_queue_.empty())
-    previous_wake_up = wake_up_queue_.top().wake_up.time;
   if (queue->heap_handle().IsValid()) {
     previous_queue_resolution =
         wake_up_queue_.at(queue->heap_handle()).wake_up.resolution;
@@ -71,9 +69,7 @@
       wake_up_queue_.erase(queue->heap_handle());
   }
 
-  absl::optional<TimeTicks> new_wake_up;
-  if (!wake_up_queue_.empty())
-    new_wake_up = wake_up_queue_.top().wake_up.time;
+  absl::optional<WakeUp> new_wake_up = GetNextDelayedWakeUp();
 
   if (previous_queue_resolution &&
       *previous_queue_resolution == WakeUpResolution::kHigh) {
@@ -84,23 +80,23 @@
   DCHECK_GE(pending_high_res_wake_up_count_, 0);
 
   if (new_wake_up != previous_wake_up)
-    OnNextWakeUpChanged(lazy_now, GetNextWakeUp());
+    OnNextWakeUpChanged(lazy_now, GetNextDelayedWakeUp());
 }
 
 void WakeUpQueue::MoveReadyDelayedTasksToWorkQueues(
     LazyNow* lazy_now,
     EnqueueOrder enqueue_order) {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
-  // Wake up any queues with pending delayed work.
   bool update_needed = false;
   while (!wake_up_queue_.empty() &&
-         wake_up_queue_.top().wake_up.time <= lazy_now->Now()) {
+         wake_up_queue_.top().wake_up.earliest_time() <= lazy_now->Now()) {
     internal::TaskQueueImpl* queue = wake_up_queue_.top().queue;
     // OnWakeUp() is expected to update the next wake-up for this queue with
     // SetNextWakeUpForQueue(), thus allowing us to make progress.
     queue->OnWakeUp(lazy_now, enqueue_order);
     update_needed = true;
   }
+
   if (!update_needed || wake_up_queue_.empty())
     return;
   // If any queue was notified, possibly update following queues. This ensures
@@ -121,11 +117,18 @@
   }
 }
 
-absl::optional<WakeUp> WakeUpQueue::GetNextWakeUp() const {
+absl::optional<WakeUp> WakeUpQueue::GetNextDelayedWakeUp() const {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
   if (wake_up_queue_.empty())
     return absl::nullopt;
-  return wake_up_queue_.top().wake_up;
+  WakeUp wake_up = wake_up_queue_.top().wake_up;
+  // `wake_up.resolution` is not meaningful since it may be different from
+  // has_pending_high_resolution_tasks(). Return WakeUpResolution::kLow here to
+  // simplify comparison between wake ups.
+  // TODO(1153139): Drive resolution by DelayPolicy and return
+  // has_pending_high_resolution_tasks() here.
+  wake_up.resolution = WakeUpResolution::kLow;
+  return wake_up;
 }
 
 Value WakeUpQueue::AsValue(TimeTicks now) const {
diff --git a/base/task/sequence_manager/wake_up_queue.h b/base/task/sequence_manager/wake_up_queue.h
index 5f96359..e3b28e2 100644
--- a/base/task/sequence_manager/wake_up_queue.h
+++ b/base/task/sequence_manager/wake_up_queue.h
@@ -37,7 +37,7 @@
   // Returns a wake-up for the next pending delayed task (pending delayed tasks
   // that are ripe may be ignored). If there are no such tasks (immediate tasks
   // don't count) or queues are disabled it returns nullopt.
-  absl::optional<WakeUp> GetNextWakeUp() const;
+  absl::optional<WakeUp> GetNextDelayedWakeUp() const;
 
   // Debug info.
   Value AsValue(TimeTicks now) const;
@@ -65,7 +65,7 @@
   virtual void UnregisterQueue(internal::TaskQueueImpl* queue) = 0;
 
   // Removes all canceled delayed tasks from the front of the queue. After
-  // calling this, GetNextWakeUp() is guaranteed to return a wake up time
+  // calling this, GetNextDelayedWakeUp() is guaranteed to return a wake up time
   // for a non-canceled task.
   void RemoveAllCanceledDelayedTasksFromFront(LazyNow* lazy_now);
 
@@ -89,7 +89,7 @@
     internal::TaskQueueImpl* queue;
 
     bool operator>(const ScheduledWakeUp& other) const {
-      return wake_up > other.wake_up;
+      return wake_up.latest_time() > other.wake_up.latest_time();
     }
 
     void SetHeapHandle(HeapHandle handle) {
diff --git a/base/task/sequence_manager/wake_up_queue_unittest.cc b/base/task/sequence_manager/wake_up_queue_unittest.cc
index 2be853e4..94d0149 100644
--- a/base/task/sequence_manager/wake_up_queue_unittest.cc
+++ b/base/task/sequence_manager/wake_up_queue_unittest.cc
@@ -71,7 +71,7 @@
     return wake_up_queue_.top().wake_up.time;
   }
 
-  MOCK_METHOD1(OnNextWakeUpChanged_TimeTicks, void(TimeTicks run_time));
+  MOCK_METHOD1(OnNextWakeUpChanged_TimeTicks, void(TimeTicks time));
 };
 
 class WakeUpQueueTest : public testing::Test {
@@ -142,6 +142,85 @@
       .Times(AnyNumber());
 }
 
+TEST_F(
+    WakeUpQueueTest,
+    ScheduleFlexibleNoSoonerWakeUpForQueueSupersedesPreviousWakeUpWithLeeway) {
+  TimeTicks now = tick_clock_.NowTicks();
+  TimeDelta delay1 = Milliseconds(10);
+  TimeDelta delay2 = Milliseconds(15);
+  TimeTicks delayed_runtime1 = now + delay1;
+  TimeTicks delayed_runtime2 = now + delay2;
+  EXPECT_CALL(*wake_up_queue_.get(),
+              OnNextWakeUpChanged_TimeTicks(delayed_runtime1));
+  LazyNow lazy_now(now);
+  task_queue_->SetNextWakeUp(
+      &lazy_now,
+      WakeUp{delayed_runtime1, Milliseconds(10), WakeUpResolution::kLow,
+             subtle::DelayPolicy::kFlexibleNoSooner});
+
+  EXPECT_EQ((WakeUp{delayed_runtime1, Milliseconds(10), WakeUpResolution::kLow,
+                    subtle::DelayPolicy::kFlexibleNoSooner}),
+            wake_up_queue_->GetNextDelayedWakeUp());
+
+  Mock::VerifyAndClearExpectations(wake_up_queue_.get());
+
+  // Now schedule a later wake_up, which should replace the previously
+  // requested one.
+  EXPECT_CALL(*wake_up_queue_.get(),
+              OnNextWakeUpChanged_TimeTicks(delayed_runtime2));
+  task_queue_->SetNextWakeUp(
+      &lazy_now, WakeUp{delayed_runtime2, TimeDelta(), WakeUpResolution::kLow,
+                        subtle::DelayPolicy::kPrecise});
+
+  EXPECT_EQ((WakeUp{delayed_runtime2, TimeDelta(), WakeUpResolution::kLow,
+                    subtle::DelayPolicy::kPrecise}),
+            wake_up_queue_->GetNextDelayedWakeUp());
+  Mock::VerifyAndClearExpectations(wake_up_queue_.get());
+
+  EXPECT_CALL(*wake_up_queue_.get(),
+              OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
+      .Times(AnyNumber());
+}
+
+TEST_F(WakeUpQueueTest,
+       ScheduleFlexiblePreferEarlyWakeUpForQueueSupersedesPreviousWakeUp) {
+  TimeTicks now = tick_clock_.NowTicks();
+  TimeDelta delay1 = Milliseconds(10);
+  TimeDelta delay2 = Milliseconds(15);
+  TimeTicks delayed_runtime1 = now + delay1;
+  TimeTicks delayed_runtime2 = now + delay2;
+  EXPECT_CALL(*wake_up_queue_.get(),
+              OnNextWakeUpChanged_TimeTicks(delayed_runtime1));
+  LazyNow lazy_now(now);
+  task_queue_->SetNextWakeUp(
+      &lazy_now, WakeUp{delayed_runtime1, TimeDelta(), WakeUpResolution::kLow,
+                        subtle::DelayPolicy::kPrecise});
+
+  EXPECT_EQ((WakeUp{delayed_runtime1, TimeDelta(), WakeUpResolution::kLow,
+                    subtle::DelayPolicy::kPrecise}),
+            wake_up_queue_->GetNextDelayedWakeUp());
+
+  Mock::VerifyAndClearExpectations(wake_up_queue_.get());
+
+  // Now schedule a later wake_up, which should replace the previously
+  // requested one.
+  EXPECT_CALL(*wake_up_queue_.get(),
+              OnNextWakeUpChanged_TimeTicks(delayed_runtime2));
+  task_queue_->SetNextWakeUp(
+      &lazy_now,
+      WakeUp{delayed_runtime2, Milliseconds(10), WakeUpResolution::kLow,
+             subtle::DelayPolicy::kFlexiblePreferEarly});
+
+  EXPECT_EQ((WakeUp{delayed_runtime2, Milliseconds(10), WakeUpResolution::kLow,
+                    subtle::DelayPolicy::kFlexiblePreferEarly}),
+            wake_up_queue_->GetNextDelayedWakeUp());
+  Mock::VerifyAndClearExpectations(wake_up_queue_.get());
+
+  EXPECT_CALL(*wake_up_queue_.get(),
+              OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
+      .Times(AnyNumber());
+}
+
 TEST_F(WakeUpQueueTest, SetNextDelayedDoWork_OnlyCalledForEarlierTasks) {
   std::unique_ptr<TaskQueueImplForTest> task_queue2 =
       std::make_unique<TaskQueueImplForTest>(nullptr, wake_up_queue_.get(),
@@ -257,6 +336,42 @@
   ASSERT_TRUE(wake_up_queue_->NextScheduledRunTime().is_max());
 }
 
+TEST_F(WakeUpQueueTest, MoveReadyDelayedTasksToWorkQueuesWithLeeway) {
+  std::unique_ptr<TaskQueueImplForTest> task_queue2 =
+      std::make_unique<TaskQueueImplForTest>(nullptr, wake_up_queue_.get(),
+                                             TaskQueue::Spec("test"));
+
+  TimeTicks now = tick_clock_.NowTicks();
+  LazyNow lazy_now_1(now);
+
+  EXPECT_CALL(*wake_up_queue_.get(),
+              OnNextWakeUpChanged_TimeTicks(now + Milliseconds(10)));
+  task_queue2->SetNextWakeUp(&lazy_now_1,
+                             WakeUp{now + Milliseconds(10), Milliseconds(4)});
+  EXPECT_CALL(*wake_up_queue_.get(),
+              OnNextWakeUpChanged_TimeTicks(now + Milliseconds(11)));
+  task_queue_->SetNextWakeUp(&lazy_now_1,
+                             WakeUp{now + Milliseconds(11), TimeDelta()});
+
+  EXPECT_EQ(now + Milliseconds(11), wake_up_queue_->NextScheduledRunTime());
+
+  wake_up_queue_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_1,
+                                                    EnqueueOrder());
+  EXPECT_EQ(now + Milliseconds(11), wake_up_queue_->NextScheduledRunTime());
+
+  tick_clock_.SetNowTicks(now + Milliseconds(10));
+  LazyNow lazy_now_2(&tick_clock_);
+  wake_up_queue_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_2,
+                                                    EnqueueOrder());
+  EXPECT_EQ(now + Milliseconds(11), wake_up_queue_->NextScheduledRunTime());
+
+  Mock::VerifyAndClearExpectations(wake_up_queue_.get());
+  EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(_))
+      .Times(AnyNumber());
+  // Tidy up.
+  task_queue2->UnregisterTaskQueue();
+}
+
 TEST_F(WakeUpQueueTest, CancelDelayedWork) {
   TimeTicks now = tick_clock_.NowTicks();
   LazyNow lazy_now(now);
@@ -321,10 +436,10 @@
   // Add two high resolution wake-ups.
   EXPECT_FALSE(wake_up_queue_->has_pending_high_resolution_tasks());
   wake_up_queue_->SetNextWakeUpForQueue(
-      &q1, &lazy_now, WakeUp{run_time1, WakeUpResolution::kHigh});
+      &q1, &lazy_now, WakeUp{run_time1, TimeDelta(), WakeUpResolution::kHigh});
   EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
   wake_up_queue_->SetNextWakeUpForQueue(
-      &q2, &lazy_now, WakeUp{run_time2, WakeUpResolution::kHigh});
+      &q2, &lazy_now, WakeUp{run_time2, TimeDelta(), WakeUpResolution::kHigh});
   EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
 
   // Remove one of the wake-ups.
@@ -337,15 +452,15 @@
 
   // Change a low resolution wake-up to a high resolution one.
   wake_up_queue_->SetNextWakeUpForQueue(
-      &q1, &lazy_now, WakeUp{run_time1, WakeUpResolution::kLow});
+      &q1, &lazy_now, WakeUp{run_time1, TimeDelta(), WakeUpResolution::kLow});
   EXPECT_FALSE(wake_up_queue_->has_pending_high_resolution_tasks());
   wake_up_queue_->SetNextWakeUpForQueue(
-      &q1, &lazy_now, WakeUp{run_time1, WakeUpResolution::kHigh});
+      &q1, &lazy_now, WakeUp{run_time1, TimeDelta(), WakeUpResolution::kHigh});
   EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
 
   // Move a high resolution wake-up in time.
   wake_up_queue_->SetNextWakeUpForQueue(
-      &q1, &lazy_now, WakeUp{run_time2, WakeUpResolution::kHigh});
+      &q1, &lazy_now, WakeUp{run_time2, TimeDelta(), WakeUpResolution::kHigh});
   EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
 
   // Cancel the wake-up twice.
diff --git a/base/task/task_features.cc b/base/task/task_features.cc
index 057b44ef..dc7511b 100644
--- a/base/task/task_features.cc
+++ b/base/task/task_features.cc
@@ -49,4 +49,10 @@
 const BASE_EXPORT Feature kRemoveCanceledTasksInTaskQueue = {
     "RemoveCanceledTasksInTaskQueue2", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const BASE_EXPORT Feature kAddTaskLeewayFeature = {
+    "AddTaskLeeway", base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::FeatureParam<TimeDelta> kTaskLeewayParam{&kAddTaskLeewayFeature,
+                                                     "leeway", Milliseconds(8)};
+
 }  // namespace base
diff --git a/base/task/task_features.h b/base/task/task_features.h
index 5ff7e41..00086d6 100644
--- a/base/task/task_features.h
+++ b/base/task/task_features.h
@@ -71,6 +71,11 @@
 // Controls whether or not canceled delayed tasks are removed from task queues.
 extern const BASE_EXPORT base::Feature kRemoveCanceledTasksInTaskQueue;
 
+// Under this feature, a non-zero leeway is added to delayed tasks. Along with
+// DelayPolicy, this affects the time at which a delayed task runs.
+extern const BASE_EXPORT Feature kAddTaskLeewayFeature;
+extern const BASE_EXPORT base::FeatureParam<TimeDelta> kTaskLeewayParam;
+
 }  // namespace base
 
 #endif  // BASE_TASK_TASK_FEATURES_H_
diff --git a/base/task/thread_pool/delayed_task_manager.cc b/base/task/thread_pool/delayed_task_manager.cc
index b771e54..88dbf24 100644
--- a/base/task/thread_pool/delayed_task_manager.cc
+++ b/base/task/thread_pool/delayed_task_manager.cc
@@ -37,7 +37,8 @@
 
 bool DelayedTaskManager::DelayedTask::operator>(
     const DelayedTask& other) const {
-  return task > other.task;
+  return std::tie(task.delayed_run_time, task.sequence_num) >
+         std::tie(other.task.delayed_run_time, other.task.sequence_num);
 }
 
 bool DelayedTaskManager::DelayedTask::IsScheduled() const {
diff --git a/base/test/task_environment.cc b/base/test/task_environment.cc
index f3a2f89..69ddf77 100644
--- a/base/test/task_environment.cc
+++ b/base/test/task_environment.cc
@@ -678,7 +678,7 @@
     // FastForwardToNextTaskOrCap isn't affected by canceled tasks.
     sequence_manager_->ReclaimMemory();
   } while (mock_time_domain_->FastForwardToNextTaskOrCap(
-               sequence_manager_->GetNextWakeUp(), fast_forward_until) !=
+               sequence_manager_->GetNextDelayedWakeUp(), fast_forward_until) !=
            MockTimeDomain::NextTaskSource::kNone);
 
   if (task_tracker_ && !could_run_tasks)
@@ -731,7 +731,7 @@
   if (!sequence_manager_->IsIdleForTesting())
     return TimeDelta();
   absl::optional<sequence_manager::WakeUp> wake_up =
-      sequence_manager_->GetNextWakeUp();
+      sequence_manager_->GetNextDelayedWakeUp();
   return wake_up ? wake_up->time - lazy_now.Now() : TimeDelta::Max();
 }
 
diff --git a/base/values.cc b/base/values.cc
index 1cb7ce3..53622114 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -1000,7 +1000,7 @@
     }
     case Type::LIST: {
       perfetto::TracedArray array = std::move(context).WriteArray();
-      for (const auto& item : GetList())
+      for (const auto& item : GetListDeprecated())
         array.Append(item);
       return;
     }
diff --git a/base/values.h b/base/values.h
index 5bd69fd..99b3d7e 100644
--- a/base/values.h
+++ b/base/values.h
@@ -93,14 +93,21 @@
 //   void AlwaysTakesList(std::unique_ptr<base::ListValue> list);
 //   void AlwaysTakesDict(std::unique_ptr<base::DictionaryValue> dict);
 //
-// NEW WAY:
+// DEPRECATED WAY:
 //
 //   void AlwaysTakesList(std::vector<base::Value> list);
 //   void AlwaysTakesDict(base::flat_map<std::string, base::Value> dict);
 //
 // Migrating code will require conversions on API boundaries. This can be done
 // cheaply by making use of overloaded base::Value constructors and the
-// `Value::TakeList()` and `Value::TakeDict()` APIs.
+// `Value::TakeListDeprecated()` and `Value::TakeDictDeprecated()` APIs.
+//
+// NEW WAY:
+//
+// Proposed API:
+// https://docs.google.com/document/d/13M-yE39fQxjXOXJIfezkcqnZoc4OyCBIit2-yfmt9yE/edit?usp=sharing
+//
+// Not yet implemented.
 class BASE_EXPORT Value {
  public:
   using BlobStorage = std::vector<uint8_t>;
@@ -220,18 +227,16 @@
 
   // Returns the Values in a list as a view. The mutable overload allows for
   // modification of the underlying values, but does not allow changing the
-  // structure of the list. If this is desired, use `TakeList()`, perform the
-  // operations, and return the list back to the Value via move assignment.
+  // structure of the list. If this is desired, use `TakeListDeprecated()`,
+  // perform the operations, and return the list back to the Value via move
+  // assignment.
   DeprecatedListView GetListDeprecated();
   DeprecatedConstListView GetListDeprecated() const;
-  DeprecatedListView GetList() { return GetListDeprecated(); }
-  DeprecatedConstListView GetList() const { return GetListDeprecated(); }
 
   // Transfers ownership of the underlying list to the caller. Subsequent
-  // calls to `GetList()` will return an empty list.
+  // calls to `GetListDeprecated()` will return an empty list.
   // Note: This requires that `type()` is Type::LIST.
   DeprecatedListStorage TakeListDeprecated() &&;
-  ListStorage TakeList() && { return std::move(*this).TakeListDeprecated(); }
 
   // Appends `value` to the end of the list.
   // Note: These CHECK that `type()` is Type::LIST.
@@ -520,9 +525,6 @@
   // calls to DictItems() will return an empty dict.
   // Note: This requires that `type()` is Type::DICTIONARY.
   DeprecatedDictStorage TakeDictDeprecated() &&;
-  DeprecatedDictStorage TakeDict() && {
-    return std::move(*this).TakeDictDeprecated();
-  }
 
   // Returns the size of the dictionary, if the dictionary is empty, and clears
   // the dictionary. Note: These CHECK that `type()` is Type::DICTIONARY.
@@ -723,10 +725,10 @@
   // and Value's Dictionary API instead.
   bool GetDictionary(StringPiece path, DictionaryValue** out_value);
   // DEPRECATED, use `Value::FindListKey(key)` or `Value::FindListPath(path)`,
-  // and `Value::GetList()` instead.
+  // and `Value::GetListDeprecated()` instead.
   bool GetList(StringPiece path, const ListValue** out_value) const;
   // DEPRECATED, use `Value::FindListKey(key)` or `Value::FindListPath(path)`,
-  // and `Value::GetList()` instead.
+  // and `Value::GetListDeprecated()` instead.
   bool GetList(StringPiece path, ListValue** out_value);
 
   // Like `Get()`, but without special treatment of '.'.  This allows e.g. URLs
@@ -797,7 +799,7 @@
   // only if the index falls within the current list range.
   // Note that the list always owns the Value passed out via `out_value`.
   // `out_value` is optional and will only be set if non-NULL.
-  // DEPRECATED, use `GetList()::operator[] instead.
+  // DEPRECATED, use `GetListDeprecated()::operator[] instead.
   bool Get(size_t index, const Value** out_value) const;
   bool Get(size_t index, Value** out_value);
 
@@ -815,13 +817,13 @@
   void Append(std::unique_ptr<Value> in_value);
 
   // Swaps contents with the `other` list.
-  // DEPRECATED, use `GetList()::swap()` instead.
+  // DEPRECATED, use `GetListDeprecated()::swap()` instead.
   void Swap(ListValue* other);
 
   // Iteration.
   //
-  // ListValue no longer supports iteration. Instead, use GetList() to get the
-  // underlying list:
+  // ListValue no longer supports iteration. Instead, use GetListDeprecated() to
+  // get the underlying list:
   //
   // for (const auto& entry : list_value.GetListDeprecated()) {
   //   ...
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index f77817c..0a726474 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -215,18 +215,18 @@
   {
     ListValue value(storage);
     EXPECT_EQ(Value::Type::LIST, value.type());
-    EXPECT_EQ(1u, value.GetList().size());
-    EXPECT_EQ(Value::Type::STRING, value.GetList()[0].type());
-    EXPECT_EQ("foo", value.GetList()[0].GetString());
+    EXPECT_EQ(1u, value.GetListDeprecated().size());
+    EXPECT_EQ(Value::Type::STRING, value.GetListDeprecated()[0].type());
+    EXPECT_EQ("foo", value.GetListDeprecated()[0].GetString());
   }
 
   storage.back() = base::Value("bar");
   {
     ListValue value(std::move(storage));
     EXPECT_EQ(Value::Type::LIST, value.type());
-    EXPECT_EQ(1u, value.GetList().size());
-    EXPECT_EQ(Value::Type::STRING, value.GetList()[0].type());
-    EXPECT_EQ("bar", value.GetList()[0].GetString());
+    EXPECT_EQ(1u, value.GetListDeprecated().size());
+    EXPECT_EQ(Value::Type::STRING, value.GetListDeprecated()[0].type());
+    EXPECT_EQ("bar", value.GetListDeprecated()[0].GetString());
   }
 }
 
@@ -239,7 +239,7 @@
   EXPECT_DEATH_IF_SUPPORTED(value.GetString(), "");
   EXPECT_DEATH_IF_SUPPORTED(value.GetBlob(), "");
   EXPECT_DEATH_IF_SUPPORTED(value.DictItems(), "");
-  EXPECT_DEATH_IF_SUPPORTED(value.GetList(), "");
+  EXPECT_DEATH_IF_SUPPORTED(value.GetListDeprecated(), "");
 }
 
 // Group of tests for the copy constructors and copy-assigmnent. For equality
@@ -455,7 +455,7 @@
   Value value(std::move(storage));
 
   // Take ownership of the dict and make sure its contents are what we expect.
-  auto dict = std::move(value).TakeDict();
+  auto dict = std::move(value).TakeDictDeprecated();
   EXPECT_EQ(8u, dict.size());
   EXPECT_TRUE(dict["null"].is_none());
   EXPECT_TRUE(dict["bool"].is_bool());
@@ -476,12 +476,12 @@
   Value value(storage);
   Value moved_value(std::move(value));
   EXPECT_EQ(Value::Type::LIST, moved_value.type());
-  EXPECT_EQ(123, moved_value.GetList().back().GetInt());
+  EXPECT_EQ(123, moved_value.GetListDeprecated().back().GetInt());
 
   Value blank;
   blank = Value(std::move(storage));
   EXPECT_EQ(Value::Type::LIST, blank.type());
-  EXPECT_EQ(123, blank.GetList().back().GetInt());
+  EXPECT_EQ(123, blank.GetListDeprecated().back().GetInt());
 }
 
 TEST(ValuesTest, TakeList) {
@@ -497,7 +497,7 @@
   value.Append(Value(Value::Type::DICTIONARY));
 
   // Take ownership of the list and make sure its contents are what we expect.
-  auto list = std::move(value).TakeList();
+  auto list = std::move(value).TakeListDeprecated();
   EXPECT_EQ(8u, list.size());
   EXPECT_TRUE(list[0].is_none());
   EXPECT_TRUE(list[1].is_bool());
@@ -509,54 +509,56 @@
   EXPECT_TRUE(list[7].is_dict());
 
   // Validate that |value| no longer contains values.
-  EXPECT_TRUE(value.GetList().empty());
+  EXPECT_TRUE(value.GetListDeprecated().empty());
 }
 
 TEST(ValuesTest, Append) {
   ListValue value;
   value.Append(true);
-  EXPECT_TRUE(value.GetList().back().is_bool());
+  EXPECT_TRUE(value.GetListDeprecated().back().is_bool());
 
   value.Append(123);
-  EXPECT_TRUE(value.GetList().back().is_int());
+  EXPECT_TRUE(value.GetListDeprecated().back().is_int());
 
   value.Append(3.14);
-  EXPECT_TRUE(value.GetList().back().is_double());
+  EXPECT_TRUE(value.GetListDeprecated().back().is_double());
 
   std::string str = "foo";
   value.Append(str.c_str());
-  EXPECT_TRUE(value.GetList().back().is_string());
+  EXPECT_TRUE(value.GetListDeprecated().back().is_string());
 
   value.Append(StringPiece(str));
-  EXPECT_TRUE(value.GetList().back().is_string());
+  EXPECT_TRUE(value.GetListDeprecated().back().is_string());
 
   value.Append(std::move(str));
-  EXPECT_TRUE(value.GetList().back().is_string());
+  EXPECT_TRUE(value.GetListDeprecated().back().is_string());
 
   std::u16string str16 = u"bar";
   value.Append(str16.c_str());
-  EXPECT_TRUE(value.GetList().back().is_string());
+  EXPECT_TRUE(value.GetListDeprecated().back().is_string());
 
   value.Append(base::StringPiece16(str16));
-  EXPECT_TRUE(value.GetList().back().is_string());
+  EXPECT_TRUE(value.GetListDeprecated().back().is_string());
 
   value.Append(Value());
-  EXPECT_TRUE(value.GetList().back().is_none());
+  EXPECT_TRUE(value.GetListDeprecated().back().is_none());
 
   value.Append(Value(Value::Type::DICTIONARY));
-  EXPECT_TRUE(value.GetList().back().is_dict());
+  EXPECT_TRUE(value.GetListDeprecated().back().is_dict());
 
   value.Append(Value(Value::Type::LIST));
-  EXPECT_TRUE(value.GetList().back().is_list());
+  EXPECT_TRUE(value.GetListDeprecated().back().is_list());
 }
 
 TEST(ValuesTest, Insert) {
   ListValue value;
-  auto GetList = [&value]() -> decltype(auto) { return value.GetList(); };
-  auto GetConstList = [&value] { return as_const(value).GetList(); };
+  auto GetListDeprecated = [&value]() -> decltype(auto) {
+    return value.GetListDeprecated();
+  };
+  auto GetConstList = [&value] { return as_const(value).GetListDeprecated(); };
 
-  auto storage_iter = value.Insert(GetList().end(), Value(true));
-  EXPECT_TRUE(GetList().begin() == storage_iter);
+  auto storage_iter = value.Insert(GetListDeprecated().end(), Value(true));
+  EXPECT_TRUE(GetListDeprecated().begin() == storage_iter);
   EXPECT_TRUE(storage_iter->is_bool());
 
   auto span_iter = value.Insert(GetConstList().begin(), Value(123));
@@ -570,19 +572,19 @@
   value.Append(2);
   value.Append(3);
 
-  EXPECT_TRUE(value.EraseListIter(value.GetList().begin() + 1));
-  EXPECT_EQ(2u, value.GetList().size());
-  EXPECT_EQ(1, value.GetList()[0].GetInt());
-  EXPECT_EQ(3, value.GetList()[1].GetInt());
+  EXPECT_TRUE(value.EraseListIter(value.GetListDeprecated().begin() + 1));
+  EXPECT_EQ(2u, value.GetListDeprecated().size());
+  EXPECT_EQ(1, value.GetListDeprecated()[0].GetInt());
+  EXPECT_EQ(3, value.GetListDeprecated()[1].GetInt());
 
-  EXPECT_TRUE(value.EraseListIter(value.GetList().begin()));
-  EXPECT_EQ(1u, value.GetList().size());
-  EXPECT_EQ(3, value.GetList()[0].GetInt());
+  EXPECT_TRUE(value.EraseListIter(value.GetListDeprecated().begin()));
+  EXPECT_EQ(1u, value.GetListDeprecated().size());
+  EXPECT_EQ(3, value.GetListDeprecated()[0].GetInt());
 
-  EXPECT_TRUE(value.EraseListIter(value.GetList().begin()));
-  EXPECT_TRUE(value.GetList().empty());
+  EXPECT_TRUE(value.EraseListIter(value.GetListDeprecated().begin()));
+  EXPECT_TRUE(value.GetListDeprecated().empty());
 
-  EXPECT_FALSE(value.EraseListIter(value.GetList().begin()));
+  EXPECT_FALSE(value.EraseListIter(value.GetListDeprecated().begin()));
 }
 
 TEST(ValuesTest, EraseListValue) {
@@ -593,16 +595,16 @@
   value.Append(3);
 
   EXPECT_EQ(2u, value.EraseListValue(Value(2)));
-  EXPECT_EQ(2u, value.GetList().size());
-  EXPECT_EQ(1, value.GetList()[0].GetInt());
-  EXPECT_EQ(3, value.GetList()[1].GetInt());
+  EXPECT_EQ(2u, value.GetListDeprecated().size());
+  EXPECT_EQ(1, value.GetListDeprecated()[0].GetInt());
+  EXPECT_EQ(3, value.GetListDeprecated()[1].GetInt());
 
   EXPECT_EQ(1u, value.EraseListValue(Value(1)));
-  EXPECT_EQ(1u, value.GetList().size());
-  EXPECT_EQ(3, value.GetList()[0].GetInt());
+  EXPECT_EQ(1u, value.GetListDeprecated().size());
+  EXPECT_EQ(3, value.GetListDeprecated()[0].GetInt());
 
   EXPECT_EQ(1u, value.EraseListValue(Value(3)));
-  EXPECT_TRUE(value.GetList().empty());
+  EXPECT_TRUE(value.GetListDeprecated().empty());
 
   EXPECT_EQ(0u, value.EraseListValue(Value(3)));
 }
@@ -616,11 +618,11 @@
 
   EXPECT_EQ(3u, value.EraseListValueIf(
                     [](const auto& val) { return val >= Value(2); }));
-  EXPECT_EQ(1u, value.GetList().size());
-  EXPECT_EQ(1, value.GetList()[0].GetInt());
+  EXPECT_EQ(1u, value.GetListDeprecated().size());
+  EXPECT_EQ(1, value.GetListDeprecated()[0].GetInt());
 
   EXPECT_EQ(1u, value.EraseListValueIf([](const auto& val) { return true; }));
-  EXPECT_TRUE(value.GetList().empty());
+  EXPECT_TRUE(value.GetListDeprecated().empty());
 
   EXPECT_EQ(0u, value.EraseListValueIf([](const auto& val) { return true; }));
 }
@@ -630,14 +632,14 @@
   value.Append(1);
   value.Append(2);
   value.Append(3);
-  EXPECT_EQ(3u, value.GetList().size());
+  EXPECT_EQ(3u, value.GetListDeprecated().size());
 
   value.ClearList();
-  EXPECT_TRUE(value.GetList().empty());
+  EXPECT_TRUE(value.GetListDeprecated().empty());
 
   // ClearList() should be idempotent.
   value.ClearList();
-  EXPECT_TRUE(value.GetList().empty());
+  EXPECT_TRUE(value.GetListDeprecated().empty());
 }
 
 TEST(ValuesTest, FindKey) {
@@ -1369,8 +1371,8 @@
 
   Value* bookmark_list = settings.FindPath("global.toolbar.bookmarks");
   ASSERT_TRUE(bookmark_list);
-  ASSERT_EQ(1U, bookmark_list->GetList().size());
-  Value* bookmark = &bookmark_list->GetList()[0];
+  ASSERT_EQ(1U, bookmark_list->GetListDeprecated().size());
+  Value* bookmark = &bookmark_list->GetListDeprecated()[0];
   ASSERT_TRUE(bookmark);
   ASSERT_TRUE(bookmark->is_dict());
   const std::string* bookmark_name = bookmark->FindStringKey("name");
@@ -1388,7 +1390,7 @@
   mixed_list.Append(88.8);
   mixed_list.Append("foo");
 
-  Value::ConstListView list_view = mixed_list.GetList();
+  Value::ConstListView list_view = mixed_list.GetListDeprecated();
   ASSERT_EQ(4u, list_view.size());
 
   ASSERT_FALSE(list_view[0].is_int());
@@ -1453,9 +1455,9 @@
 TEST(ValuesTest, ListDeletion) {
   ListValue list;
   list.Append(std::make_unique<Value>());
-  EXPECT_FALSE(list.GetList().empty());
+  EXPECT_FALSE(list.GetListDeprecated().empty());
   list.ClearList();
-  EXPECT_TRUE(list.GetList().empty());
+  EXPECT_TRUE(list.GetListDeprecated().empty());
 }
 
 TEST(ValuesTest, DictionaryDeletion) {
@@ -1589,8 +1591,8 @@
   storage.emplace_back(0);
   storage.emplace_back(1);
   Value* list_weak = original_dict.SetKey("list", Value(std::move(storage)));
-  Value* list_element_0_weak = &list_weak->GetList()[0];
-  Value* list_element_1_weak = &list_weak->GetList()[1];
+  Value* list_element_0_weak = &list_weak->GetListDeprecated()[0];
+  Value* list_element_1_weak = &list_weak->GetListDeprecated()[1];
 
   Value* dict_weak = original_dict.SetKey(
       "dictionary", base::Value(base::Value::Type::DICTIONARY));
@@ -1657,7 +1659,7 @@
   ListValue* copy_list = nullptr;
   ASSERT_TRUE(copy_value->GetAsList(&copy_list));
   ASSERT_TRUE(copy_list);
-  ASSERT_EQ(2U, copy_list->GetList().size());
+  ASSERT_EQ(2U, copy_list->GetListDeprecated().size());
 
   Value* copy_list_element_0;
   ASSERT_TRUE(copy_list->Get(0, &copy_list_element_0));
@@ -1960,10 +1962,11 @@
 
     ListValue* inner_value;
     EXPECT_TRUE(root->GetList("list_with_empty_children", &inner_value));
-    ASSERT_EQ(1U, inner_value->GetList().size());  // Dictionary was pruned.
-    const Value& inner_value2 = inner_value->GetList()[0];
+    ASSERT_EQ(
+        1U, inner_value->GetListDeprecated().size());  // Dictionary was pruned.
+    const Value& inner_value2 = inner_value->GetListDeprecated()[0];
     ASSERT_TRUE(inner_value2.is_list());
-    EXPECT_EQ(1U, inner_value2.GetList().size());
+    EXPECT_EQ(1U, inner_value2.GetListDeprecated().size());
   }
 }
 
diff --git a/build/config/fuchsia/test/test_logger_capabilities.test-cmx b/build/config/fuchsia/test/test_logger_capabilities.test-cmx
deleted file mode 100644
index 68b2a67..0000000
--- a/build/config/fuchsia/test/test_logger_capabilities.test-cmx
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "sandbox": {
-    "services": [
-      "fuchsia.logger.Log"
-    ]
-  }
-}
\ No newline at end of file
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 55d38c7..3b9cc9d 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-7.20220204.2.1
+7.20220206.0.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 55d38c7..7128965d 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-7.20220204.2.1
+7.20220205.3.1
diff --git a/cc/animation/animation.cc b/cc/animation/animation.cc
index 3b1dced3..cabe6da 100644
--- a/cc/animation/animation.cc
+++ b/cc/animation/animation.cc
@@ -26,17 +26,13 @@
   return base::WrapRefCounted(new Animation(id));
 }
 
-Animation::Animation(int id)
-    : animation_host_(),
-      animation_timeline_(),
-      animation_delegate_(),
-      id_(id),
-      keyframe_effect_(std::make_unique<KeyframeEffect>(this)) {
+Animation::Animation(int id) : id_(id) {
   DCHECK(id_);
+  keyframe_effect_.Write(*this) = std::make_unique<KeyframeEffect>(this);
 }
 
 Animation::~Animation() {
-  DCHECK(!animation_timeline_);
+  DCHECK(!animation_timeline());
 }
 
 scoped_refptr<Animation> Animation::CreateImplInstance() const {
@@ -44,33 +40,39 @@
 }
 
 ElementId Animation::element_id() const {
-  return keyframe_effect_->element_id();
+  return keyframe_effect()->element_id();
 }
 
 void Animation::SetAnimationHost(AnimationHost* animation_host) {
+  DCHECK(IsOwnerThread());
+  if (animation_host == animation_host_)
+    return;
+
+  WaitForProtectedSequenceCompletion();
+
   animation_host_ = animation_host;
 }
 
 void Animation::SetAnimationTimeline(AnimationTimeline* timeline) {
-  if (animation_timeline_ == timeline)
+  if (animation_timeline() == timeline)
     return;
 
   // We need to unregister the animation to manage ElementAnimations and
   // observers properly.
-  if (keyframe_effect_->has_attached_element() &&
-      keyframe_effect_->has_bound_element_animations()) {
+  if (keyframe_effect()->has_attached_element() &&
+      keyframe_effect()->has_bound_element_animations()) {
     UnregisterAnimation();
   }
 
-  animation_timeline_ = timeline;
+  animation_timeline_.Write(*this) = timeline;
 
   // Register animation only if layer AND host attached.
-  if (keyframe_effect_->has_attached_element() && animation_host_)
+  if (keyframe_effect()->has_attached_element() && animation_host())
     RegisterAnimation();
 }
 
-scoped_refptr<ElementAnimations> Animation::element_animations() const {
-  return keyframe_effect_->element_animations();
+scoped_refptr<const ElementAnimations> Animation::element_animations() const {
+  return keyframe_effect()->element_animations();
 }
 
 void Animation::AttachElement(ElementId element_id) {
@@ -83,48 +85,61 @@
 }
 
 void Animation::AttachElementInternal(ElementId element_id) {
-  keyframe_effect_->AttachElement(element_id);
+  keyframe_effect()->AttachElement(element_id);
   // Register animation only if layer AND host attached.
-  if (animation_host_)
+  if (animation_host())
     RegisterAnimation();
 }
 
 void Animation::SetKeyframeEffectForTesting(
     std::unique_ptr<KeyframeEffect> effect) {
-  keyframe_effect_ = std::move(effect);
+  keyframe_effect_.Write(*this) = std::move(effect);
+}
+
+bool Animation::IsOwnerThread() const {
+  return !animation_host_ || animation_host_->IsOwnerThread();
+}
+
+bool Animation::InProtectedSequence() const {
+  return !animation_host_ || animation_host_->InProtectedSequence();
+}
+
+void Animation::WaitForProtectedSequenceCompletion() const {
+  if (animation_host_)
+    animation_host_->WaitForProtectedSequenceCompletion();
 }
 
 void Animation::DetachElement() {
-  DCHECK(keyframe_effect_->has_attached_element());
+  DCHECK(keyframe_effect()->has_attached_element());
 
-  if (animation_host_)
+  if (animation_host())
     UnregisterAnimation();
 
-  keyframe_effect_->DetachElement();
+  keyframe_effect()->DetachElement();
 }
 
 void Animation::RegisterAnimation() {
-  DCHECK(animation_host_);
-  DCHECK(keyframe_effect_->has_attached_element());
-  DCHECK(!keyframe_effect_->has_bound_element_animations());
+  DCHECK(animation_host());
+  DCHECK(keyframe_effect()->has_attached_element());
+  DCHECK(!keyframe_effect()->has_bound_element_animations());
 
   // Create ElementAnimations or re-use existing.
-  animation_host_->RegisterAnimationForElement(keyframe_effect_->element_id(),
-                                               this);
+  animation_host()->RegisterAnimationForElement(keyframe_effect()->element_id(),
+                                                this);
 }
 
 void Animation::UnregisterAnimation() {
-  DCHECK(animation_host_);
-  DCHECK(keyframe_effect_->has_attached_element());
-  DCHECK(keyframe_effect_->has_bound_element_animations());
+  DCHECK(animation_host());
+  DCHECK(keyframe_effect()->has_attached_element());
+  DCHECK(keyframe_effect()->has_bound_element_animations());
 
   // Destroy ElementAnimations or release it if it's still needed.
-  animation_host_->UnregisterAnimationForElement(keyframe_effect_->element_id(),
-                                                 this);
+  animation_host()->UnregisterAnimationForElement(
+      keyframe_effect()->element_id(), this);
 }
 
 void Animation::PushPropertiesTo(Animation* animation_impl) {
-  keyframe_effect_->PushPropertiesTo(animation_impl->keyframe_effect_.get());
+  keyframe_effect()->PushPropertiesTo(animation_impl->keyframe_effect());
 }
 
 void Animation::Tick(base::TimeTicks tick_time) {
@@ -140,39 +155,39 @@
     // time and then ticks it which side-steps the start time altogether. See
     // crbug.com/1076012 for alternative design choices considered for future
     // improvement.
-    keyframe_effect_->Pause(tick_time - base::TimeTicks(),
-                            PauseCondition::kAfterStart);
-    keyframe_effect_->Tick(base::TimeTicks());
+    keyframe_effect()->Pause(tick_time - base::TimeTicks(),
+                             PauseCondition::kAfterStart);
+    keyframe_effect()->Tick(base::TimeTicks());
   } else {
     DCHECK(!tick_time.is_null());
-    keyframe_effect_->Tick(tick_time);
+    keyframe_effect()->Tick(tick_time);
   }
 }
 
 bool Animation::IsScrollLinkedAnimation() const {
-  return animation_timeline_ && animation_timeline_->IsScrollTimeline();
+  return animation_timeline() && animation_timeline()->IsScrollTimeline();
 }
 
 void Animation::UpdateState(bool start_ready_animations,
                             AnimationEvents* events) {
-  keyframe_effect_->UpdateState(start_ready_animations, events);
-  keyframe_effect_->UpdateTickingState();
+  keyframe_effect()->UpdateState(start_ready_animations, events);
+  keyframe_effect()->UpdateTickingState();
 }
 
 void Animation::AddToTicking() {
-  DCHECK(animation_host_);
-  animation_host_->AddToTicking(this);
+  DCHECK(animation_host());
+  animation_host()->AddToTicking(this);
 }
 
 void Animation::RemoveFromTicking() {
-  DCHECK(animation_host_);
-  animation_host_->RemoveFromTicking(this);
+  DCHECK(animation_host());
+  animation_host()->RemoveFromTicking(this);
 }
 
 void Animation::DispatchAndDelegateAnimationEvent(const AnimationEvent& event) {
   if (event.ShouldDispatchToKeyframeEffectAndModel()) {
-    if (!keyframe_effect_ ||
-        !keyframe_effect_->DispatchAnimationEventToKeyframeModel(event)) {
+    if (!keyframe_effect() ||
+        !keyframe_effect()->DispatchAnimationEventToKeyframeModel(event)) {
       // If we fail to dispatch the event, it is to clean up an obsolete
       // animation and should not notify the delegate.
       // TODO(gerchiko): Determine when we expect the referenced animations not
@@ -220,40 +235,40 @@
 }
 
 bool Animation::RequiresInvalidation() const {
-  return keyframe_effect_->RequiresInvalidation();
+  return keyframe_effect()->RequiresInvalidation();
 }
 
 bool Animation::AffectsNativeProperty() const {
-  return keyframe_effect_->AffectsNativeProperty();
+  return keyframe_effect()->AffectsNativeProperty();
 }
 
 void Animation::SetNeedsCommit() {
-  DCHECK(animation_host_);
-  animation_host_->SetNeedsCommit();
+  DCHECK(animation_host());
+  animation_host()->SetNeedsCommit();
 }
 
 void Animation::SetNeedsPushProperties() {
-  if (!animation_timeline_)
+  if (!animation_timeline())
     return;
-  animation_timeline_->SetNeedsPushProperties();
+  animation_timeline()->SetNeedsPushProperties();
 }
 
 void Animation::ActivateKeyframeModels() {
-  keyframe_effect_->ActivateKeyframeModels();
-  keyframe_effect_->UpdateTickingState();
+  keyframe_effect()->ActivateKeyframeModels();
+  keyframe_effect()->UpdateTickingState();
 }
 
 KeyframeModel* Animation::GetKeyframeModel(
     TargetProperty::Type target_property) const {
   return KeyframeModel::ToCcKeyframeModel(
-      keyframe_effect_->GetKeyframeModel(target_property));
+      keyframe_effect()->GetKeyframeModel(target_property));
 }
 
 std::string Animation::ToString() const {
   return base::StringPrintf(
       "Animation{id=%d, element_id=%s, keyframe_models=[%s]}", id_,
-      keyframe_effect_->element_id().ToString().c_str(),
-      keyframe_effect_->KeyframeModelsToString().c_str());
+      keyframe_effect()->element_id().ToString().c_str(),
+      keyframe_effect()->KeyframeModelsToString().c_str());
 }
 
 bool Animation::IsWorkletAnimation() const {
@@ -262,27 +277,27 @@
 
 void Animation::AddKeyframeModel(
     std::unique_ptr<KeyframeModel> keyframe_model) {
-  keyframe_effect_->AddKeyframeModel(std::move(keyframe_model));
+  keyframe_effect()->AddKeyframeModel(std::move(keyframe_model));
 }
 
 void Animation::PauseKeyframeModel(int keyframe_model_id,
                                    base::TimeDelta time_offset) {
-  keyframe_effect_->PauseKeyframeModel(keyframe_model_id, time_offset);
+  keyframe_effect()->PauseKeyframeModel(keyframe_model_id, time_offset);
 }
 
 void Animation::RemoveKeyframeModel(int keyframe_model_id) {
-  keyframe_effect_->RemoveKeyframeModel(keyframe_model_id);
+  keyframe_effect()->RemoveKeyframeModel(keyframe_model_id);
 }
 
 void Animation::AbortKeyframeModel(int keyframe_model_id) {
-  keyframe_effect_->AbortKeyframeModel(keyframe_model_id);
+  keyframe_effect()->AbortKeyframeModel(keyframe_model_id);
 }
 
 void Animation::AbortKeyframeModelsWithProperty(
     TargetProperty::Type target_property,
     bool needs_completion) {
-  keyframe_effect_->AbortKeyframeModelsWithProperty(target_property,
-                                                    needs_completion);
+  keyframe_effect()->AbortKeyframeModelsWithProperty(target_property,
+                                                     needs_completion);
 }
 
 void Animation::NotifyKeyframeModelFinishedForTesting(
diff --git a/cc/animation/animation.h b/cc/animation/animation.h
index 9902f78..6e1a6bf1 100644
--- a/cc/animation/animation.h
+++ b/cc/animation/animation.h
@@ -15,6 +15,7 @@
 #include "cc/animation/animation_export.h"
 #include "cc/animation/element_animations.h"
 #include "cc/animation/keyframe_model.h"
+#include "cc/base/protected_sequence_synchronizer.h"
 #include "cc/paint/element_id.h"
 #include "ui/gfx/animation/keyframe/animation_curve.h"
 
@@ -41,7 +42,8 @@
 // synchronizing to/from the impl thread when requested.
 //
 // There is a 1:1 relationship between Animation and KeyframeEffect.
-class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> {
+class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation>,
+                                      public ProtectedSequenceSynchronizer {
  public:
   static scoped_refptr<Animation> Create(int id);
   virtual scoped_refptr<Animation> CreateImplInstance() const;
@@ -52,22 +54,36 @@
   int id() const { return id_; }
   ElementId element_id() const;
 
-  KeyframeEffect* keyframe_effect() const { return keyframe_effect_.get(); }
+  KeyframeEffect* keyframe_effect() {
+    return keyframe_effect_.Write(*this).get();
+  }
+
+  const KeyframeEffect* keyframe_effect() const {
+    return keyframe_effect_.Read(*this).get();
+  }
 
   // Parent AnimationHost. Animation can be detached from AnimationTimeline.
-  AnimationHost* animation_host() { return animation_host_; }
-  const AnimationHost* animation_host() const { return animation_host_; }
+  AnimationHost* animation_host() {
+    DCHECK(IsOwnerThread() || InProtectedSequence());
+    return animation_host_;
+  }
+  const AnimationHost* animation_host() const {
+    DCHECK(IsOwnerThread() || InProtectedSequence());
+    return animation_host_;
+  }
   void SetAnimationHost(AnimationHost* animation_host);
-  bool has_animation_host() const { return !!animation_host_; }
+  bool has_animation_host() const { return !!animation_host(); }
 
   // Parent AnimationTimeline.
-  AnimationTimeline* animation_timeline() { return animation_timeline_; }
+  AnimationTimeline* animation_timeline() {
+    return animation_timeline_.Read(*this);
+  }
   const AnimationTimeline* animation_timeline() const {
-    return animation_timeline_;
+    return animation_timeline_.Read(*this);
   }
   void SetAnimationTimeline(AnimationTimeline* timeline);
 
-  scoped_refptr<ElementAnimations> element_animations() const;
+  scoped_refptr<const ElementAnimations> element_animations() const;
 
   void set_animation_delegate(AnimationDelegate* delegate) {
     animation_delegate_ = delegate;
@@ -143,6 +159,11 @@
 
   void SetKeyframeEffectForTesting(std::unique_ptr<KeyframeEffect>);
 
+  // ProtectedSequenceSynchronizer implementation
+  bool IsOwnerThread() const override;
+  bool InProtectedSequence() const override;
+  void WaitForProtectedSequenceCompletion() const override;
+
  private:
   friend class base::RefCounted<Animation>;
 
@@ -157,14 +178,20 @@
 
  protected:
   explicit Animation(int id);
-  virtual ~Animation();
+  ~Animation() override;
 
-  raw_ptr<AnimationHost> animation_host_;
-  raw_ptr<AnimationTimeline> animation_timeline_;
-  raw_ptr<AnimationDelegate> animation_delegate_;
+  raw_ptr<AnimationDelegate> animation_delegate_ = nullptr;
 
   const int id_;
-  std::unique_ptr<KeyframeEffect> keyframe_effect_;
+
+ private:
+  // Animation's ProtectedSequenceSynchronizer implementation is implemented
+  // using this member. As such the various helpers can not be used to protect
+  // access (otherwise we would get infinite recursion).
+  raw_ptr<AnimationHost> animation_host_ = nullptr;
+  ProtectedSequenceReadable<raw_ptr<AnimationTimeline>> animation_timeline_{
+      nullptr};
+  ProtectedSequenceWritable<std::unique_ptr<KeyframeEffect>> keyframe_effect_;
 };
 
 }  // namespace cc
diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc
index 3733889..601f126 100644
--- a/cc/animation/animation_host.cc
+++ b/cc/animation/animation_host.cc
@@ -77,11 +77,17 @@
   return mutator_host_impl;
 }
 
-AnimationTimeline* AnimationHost::GetTimelineById(int timeline_id) const {
+const AnimationTimeline* AnimationHost::GetTimelineById(int timeline_id) const {
   auto f = id_to_timeline_map_.Read(*this).find(timeline_id);
   return f == id_to_timeline_map_.Read(*this).end() ? nullptr : f->second.get();
 }
 
+AnimationTimeline* AnimationHost::GetTimelineById(int timeline_id) {
+  auto f = id_to_timeline_map_.Write(*this).find(timeline_id);
+  return f == id_to_timeline_map_.Write(*this).end() ? nullptr
+                                                     : f->second.get();
+}
+
 void AnimationHost::ClearMutators() {
   for (auto& kv : id_to_timeline_map_.Read(*this))
     EraseTimeline(kv.second);
@@ -165,7 +171,7 @@
 }
 
 void AnimationHost::UpdateRegisteredElementIds(ElementListType changed_list) {
-  for (auto map_entry : element_to_animations_map_.Read(*this)) {
+  for (auto map_entry : element_to_animations_map_.Write(*this)) {
     // kReservedElementId is reserved for a paint worklet element that animates
     // a custom property. This element is assumed to always be present as no
     // element is needed to tick this animation.
@@ -180,7 +186,7 @@
 }
 
 void AnimationHost::InitClientAnimationState() {
-  for (auto map_entry : element_to_animations_map_.Read(*this))
+  for (auto map_entry : element_to_animations_map_.Write(*this))
     map_entry.second->InitClientAnimationState();
 }
 
@@ -338,7 +344,7 @@
 void AnimationHost::PushTimelinesToImplThread(AnimationHost* host_impl) const {
   for (auto& kv : id_to_timeline_map_.Read(*this)) {
     auto& timeline = kv.second;
-    AnimationTimeline* timeline_impl =
+    const AnimationTimeline* timeline_impl =
         host_impl->GetTimelineById(timeline->id());
     if (timeline_impl)
       continue;
@@ -389,8 +395,8 @@
   }
 
   // Update the impl-only scroll offset animations.
-  scroll_offset_animations_.Read(*this)->PushPropertiesTo(
-      host_impl->scroll_offset_animations_impl_.Read(*host_impl).get());
+  scroll_offset_animations_.Write(*this)->PushPropertiesTo(
+      host_impl->scroll_offset_animations_impl_.Write(*host_impl).get());
 
   // The pending info list is cleared in LayerTreeHostImpl::CommitComplete
   // and should be empty when pushing properties.
@@ -399,7 +405,7 @@
       TakePendingThroughputTrackerInfos();
 }
 
-scoped_refptr<ElementAnimations>
+scoped_refptr<const ElementAnimations>
 AnimationHost::GetElementAnimationsForElementId(ElementId element_id) const {
   if (!element_id)
     return nullptr;
@@ -408,6 +414,15 @@
                                                               : iter->second;
 }
 
+scoped_refptr<ElementAnimations>
+AnimationHost::GetElementAnimationsForElementId(ElementId element_id) {
+  if (!element_id)
+    return nullptr;
+  auto iter = element_to_animations_map_.Write(*this).find(element_id);
+  return iter == element_to_animations_map_.Write(*this).end() ? nullptr
+                                                               : iter->second;
+}
+
 gfx::PointF AnimationHost::GetScrollOffsetForAnimation(
     ElementId element_id) const {
   DCHECK(property_trees_);
@@ -739,7 +754,7 @@
     float autoscroll_velocity,
     base::TimeDelta animation_start_offset) {
   DCHECK(scroll_offset_animations_impl_.Read(*this));
-  scroll_offset_animations_impl_.Read(*this)->AutoScrollAnimationCreate(
+  scroll_offset_animations_impl_.Write(*this)->AutoScrollAnimationCreate(
       element_id, target_offset, current_offset, autoscroll_velocity,
       animation_start_offset);
 }
@@ -751,7 +766,7 @@
     base::TimeDelta delayed_by,
     base::TimeDelta animation_start_offset) {
   DCHECK(scroll_offset_animations_impl_.Read(*this));
-  scroll_offset_animations_impl_.Read(*this)->MouseWheelScrollAnimationCreate(
+  scroll_offset_animations_impl_.Write(*this)->MouseWheelScrollAnimationCreate(
       element_id, target_offset, current_offset, delayed_by,
       animation_start_offset);
 }
@@ -762,19 +777,19 @@
     base::TimeTicks frame_monotonic_time,
     base::TimeDelta delayed_by) {
   DCHECK(scroll_offset_animations_impl_.Read(*this));
-  return scroll_offset_animations_impl_.Read(*this)
+  return scroll_offset_animations_impl_.Write(*this)
       ->ScrollAnimationUpdateTarget(scroll_delta, max_scroll_offset,
                                     frame_monotonic_time, delayed_by);
 }
 
-ScrollOffsetAnimations& AnimationHost::scroll_offset_animations() const {
+ScrollOffsetAnimations& AnimationHost::scroll_offset_animations() {
   DCHECK(scroll_offset_animations_.Read(*this));
-  return *scroll_offset_animations_.Read(*this).get();
+  return *scroll_offset_animations_.Write(*this).get();
 }
 
 void AnimationHost::ScrollAnimationAbort() {
   DCHECK(scroll_offset_animations_impl_.Read(*this));
-  scroll_offset_animations_impl_.Read(*this)->ScrollAnimationAbort(
+  scroll_offset_animations_impl_.Write(*this)->ScrollAnimationAbort(
       false /* needs_completion */);
 }
 
@@ -811,7 +826,7 @@
 void AnimationHost::SetLayerTreeMutator(
     std::unique_ptr<LayerTreeMutator> mutator) {
   mutator_.Write(*this) = std::move(mutator);
-  mutator_.Read(*this)->SetClient(this);
+  mutator_.Write(*this)->SetClient(this);
 }
 
 WorkletAnimation* AnimationHost::FindWorkletAnimation(WorkletAnimationId id) {
diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h
index db533800..e180a98 100644
--- a/cc/animation/animation_host.h
+++ b/cc/animation/animation_host.h
@@ -63,14 +63,17 @@
 
   void AddAnimationTimeline(scoped_refptr<AnimationTimeline> timeline);
   void RemoveAnimationTimeline(scoped_refptr<AnimationTimeline> timeline);
-  AnimationTimeline* GetTimelineById(int timeline_id) const;
+  const AnimationTimeline* GetTimelineById(int timeline_id) const;
+  AnimationTimeline* GetTimelineById(int timeline_id);
 
   void RegisterAnimationForElement(ElementId element_id, Animation* animation);
   void UnregisterAnimationForElement(ElementId element_id,
                                      Animation* animation);
 
-  scoped_refptr<ElementAnimations> GetElementAnimationsForElementId(
+  scoped_refptr<const ElementAnimations> GetElementAnimationsForElementId(
       ElementId element_id) const;
+  scoped_refptr<ElementAnimations> GetElementAnimationsForElementId(
+      ElementId element_id);
 
   gfx::PointF GetScrollOffsetForAnimation(ElementId element_id) const;
 
@@ -198,7 +201,7 @@
   ElementId ImplOnlyScrollAnimatingElement() const override;
 
   // This should only be called from the main thread.
-  ScrollOffsetAnimations& scroll_offset_animations() const;
+  ScrollOffsetAnimations& scroll_offset_animations();
 
   // Registers the given animation as ticking. A ticking animation is one that
   // has a running keyframe model.
@@ -284,7 +287,7 @@
   // will be non-null for a given AnimationHost instance (the former if
   // thread_instance_ == ThreadInstance::MAIN, the latter if thread_instance_ ==
   // ThreadInstance::IMPL).
-  ProtectedSequenceReadable<std::unique_ptr<ScrollOffsetAnimations>>
+  ProtectedSequenceWritable<std::unique_ptr<ScrollOffsetAnimations>>
       scroll_offset_animations_;
   ProtectedSequenceReadable<std::unique_ptr<ScrollOffsetAnimationsImpl>>
       scroll_offset_animations_impl_;
diff --git a/cc/animation/animation_timeline.h b/cc/animation/animation_timeline.h
index c38edc0..0aed669 100644
--- a/cc/animation/animation_timeline.h
+++ b/cc/animation/animation_timeline.h
@@ -87,7 +87,7 @@
 
   void EraseAnimation(scoped_refptr<Animation> animation);
 
-  int id_;
+  const int id_;
   raw_ptr<AnimationHost> animation_host_;
   bool needs_push_properties_;
 
diff --git a/cc/animation/element_animations_unittest.cc b/cc/animation/element_animations_unittest.cc
index d68ba61..16101853 100644
--- a/cc/animation/element_animations_unittest.cc
+++ b/cc/animation/element_animations_unittest.cc
@@ -174,7 +174,7 @@
   timeline_->AttachAnimation(animation_);
   animation_->AttachElement(element_id_);
 
-  scoped_refptr<ElementAnimations> element_animations =
+  scoped_refptr<const ElementAnimations> element_animations =
       animation_->keyframe_effect()->element_animations();
   EXPECT_TRUE(element_animations);
 
@@ -198,7 +198,7 @@
   PushProperties();
   GetImplTimelineAndAnimationByID();
 
-  scoped_refptr<ElementAnimations> element_animations_impl =
+  scoped_refptr<const ElementAnimations> element_animations_impl =
       animation_impl_->keyframe_effect()->element_animations();
   EXPECT_TRUE(element_animations_impl);
 
@@ -3982,7 +3982,8 @@
 
   // The client should call this function which should refresh all data of the
   // client.
-  element_animations_->InitClientAnimationState();
+  const_cast<ElementAnimations*>(element_animations_.get())
+      ->InitClientAnimationState();
   EXPECT_TRUE(layer->is_currently_animating(TargetProperty::TRANSFORM));
   EXPECT_EQ(1.f, layer->maximum_animation_scale());
 }
diff --git a/cc/animation/keyframe_effect.cc b/cc/animation/keyframe_effect.cc
index def46c08..08d2cb0 100644
--- a/cc/animation/keyframe_effect.cc
+++ b/cc/animation/keyframe_effect.cc
@@ -68,7 +68,7 @@
   // TODO(smcgruer): We only need the below calls when needs_push_properties_
   // goes from false to true - see http://crbug.com/764405
   DCHECK(element_animations());
-  element_animations()->SetNeedsPushProperties();
+  element_animations_->SetNeedsPushProperties();
 
   animation_->SetNeedsPushProperties();
 }
diff --git a/cc/animation/keyframe_effect.h b/cc/animation/keyframe_effect.h
index ab77c96d..4105805 100644
--- a/cc/animation/keyframe_effect.h
+++ b/cc/animation/keyframe_effect.h
@@ -49,7 +49,7 @@
   KeyframeEffect& operator=(const KeyframeEffect&) = delete;
 
   // ElementAnimations object where this controller is listed.
-  scoped_refptr<ElementAnimations> element_animations() const {
+  scoped_refptr<const ElementAnimations> element_animations() const {
     return element_animations_;
   }
 
diff --git a/cc/animation/scroll_timeline.h b/cc/animation/scroll_timeline.h
index fc9784d..a654855 100644
--- a/cc/animation/scroll_timeline.h
+++ b/cc/animation/scroll_timeline.h
@@ -118,6 +118,12 @@
   return static_cast<ScrollTimeline*>(timeline);
 }
 
+inline const ScrollTimeline* ToScrollTimeline(
+    const AnimationTimeline* timeline) {
+  DCHECK(timeline->IsScrollTimeline());
+  return static_cast<const ScrollTimeline*>(timeline);
+}
+
 // https://drafts.csswg.org/scroll-animations-1/#progress-calculation-algorithm
 template <typename T>
 double ComputeProgress(double current_offset, const T& resolved_offsets) {
diff --git a/cc/animation/worklet_animation.cc b/cc/animation/worklet_animation.cc
index 72fec0e..96c523a 100644
--- a/cc/animation/worklet_animation.cc
+++ b/cc/animation/worklet_animation.cc
@@ -19,22 +19,16 @@
     int cc_animation_id,
     WorkletAnimationId worklet_animation_id,
     const std::string& name,
-    double playback_rate,
+    double playback_rate_value,
     std::unique_ptr<AnimationOptions> options,
     std::unique_ptr<AnimationEffectTimings> effect_timings,
     bool is_controlling_instance)
     : Animation(cc_animation_id),
       worklet_animation_id_(worklet_animation_id),
       name_(name),
-      playback_rate_(playback_rate),
+      playback_rate_(playback_rate_value),
       options_(std::move(options)),
       effect_timings_(std::move(effect_timings)),
-      local_time_(absl::nullopt),
-      last_synced_local_time_(absl::nullopt),
-      start_time_(absl::nullopt),
-      last_current_time_(absl::nullopt),
-      has_pending_tree_lock_(false),
-      state_(State::PENDING),
       is_impl_instance_(is_controlling_instance) {}
 
 WorkletAnimation::~WorkletAnimation() = default;
@@ -42,24 +36,25 @@
 scoped_refptr<WorkletAnimation> WorkletAnimation::Create(
     WorkletAnimationId worklet_animation_id,
     const std::string& name,
-    double playback_rate,
+    double playback_rate_value,
     std::unique_ptr<AnimationOptions> options,
     std::unique_ptr<AnimationEffectTimings> effect_timings) {
   return WrapRefCounted(new WorkletAnimation(
       AnimationIdProvider::NextAnimationId(), worklet_animation_id, name,
-      playback_rate, std::move(options), std::move(effect_timings), false));
+      playback_rate_value, std::move(options), std::move(effect_timings),
+      false));
 }
 
 scoped_refptr<Animation> WorkletAnimation::CreateImplInstance() const {
   return WrapRefCounted(
-      new WorkletAnimation(id(), worklet_animation_id_, name(), playback_rate_,
+      new WorkletAnimation(id(), worklet_animation_id_, name(), playback_rate(),
                            CloneOptions(), CloneEffectTimings(), true));
 }
 
 void WorkletAnimation::PushPropertiesTo(Animation* animation_impl) {
   Animation::PushPropertiesTo(animation_impl);
   WorkletAnimation* worklet_animation_impl = ToWorkletAnimation(animation_impl);
-  worklet_animation_impl->SetPlaybackRate(playback_rate_);
+  worklet_animation_impl->SetPlaybackRate(playback_rate());
 }
 
 void WorkletAnimation::Tick(base::TimeTicks monotonic_time) {
@@ -67,30 +62,31 @@
   // compositor and the tick is more expensive than regular animations.
   if (!is_impl_instance_)
     return;
-  if (!local_time_.has_value())
+  if (!local_time_.Read(*this).has_value())
     return;
   // As the output of a WorkletAnimation is driven by a script-provided local
   // time, we don't want the underlying effect to participate in the normal
   // animations lifecycle. To avoid this we pause the underlying keyframe effect
   // at the local time obtained from the user script - essentially turning each
   // call to |WorkletAnimation::Tick| into a seek in the effect.
-  keyframe_effect_->Pause(local_time_.value());
-  keyframe_effect_->Tick(base::TimeTicks());
+  keyframe_effect()->Pause(local_time_.Read(*this).value());
+  keyframe_effect()->Tick(base::TimeTicks());
 }
 
 void WorkletAnimation::UpdateState(bool start_ready_animations,
                                    AnimationEvents* events) {
   Animation::UpdateState(start_ready_animations, events);
-  if (last_synced_local_time_ != local_time_)
+  if (last_synced_local_time_.Read(*this) != local_time_.Read(*this))
     events->set_needs_time_updated_events(true);
 }
 
 void WorkletAnimation::TakeTimeUpdatedEvent(AnimationEvents* events) {
   DCHECK(events->needs_time_updated_events());
-  if (last_synced_local_time_ != local_time_) {
-    AnimationEvent event(animation_timeline()->id(), id_, local_time_);
+  if (last_synced_local_time_.Read(*this) != local_time_.Read(*this)) {
+    AnimationEvent event(animation_timeline()->id(), id_,
+                         local_time_.Read(*this));
     events->events_.push_back(event);
-    last_synced_local_time_ = local_time_;
+    last_synced_local_time_.Write(*this) = local_time_.Read(*this);
   }
 }
 
@@ -105,11 +101,12 @@
   // See: https://github.com/w3c/csswg-drafts/issues/2075
   // To stay consistent with blink::WorkletAnimation, record start time only
   // when the timeline becomes active.
-  if (!start_time_.has_value() && is_timeline_active)
-    start_time_ = animation_timeline_->IsScrollTimeline() ? base::TimeTicks()
-                                                          : monotonic_time;
+  if (!start_time_.Read(*this).has_value() && is_timeline_active)
+    start_time_.Write(*this) = animation_timeline()->IsScrollTimeline()
+                                   ? base::TimeTicks()
+                                   : monotonic_time;
 
-  if (is_active_tree && has_pending_tree_lock_)
+  if (is_active_tree && has_pending_tree_lock_.Read(*this))
     return;
 
   // Skip running worklet animations with unchanged input time and reuse
@@ -117,7 +114,7 @@
   if (!NeedsUpdate(monotonic_time, scroll_tree, is_active_tree))
     return;
 
-  DCHECK(is_timeline_active || state_ == State::REMOVED);
+  DCHECK(is_timeline_active || state_.Read(*this) == State::REMOVED);
 
   // TODO(https://crbug.com/1011138): Initialize current_time to null if the
   // timeline is inactive. It might be inactive here when state is
@@ -130,25 +127,25 @@
   // means we don't need to produce any new input state. See also:
   // https://drafts.csswg.org/web-animations/#responding-to-a-newly-inactive-timeline
   if (!is_timeline_active)
-    current_time = last_current_time_;
+    current_time = last_current_time_.Read(*this);
 
   // TODO(https://crbug.com/1011138): Do not early exit if state is
   // State::REMOVED. The animation must be removed in this case.
   if (!current_time)
     return;
-  last_current_time_ = current_time;
+  last_current_time_.Write(*this) = current_time;
 
   // Prevent active tree mutations from queuing up until pending tree is
   // activated to preserve flow of time for scroll timelines.
-  has_pending_tree_lock_ =
-      !is_active_tree && animation_timeline_->IsScrollTimeline();
+  has_pending_tree_lock_.Write(*this) =
+      !is_active_tree && animation_timeline()->IsScrollTimeline();
 
-  switch (state_) {
+  switch (state_.Read(*this)) {
     case State::PENDING:
       input_state->Add({worklet_animation_id(), name(),
                         current_time->InMillisecondsF(), CloneOptions(),
                         CloneEffectTimings()});
-      state_ = State::RUNNING;
+      state_.Write(*this) = State::RUNNING;
       break;
     case State::RUNNING:
       // TODO(jortaylo): EffectTimings need to be sent to the worklet during
@@ -166,43 +163,48 @@
 void WorkletAnimation::SetOutputState(
     const MutatorOutputState::AnimationState& state) {
   DCHECK_EQ(state.local_times.size(), 1u);
-  local_time_ = state.local_times[0];
+  local_time_.Write(*this) = state.local_times[0];
 }
 
-void WorkletAnimation::SetPlaybackRate(double playback_rate) {
-  if (playback_rate == playback_rate_)
+void WorkletAnimation::SetPlaybackRate(double rate) {
+  if (rate == playback_rate())
     return;
 
   // Setting playback rate is rejected in the blink side if playback_rate_ is
   // zero.
-  DCHECK(playback_rate_);
+  DCHECK(playback_rate());
 
-  if (start_time_ && last_current_time_) {
+  if (start_time_.Read(*this) && last_current_time_.Read(*this)) {
     // Update startTime in order to maintain previous currentTime and,
     // as a result, prevent the animation from jumping.
-    base::TimeDelta current_time = last_current_time_.value();
-    start_time_ = start_time_.value() + current_time / playback_rate_ -
-                  current_time / playback_rate;
+    base::TimeDelta current_time = last_current_time_.Read(*this).value();
+    start_time_.Write(*this) = start_time_.Read(*this).value() +
+                               current_time / playback_rate() -
+                               current_time / rate;
   }
-  playback_rate_ = playback_rate;
+  playback_rate_.Write(*this) = rate;
 }
 
-void WorkletAnimation::UpdatePlaybackRate(double playback_rate) {
-  if (playback_rate == playback_rate_)
+void WorkletAnimation::UpdatePlaybackRate(double rate) {
+  if (rate == playback_rate())
     return;
-  playback_rate_ = playback_rate;
+  playback_rate_.Write(*this) = rate;
   SetNeedsPushProperties();
 }
 
+void WorkletAnimation::ReleasePendingTreeLock() {
+  has_pending_tree_lock_.Write(*this) = false;
+}
+
 absl::optional<base::TimeDelta> WorkletAnimation::CurrentTime(
     base::TimeTicks monotonic_time,
     const ScrollTree& scroll_tree,
     bool is_active_tree) {
   DCHECK(IsTimelineActive(scroll_tree, is_active_tree));
   base::TimeTicks timeline_time;
-  if (animation_timeline_->IsScrollTimeline()) {
+  if (animation_timeline()->IsScrollTimeline()) {
     absl::optional<base::TimeTicks> scroll_monotonic_time =
-        ToScrollTimeline(animation_timeline_)
+        ToScrollTimeline(animation_timeline())
             ->CurrentTime(scroll_tree, is_active_tree);
     if (!scroll_monotonic_time)
       return absl::nullopt;
@@ -210,13 +212,13 @@
   } else {
     timeline_time = monotonic_time;
   }
-  return (timeline_time - start_time_.value()) * playback_rate_;
+  return (timeline_time - start_time_.Read(*this).value()) * playback_rate();
 }
 
 bool WorkletAnimation::NeedsUpdate(base::TimeTicks monotonic_time,
                                    const ScrollTree& scroll_tree,
                                    bool is_active_tree) {
-  if (state_ == State::REMOVED)
+  if (state_.Read(*this) == State::REMOVED)
     return true;
 
   // When the timeline is inactive we apply the last current time to the
@@ -226,21 +228,21 @@
 
   absl::optional<base::TimeDelta> current_time =
       CurrentTime(monotonic_time, scroll_tree, is_active_tree);
-  bool needs_update = last_current_time_ != current_time;
+  bool needs_update = last_current_time_.Read(*this) != current_time;
   return needs_update;
 }
 
 bool WorkletAnimation::IsTimelineActive(const ScrollTree& scroll_tree,
                                         bool is_active_tree) const {
-  if (!animation_timeline_->IsScrollTimeline())
+  if (!animation_timeline()->IsScrollTimeline())
     return true;
 
-  return ToScrollTimeline(animation_timeline_)
+  return ToScrollTimeline(animation_timeline())
       ->IsActive(scroll_tree, is_active_tree);
 }
 
 void WorkletAnimation::RemoveKeyframeModel(int keyframe_model_id) {
-  state_ = State::REMOVED;
+  state_.Write(*this) = State::REMOVED;
   Animation::RemoveKeyframeModel(keyframe_model_id);
 }
 
diff --git a/cc/animation/worklet_animation.h b/cc/animation/worklet_animation.h
index e21d2f5..090bf92 100644
--- a/cc/animation/worklet_animation.h
+++ b/cc/animation/worklet_animation.h
@@ -37,14 +37,14 @@
   WorkletAnimation(int cc_animation_id,
                    WorkletAnimationId worklet_animation_id,
                    const std::string& name,
-                   double playback_rate,
+                   double playback_rate_value,
                    std::unique_ptr<AnimationOptions> options,
                    std::unique_ptr<AnimationEffectTimings> effect_timings,
                    bool is_controlling_instance);
   static scoped_refptr<WorkletAnimation> Create(
       WorkletAnimationId worklet_animation_id,
       const std::string& name,
-      double playback_rate,
+      double playback_rate_value,
       std::unique_ptr<AnimationOptions> options,
       std::unique_ptr<AnimationEffectTimings> effect_timings);
   scoped_refptr<Animation> CreateImplInstance() const override;
@@ -69,17 +69,19 @@
   void PushPropertiesTo(Animation* animation_impl) override;
 
   // Called by Blink WorkletAnimation when its playback rate is updated.
-  void UpdatePlaybackRate(double playback_rate);
+  void UpdatePlaybackRate(double rate);
   void SetPlaybackRateForTesting(double playback_rate) {
     SetPlaybackRate(playback_rate);
   }
 
   void RemoveKeyframeModel(int keyframe_model_id) override;
-  void ReleasePendingTreeLock() { has_pending_tree_lock_ = false; }
+  void ReleasePendingTreeLock();
 
  private:
   ~WorkletAnimation() override;
 
+  double playback_rate() const { return playback_rate_.Read(*this); }
+
   // Returns the current time to be passed into the underlying AnimationWorklet.
   // The current time is based on the timeline associated with the animation and
   // in case of scroll timeline it may be nullopt when the associated scrolling
@@ -104,13 +106,13 @@
 
   // Updates the playback rate of the Impl thread instance.
   // Called by the UI thread WorkletAnimation instance during commit.
-  void SetPlaybackRate(double playback_rate);
+  void SetPlaybackRate(double rate);
 
   bool IsTimelineActive(const ScrollTree& scroll_tree,
                         bool is_active_tree) const;
 
-  WorkletAnimationId worklet_animation_id_;
-  std::string name_;
+  const WorkletAnimationId worklet_animation_id_;
+  const std::string name_;
 
   // Controls speed of the animation.
   // https://drafts.csswg.org/web-animations-2/#animation-effect-playback-rate
@@ -119,35 +121,37 @@
   // thread instance.
   // For the Impl thread instance contains the actual playback rate of the
   // animation.
-  double playback_rate_;
+  ProtectedSequenceReadable<double> playback_rate_;
 
+  // These are set once, and never change.
   std::unique_ptr<AnimationOptions> options_;
   std::unique_ptr<AnimationEffectTimings> effect_timings_;
 
   // Local time is used as an input to the keyframe effect of this animation.
   // The value comes from the user script that runs inside the animation worklet
   // global scope.
-  absl::optional<base::TimeDelta> local_time_;
+  ProtectedSequenceReadable<absl::optional<base::TimeDelta>> local_time_;
   // Local time passed to the main thread worklet animation to update its
   // keyframe effect. We only set the most recent local time, meaning that if
   // there are multiple compositor frames without a single main frame only
   // the local time associated with the latest frame is sent to the main thread.
-  absl::optional<base::TimeDelta> last_synced_local_time_;
+  ProtectedSequenceReadable<absl::optional<base::TimeDelta>>
+      last_synced_local_time_;
 
-  absl::optional<base::TimeTicks> start_time_;
+  ProtectedSequenceReadable<absl::optional<base::TimeTicks>> start_time_;
 
   // Last current time used for updating. We use this to skip updating if
   // current time has not changed since last update.
-  absl::optional<base::TimeDelta> last_current_time_;
+  ProtectedSequenceReadable<absl::optional<base::TimeDelta>> last_current_time_;
 
   // To ensure that 'time' progresses forward for scroll animations, we guard
   // against allowing active tree mutations while the pending tree has a
   // lock in the worklet. The lock is established when updating the input state
   // for the pending tree and release on pending tree activation.
-  bool has_pending_tree_lock_;
-  State state_;
+  ProtectedSequenceReadable<bool> has_pending_tree_lock_{false};
+  ProtectedSequenceReadable<State> state_{State::PENDING};
 
-  bool is_impl_instance_;
+  const bool is_impl_instance_;
 };
 
 inline WorkletAnimation* ToWorkletAnimation(Animation* animation) {
diff --git a/cc/paint/skottie_mru_resource_provider.cc b/cc/paint/skottie_mru_resource_provider.cc
index 0d91997..9307eee2 100644
--- a/cc/paint/skottie_mru_resource_provider.cc
+++ b/cc/paint/skottie_mru_resource_provider.cc
@@ -42,7 +42,7 @@
   if (!assets)
     return image_asset_sizes;
 
-  for (const base::Value& asset : assets->GetList()) {
+  for (const base::Value& asset : assets->GetListDeprecated()) {
     const std::string* id = asset.FindStringKey(kIdKey);
     absl::optional<int> width = asset.FindIntKey(kWidthKey);
     absl::optional<int> height = asset.FindIntKey(kHeightKey);
diff --git a/cc/test/animation_test_common.cc b/cc/test/animation_test_common.cc
index e381c46..d03b457 100644
--- a/cc/test/animation_test_common.cc
+++ b/cc/test/animation_test_common.cc
@@ -355,7 +355,7 @@
     ElementId element_id,
     scoped_refptr<AnimationTimeline> timeline,
     std::unique_ptr<KeyframeModel> keyframe_model) {
-  scoped_refptr<ElementAnimations> element_animations =
+  scoped_refptr<const ElementAnimations> element_animations =
       timeline->animation_host()->GetElementAnimationsForElementId(element_id);
   DCHECK(element_animations);
   KeyframeEffect* keyframe_effect =
@@ -368,7 +368,7 @@
     ElementId element_id,
     scoped_refptr<AnimationTimeline> timeline,
     int keyframe_model_id) {
-  scoped_refptr<ElementAnimations> element_animations =
+  scoped_refptr<const ElementAnimations> element_animations =
       timeline->animation_host()->GetElementAnimationsForElementId(element_id);
   DCHECK(element_animations);
   KeyframeEffect* keyframe_effect =
@@ -381,7 +381,7 @@
     ElementId element_id,
     scoped_refptr<AnimationTimeline> timeline,
     int keyframe_model_id) {
-  scoped_refptr<ElementAnimations> element_animations =
+  scoped_refptr<const ElementAnimations> element_animations =
       timeline->animation_host()->GetElementAnimationsForElementId(element_id);
   DCHECK(element_animations);
   KeyframeEffect* keyframe_effect =
diff --git a/cc/test/animation_timelines_test_common.cc b/cc/test/animation_timelines_test_common.cc
index 8e319de..76b1a3d 100644
--- a/cc/test/animation_timelines_test_common.cc
+++ b/cc/test/animation_timelines_test_common.cc
@@ -517,7 +517,7 @@
 
 KeyframeEffect* AnimationTimelinesTest::GetKeyframeEffectForElementId(
     ElementId element_id) {
-  const scoped_refptr<ElementAnimations> element_animations =
+  const scoped_refptr<const ElementAnimations> element_animations =
       host_->GetElementAnimationsForElementId(element_id);
   return element_animations
              ? element_animations->FirstKeyframeEffectForTesting()
@@ -526,7 +526,7 @@
 
 KeyframeEffect* AnimationTimelinesTest::GetImplKeyframeEffectForLayerId(
     ElementId element_id) {
-  const scoped_refptr<ElementAnimations> element_animations =
+  const scoped_refptr<const ElementAnimations> element_animations =
       host_impl_->GetElementAnimationsForElementId(element_id);
   return element_animations
              ? element_animations->FirstKeyframeEffectForTesting()
diff --git a/cc/test/animation_timelines_test_common.h b/cc/test/animation_timelines_test_common.h
index c784c5af..8febc289 100644
--- a/cc/test/animation_timelines_test_common.h
+++ b/cc/test/animation_timelines_test_common.h
@@ -322,11 +322,11 @@
 
   scoped_refptr<AnimationTimeline> timeline_;
   scoped_refptr<Animation> animation_;
-  scoped_refptr<ElementAnimations> element_animations_;
+  scoped_refptr<const ElementAnimations> element_animations_;
 
   scoped_refptr<AnimationTimeline> timeline_impl_;
   scoped_refptr<Animation> animation_impl_;
-  scoped_refptr<ElementAnimations> element_animations_impl_;
+  scoped_refptr<const ElementAnimations> element_animations_impl_;
 };
 
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc
index eb07ae0..42dd86d 100644
--- a/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -370,9 +370,9 @@
       return;
     first_animation_frame_ = false;
 
-    scoped_refptr<AnimationTimeline> timeline_impl =
+    scoped_refptr<const AnimationTimeline> timeline_impl =
         GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
-    scoped_refptr<Animation> animation_child_impl =
+    scoped_refptr<const Animation> animation_child_impl =
         timeline_impl->GetAnimationById(animation_child_id_);
 
     KeyframeModel* keyframe_model =
@@ -436,7 +436,7 @@
 
   void UpdateAnimationState(LayerTreeHostImpl* impl_host,
                             bool has_unfinished_animation) override {
-    scoped_refptr<AnimationTimeline> timeline_impl =
+    scoped_refptr<const AnimationTimeline> timeline_impl =
         GetImplAnimationHost(impl_host)->GetTimelineById(timeline_id_);
     scoped_refptr<Animation> animation_child_impl =
         timeline_impl->GetAnimationById(animation_child_id_);
@@ -512,7 +512,7 @@
   }
 
   void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
-    scoped_refptr<AnimationTimeline> timeline_impl =
+    scoped_refptr<const AnimationTimeline> timeline_impl =
         GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
     scoped_refptr<Animation> animation_impl =
         timeline_impl->GetAnimationById(animation_id_);
@@ -1172,7 +1172,7 @@
     if (!host_impl->active_tree()->root_layer())
       return false;
 
-    scoped_refptr<AnimationTimeline> timeline_impl =
+    scoped_refptr<const AnimationTimeline> timeline_impl =
         GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
     scoped_refptr<Animation> animation_impl =
         timeline_impl->GetAnimationById(animation_child_id_);
@@ -1458,7 +1458,7 @@
     if (sync_tree->source_frame_number() != 0)
       return;
 
-    scoped_refptr<AnimationTimeline> timeline_impl =
+    scoped_refptr<const AnimationTimeline> timeline_impl =
         GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
     scoped_refptr<Animation> animation_impl =
         timeline_impl->GetAnimationById(animation_id_);
@@ -1545,7 +1545,7 @@
   }
 
   void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
-    scoped_refptr<AnimationTimeline> timeline_impl =
+    scoped_refptr<const AnimationTimeline> timeline_impl =
         GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_);
     scoped_refptr<Animation> animation_impl =
         timeline_impl->GetAnimationById(animation_id_);
diff --git a/chrome/VERSION b/chrome/VERSION
index 8c39f40..95b6019 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=100
 MINOR=0
-BUILD=4871
+BUILD=4874
 PATCH=0
diff --git a/chrome/android/features/keyboard_accessory/BUILD.gn b/chrome/android/features/keyboard_accessory/BUILD.gn
index 9322b9f647..b1dcbbf9 100644
--- a/chrome/android/features/keyboard_accessory/BUILD.gn
+++ b/chrome/android/features/keyboard_accessory/BUILD.gn
@@ -127,6 +127,7 @@
     "//chrome/test/android:chrome_java_test_support",
     "//components/autofill/android:autofill_java",
     "//components/browser_ui/bottomsheet/android:java",
+    "//components/browser_ui/widget/android:java",
     "//components/embedder_support/android:content_view_java",
     "//components/embedder_support/android:util_java",
     "//components/feature_engagement/public:public_java",
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMediator.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMediator.java
index fb8430e..da35885 100644
--- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMediator.java
+++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMediator.java
@@ -62,6 +62,7 @@
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
 import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver;
 import org.chromium.components.browser_ui.widget.InsetObserverView;
+import org.chromium.components.browser_ui.widget.InsetObserverViewSupplier;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.DropdownPopupWindow;
 import org.chromium.ui.base.WindowAndroid;
@@ -150,7 +151,7 @@
         mAccessorySheet.setHeight(3
                 * mActivity.getResources().getDimensionPixelSize(
                         R.dimen.keyboard_accessory_suggestion_height));
-        setInsetObserverViewSupplier(mActivity::getInsetObserverView);
+        setInsetObserverViewSupplier(InsetObserverViewSupplier.from(mWindowAndroid));
         mActivity.findViewById(android.R.id.content).addOnLayoutChangeListener(this);
         mTabModelObserver = new TabModelSelectorTabModelObserver(mActivity.getTabModelSelector()) {
             @Override
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java
index 1d80eb7..60b6f12 100644
--- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java
+++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java
@@ -122,9 +122,7 @@
             ChromeActivity activity = mActivityTestRule.getActivity();
             mWebContentsRef.set(activity.getActivityTab().getWebContents());
             getManualFillingCoordinator().getMediatorForTesting().setInsetObserverViewSupplier(
-                    ()
-                            -> getKeyboard().createInsetObserver(
-                                    activity.getInsetObserverView().getContext()));
+                    () -> getKeyboard().createInsetObserver(activity.getApplicationContext()));
             // The TestInputMethodManagerWrapper intercepts showSoftInput so that a keyboard is
             // never brought up.
             final ImeAdapter imeAdapter = ImeAdapter.fromWebContents(mWebContentsRef.get());
diff --git a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java
index 55c22e4..e9ea2387 100644
--- a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java
+++ b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java
@@ -82,6 +82,8 @@
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.browser_ui.widget.InsetObserverView;
+import org.chromium.components.browser_ui.widget.InsetObserverViewSupplier;
 import org.chromium.components.embedder_support.view.ContentView;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.display.DisplayAndroid;
@@ -125,6 +127,8 @@
     private ConfirmationDialogHelper mMockConfirmationHelper;
     @Mock
     private FullscreenManager mMockFullscreenManager;
+    @Mock
+    private InsetObserverView mInsetObserver;
 
     @Rule
     public Features.JUnitProcessor mFeaturesProcessor = new Features.JUnitProcessor();
@@ -315,6 +319,7 @@
         when(mMockContentView.getRootView()).thenReturn(mock(View.class));
         mLastMockWebContents = mock(WebContents.class);
         when(mMockActivity.getCurrentWebContents()).then(i -> mLastMockWebContents);
+        InsetObserverViewSupplier.setInstanceForTesting(mInsetObserver);
         setContentAreaDimensions(2.f, 80, 300);
         Configuration config = new Configuration();
         config.hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java
index 5276ca1..98bb64c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java
@@ -25,6 +25,7 @@
 import org.chromium.chrome.browser.browsing_data.BrowsingDataBridge;
 import org.chromium.chrome.browser.browsing_data.BrowsingDataType;
 import org.chromium.chrome.browser.browsing_data.TimePeriod;
+import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.metrics.UmaUtils;
 import org.chromium.chrome.browser.metrics.VariationsSession;
 import org.chromium.chrome.browser.notifications.NotificationPlatformBridge;
@@ -39,6 +40,8 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.translate.TranslateBridge;
 import org.chromium.components.browser_ui.share.ShareImageFileUtils;
+import org.chromium.components.feature_engagement.EventConstants;
+import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.components.user_prefs.UserPrefs;
 
 import java.util.HashMap;
@@ -197,6 +200,9 @@
         }
         RecordHistogram.recordCountHistogram(
                 "Tab.TotalTabCount.BeforeLeavingApp", totalTabCount);
+
+        Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedRegularProfile());
+        tracker.notifyEvent(EventConstants.FOREGROUND_SESSION_DESTROYED);
     }
 
     private void onForegroundActivityDestroyed() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index b3713e2..4eebe21 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1619,7 +1619,7 @@
                 this::isInOverviewMode, this::isWarmOnResume, /* appMenuDelegate= */ this,
                 /* statusBarColorProvider= */ this, mEphemeralTabCoordinatorSupplier,
                 getIntentRequestTracker(), getControlContainerHeightResource(),
-                this::getInsetObserverView, this::backShouldCloseTab,
+                mInsetObserverViewSupplier, this::backShouldCloseTab,
                 getTabReparentingControllerSupplier(), new OmniboxPedalDelegateImpl(this),
                 // TODO(sinansahin): This currently only checks for incognito extras in the intent.
                 // We should make it more robust by using more signals.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
index 30cc942..be900db 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/DEPS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
@@ -30,9 +30,6 @@
   "BaseCustomTabActivity\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
-  "DisplayCutoutTabHelper\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
   "DownloadInfoBarController\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
index 94051c74..1f5a74a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -209,6 +209,7 @@
 import org.chromium.components.browser_ui.notifications.NotificationManagerProxyImpl;
 import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.widget.InsetObserverView;
+import org.chromium.components.browser_ui.widget.InsetObserverViewSupplier;
 import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController;
 import org.chromium.components.browser_ui.widget.gesture.SwipeGestureListener.SwipeHandler;
 import org.chromium.components.browser_ui.widget.textbubble.TextBubble;
@@ -326,7 +327,8 @@
             new ObservableSupplierImpl<>();
     private ObservableSupplierImpl<LayoutManagerImpl> mLayoutManagerSupplier =
             new ObservableSupplierImpl<>();
-    private InsetObserverView mInsetObserverView;
+    protected final UnownedUserDataSupplier<InsetObserverView> mInsetObserverViewSupplier =
+            new InsetObserverViewSupplier();
     private ContextualSearchManager mContextualSearchManager;
     private SnackbarManager mSnackbarManager;
 
@@ -503,6 +505,7 @@
         mTabModelSelectorSupplier.attach(getWindowAndroid().getUnownedUserDataHost());
         mTabCreatorManagerSupplier.attach(getWindowAndroid().getUnownedUserDataHost());
         mManualFillingComponentSupplier.attach(getWindowAndroid().getUnownedUserDataHost());
+        mInsetObserverViewSupplier.attach(getWindowAndroid().getUnownedUserDataHost());
         mBrowserControlsManagerSupplier.attach(getWindowAndroid().getUnownedUserDataHost());
         // BrowserControlsManager is ready immediately.
         mBrowserControlsManagerSupplier.set(
@@ -806,8 +809,8 @@
         // Add a custom view right after the root view that stores the insets to access later.
         // WebContents needs the insets to determine the portion of the screen obscured by
         // non-content displaying things such as the OSK.
-        mInsetObserverView = InsetObserverView.create(this);
-        rootView.addView(mInsetObserverView, 0);
+        mInsetObserverViewSupplier.set(InsetObserverView.create(this));
+        rootView.addView(mInsetObserverViewSupplier.get(), 0);
 
         super.onInitialLayoutInflationComplete();
     }
@@ -2020,15 +2023,6 @@
     }
 
     /**
-     * Returns the {@link InsetObserverView} that has the current system window
-     * insets information.
-     * @return The {@link InsetObserverView}, possibly null.
-     */
-    public InsetObserverView getInsetObserverView() {
-        return mInsetObserverView;
-    }
-
-    /**
      * Gets the supplier of the {@link TabCreatorManager} instance.
      */
     public ObservableSupplier<TabCreatorManager> getTabCreatorManagerSupplier() {
@@ -2202,7 +2196,7 @@
         compositorViewHolder.setControlContainer(controlContainer);
         compositorViewHolder.setBrowserControlsManager(mBrowserControlsManagerSupplier.get());
         compositorViewHolder.setUrlBar(urlBar);
-        compositorViewHolder.setInsetObserverView(getInsetObserverView());
+        compositorViewHolder.setInsetObserverView(mInsetObserverViewSupplier.get());
         compositorViewHolder.setAutofillUiBottomInsetSupplier(
                 mManualFillingComponentSupplier.get().getBottomInsetSupplier());
         compositorViewHolder.setTopUiThemeColorProvider(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/display_cutout/ActivityDisplayCutoutModeSupplier.java b/chrome/android/java/src/org/chromium/chrome/browser/display_cutout/ActivityDisplayCutoutModeSupplier.java
index e422c30f..df29bd5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/display_cutout/ActivityDisplayCutoutModeSupplier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/display_cutout/ActivityDisplayCutoutModeSupplier.java
@@ -6,9 +6,11 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.UnownedUserDataKey;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.UnownedUserDataSupplier;
 import org.chromium.ui.base.WindowAndroid;
 
@@ -22,12 +24,23 @@
     /** The key for accessing this object on an {@link org.chromium.base.UnownedUserDataHost}. */
     private static final UnownedUserDataKey<ActivityDisplayCutoutModeSupplier> KEY =
             new UnownedUserDataKey<>(ActivityDisplayCutoutModeSupplier.class);
+    private static ObservableSupplierImpl<Integer> sInstanceForTesting;
 
     public static @Nullable ObservableSupplier<Integer> from(@NonNull WindowAndroid window) {
+        if (sInstanceForTesting != null) return sInstanceForTesting;
         return KEY.retrieveDataFromHost(window.getUnownedUserDataHost());
     }
 
     public ActivityDisplayCutoutModeSupplier() {
         super(KEY);
     }
+
+    /** Sets an instance for testing. */
+    @VisibleForTesting
+    public static void setInstanceForTesting(Integer mode) {
+        if (sInstanceForTesting == null) {
+            sInstanceForTesting = new ObservableSupplierImpl<>();
+        }
+        sInstanceForTesting.set(mode);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTabHelper.java
index 7bbf2741..4dbf049 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTabHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTabHelper.java
@@ -13,7 +13,6 @@
 import org.chromium.base.UserData;
 import org.chromium.base.UserDataHost;
 import org.chromium.base.supplier.ObservableSupplier;
-import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.customtabs.BaseCustomTabActivity;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
@@ -21,6 +20,7 @@
 import org.chromium.chrome.browser.tab.TabSelectionType;
 import org.chromium.components.browser_ui.display_cutout.DisplayCutoutController;
 import org.chromium.components.browser_ui.widget.InsetObserverView;
+import org.chromium.components.browser_ui.widget.InsetObserverViewSupplier;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
 import org.chromium.ui.base.WindowAndroid;
@@ -88,8 +88,7 @@
         }
         @Override
         public InsetObserverView getInsetObserverView() {
-            Activity activity = getAttachedActivity();
-            return activity == null ? null : ((ChromeActivity) activity).getInsetObserverView();
+            return InsetObserverViewSupplier.getValueOrNullFrom(mTab.getWindowAndroid());
         }
         @Override
         public ObservableSupplier<Integer> getBrowserDisplayCutoutModeSupplier() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninCheckerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninCheckerTest.java
index c18cec1..e5b7350 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninCheckerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninCheckerTest.java
@@ -24,6 +24,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.DisableIf;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.UserActionTester;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -238,6 +239,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "https://crbug.com/1293942")
     public void signinWhenChildAccountIsFirstAccount() {
         final CoreAccountInfo childAccount = mAccountManagerTestRule.addAccount(CHILD_ACCOUNT_NAME);
         mAccountManagerTestRule.addAccount("the.second.account@gmail.com");
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutControllerTest.java
index 231a5704..3524bc71 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutControllerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutControllerTest.java
@@ -18,7 +18,6 @@
 
 import org.junit.Assert;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -34,18 +33,16 @@
 import org.chromium.chrome.browser.tab.TabSelectionType;
 import org.chromium.components.browser_ui.display_cutout.DisplayCutoutController;
 import org.chromium.components.browser_ui.widget.InsetObserverView;
+import org.chromium.components.browser_ui.widget.InsetObserverViewSupplier;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.testing.local.LocalRobolectricTestRunner;
 import org.chromium.ui.base.WindowAndroid;
 
 import java.lang.ref.WeakReference;
 
-/**
- * Tests for {@link DisplayCutoutController} class.
- */
+/** Tests for {@link DisplayCutoutController} class. */
 @RunWith(LocalRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
-@Ignore("https://crbug.com/1216298")
 public class DisplayCutoutControllerTest {
     @Mock
     private TabImpl mTab;
@@ -79,15 +76,15 @@
 
         mActivityRef = new WeakReference<>(mChromeActivity);
 
-        // Mock dependency on InsetObserverView.
-
         when(mChromeActivity.getWindow()).thenReturn(mWindow);
         when(mWindow.getAttributes()).thenReturn(new LayoutParams());
         when(mTab.getWindowAndroid()).thenReturn(mWindowAndroid);
         when(mTab.getWebContents()).thenReturn(mWebContents);
         when(mWebContents.isFullscreenForCurrentTab()).thenReturn(true);
         when(mWindowAndroid.getActivity()).thenReturn(mActivityRef);
-        when(mChromeActivity.getInsetObserverView()).thenReturn(mInsetObserver);
+
+        InsetObserverViewSupplier.setInstanceForTesting(mInsetObserver);
+        ActivityDisplayCutoutModeSupplier.setInstanceForTesting(0);
 
         mDisplayCutoutTabHelper = spy(new DisplayCutoutTabHelper(mTab));
         mController = spy(mDisplayCutoutTabHelper.mCutoutController);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 14c8d10..0d1c3e8 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5175,7 +5175,7 @@
       </message>
 
       <message name="IDS_WEB_APP_SETTINGS_TITLE" desc="Title of web app settings page">
-        Apps
+        App Settings
       </message>
 
       <if expr="chromeos_ash or chromeos_lacros">
diff --git a/chrome/app/generated_resources_grd/IDS_WEB_APP_SETTINGS_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEB_APP_SETTINGS_TITLE.png.sha1
index 5920a256..113990fc 100644
--- a/chrome/app/generated_resources_grd/IDS_WEB_APP_SETTINGS_TITLE.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_WEB_APP_SETTINGS_TITLE.png.sha1
@@ -1 +1 @@
-1c16bad974c1b4eb1a16f96661d7221c8185e7a5
\ No newline at end of file
+74b66203ee3dbafa65a6707efa83bbde3491387d
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 41ed3ebd..f885370 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -298,6 +298,18 @@
   <message name="IDS_SETTINGS_AUTOFILL_MORE_ACTIONS_CARD_DESCRIPTION" desc="The (accessibility) credit card description from the network of the card and last 4 digits of the card number.">
     <ph name="NETWORK_NAME">$1<ex>Visa</ex></ph> ending in <ph name="LAST_FOUR_DIGITS">$2<ex>1234</ex></ph>
   </message>
+  <message name="IDS_AUTOFILL_ADD_VIRTUAL_CARD" desc="The text shown in the secondary action menu button to enroll a card in the virtual card feature. Virtual cards are credit cards generated from the actual cards and provide extra security.">
+    Add virtual card
+  </message>
+  <message name="IDS_AUTOFILL_REMOVE_VIRTUAL_CARD" desc="The text shown in the secondary action menu button to unenroll a card from the virtual card feature. Virtual cards are credit cards generated from the actual cards and provide extra security.">
+    Remove virtual card
+  </message>
+  <message name="IDS_AUTOFILL_EDIT_SERVER_CREDIT_CARD" desc="The text shown in the secondary action menu button to direct users to pay.google.com to edit the information of credit cards stored in Google Payments.">
+    Edit in Google Pay
+  </message>
+  <message name="IDS_AUTOFILL_VIRTUAL_CARD_ENABLED_LABEL" desc="The text shown next to the card summary to indicate that a virtual card has been generated for the credit card and is enabled. Virtual cards are credit cards generated from the actual cards and provide extra security.">
+    (Virtual card enabled)
+  </message>
   <message name="IDS_SETTINGS_ADDRESS_REMOVE" desc="Label for a context menu item that removes the selected address." meaning="Remove selected address.">
     Remove
   </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_AUTOFILL_ADD_VIRTUAL_CARD.png.sha1 b/chrome/app/settings_strings_grdp/IDS_AUTOFILL_ADD_VIRTUAL_CARD.png.sha1
new file mode 100644
index 0000000..607039f
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_AUTOFILL_ADD_VIRTUAL_CARD.png.sha1
@@ -0,0 +1 @@
+c759b9d5c6ea6999784424458cd6073483dc0774
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_AUTOFILL_EDIT_SERVER_CREDIT_CARD.png.sha1 b/chrome/app/settings_strings_grdp/IDS_AUTOFILL_EDIT_SERVER_CREDIT_CARD.png.sha1
new file mode 100644
index 0000000..607039f
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_AUTOFILL_EDIT_SERVER_CREDIT_CARD.png.sha1
@@ -0,0 +1 @@
+c759b9d5c6ea6999784424458cd6073483dc0774
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_AUTOFILL_REMOVE_VIRTUAL_CARD.png.sha1 b/chrome/app/settings_strings_grdp/IDS_AUTOFILL_REMOVE_VIRTUAL_CARD.png.sha1
new file mode 100644
index 0000000..b3dcedc
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_AUTOFILL_REMOVE_VIRTUAL_CARD.png.sha1
@@ -0,0 +1 @@
+4ac1761c82310738347991949b5a96b5ac5c0ba0
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENABLED_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENABLED_LABEL.png.sha1
new file mode 100644
index 0000000..b3dcedc
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENABLED_LABEL.png.sha1
@@ -0,0 +1 @@
+4ac1761c82310738347991949b5a96b5ac5c0ba0
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index fbf475b..6f7ed95a 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -321,8 +321,6 @@
     "component_updater/crowd_deny_component_installer.h",
     "component_updater/first_party_sets_component_installer.cc",
     "component_updater/first_party_sets_component_installer.h",
-    "component_updater/floc_component_installer.cc",
-    "component_updater/floc_component_installer.h",
     "component_updater/mei_preload_component_installer.cc",
     "component_updater/mei_preload_component_installer.h",
     "component_updater/pki_metadata_component_installer.cc",
@@ -505,19 +503,6 @@
     "feature_engagement/tracker_factory.h",
     "feature_guide/notifications/feature_notification_guide_service_factory.cc",
     "feature_guide/notifications/feature_notification_guide_service_factory.h",
-    "federated_learning/floc_eligibility_observer.cc",
-    "federated_learning/floc_eligibility_observer.h",
-    "federated_learning/floc_event_logger.cc",
-    "federated_learning/floc_event_logger.h",
-    "federated_learning/floc_id_provider.h",
-    "federated_learning/floc_id_provider_factory.cc",
-    "federated_learning/floc_id_provider_factory.h",
-    "federated_learning/floc_id_provider_impl.cc",
-    "federated_learning/floc_id_provider_impl.h",
-    "federated_learning/floc_remote_permission_service.cc",
-    "federated_learning/floc_remote_permission_service.h",
-    "federated_learning/floc_remote_permission_service_factory.cc",
-    "federated_learning/floc_remote_permission_service_factory.h",
     "file_select_helper.cc",
     "file_select_helper.h",
     "file_system_access/chrome_file_system_access_permission_context.cc",
@@ -952,8 +937,6 @@
     "page_info/chrome_about_this_site_service_client.h",
     "page_load_metrics/observers/aborts_page_load_metrics_observer.cc",
     "page_load_metrics/observers/aborts_page_load_metrics_observer.h",
-    "page_load_metrics/observers/ad_metrics/floc_page_load_metrics_observer.cc",
-    "page_load_metrics/observers/ad_metrics/floc_page_load_metrics_observer.h",
     "page_load_metrics/observers/core/amp_page_load_metrics_observer.cc",
     "page_load_metrics/observers/core/amp_page_load_metrics_observer.h",
     "page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc",
@@ -1981,7 +1964,6 @@
     "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings",
     "//chrome/browser/ui/webui/download_shelf:mojo_bindings",
     "//chrome/browser/ui/webui/downloads:mojo_bindings",
-    "//chrome/browser/ui/webui/federated_learning:mojo_bindings",
     "//chrome/browser/ui/webui/history_clusters:mojo_bindings",
     "//chrome/browser/ui/webui/image_editor:mojo_bindings",
     "//chrome/browser/ui/webui/internals/user_education:mojo_bindings",
@@ -2079,7 +2061,6 @@
     "//components/favicon/core:history_implementation",
     "//components/favicon_base",
     "//components/feature_engagement",
-    "//components/federated_learning",
     "//components/feed:buildflags",
     "//components/feed/core/common:feed_core_common",
     "//components/feed/core/shared_prefs:feed_shared_prefs",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index dcb24cf..f606ada 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1976,6 +1976,20 @@
      base::size(kStartSurfaceAndroid_SingleSurfaceSingleTab), nullptr},
 };
 
+const FeatureEntry::FeatureParam kFeatureNotificationGuide_low_engaged[] = {
+    {"enable_feature_incognito_tab", "true"},
+    {"enable_feature_ntp_suggestion_card", "true"},
+    {"enable_feature_voice_search", "true"}};
+
+const FeatureEntry::FeatureParam kFeatureNotificationGuide_default_browser[] = {
+    {"enable_feature_default_browser", "true"}};
+
+const FeatureEntry::FeatureVariation kFeatureNotificationGuideVariations[] = {
+    {"Low engaged users", kFeatureNotificationGuide_low_engaged,
+     base::size(kFeatureNotificationGuide_low_engaged), nullptr},
+    {"Default browser", kFeatureNotificationGuide_default_browser,
+     base::size(kFeatureNotificationGuide_default_browser), nullptr},
+};
 const FeatureEntry::FeatureParam kWebFeed_accelerator[] = {
     {"intro_style", "accelerator"}};
 
@@ -3964,8 +3978,11 @@
                                     "AddToHomescreen")},
     {"feature-notification-guide",
      flag_descriptions::kFeatureNotificationGuideName,
-     flag_descriptions::kFeatureNotificationGuideDescription, kOsAll,
-     FEATURE_VALUE_TYPE(feature_guide::features::kFeatureNotificationGuide)},
+     flag_descriptions::kFeatureNotificationGuideDescription, kOsAndroid,
+     FEATURE_WITH_PARAMS_VALUE_TYPE(
+         feature_guide::features::kFeatureNotificationGuide,
+         kFeatureNotificationGuideVariations,
+         "FeatureNotificationGuide")},
     {"feature-notification-guide-skip-check-for-low-engaged-users",
      flag_descriptions::
          kFeatureNotificationGuideSkipCheckForLowEngagedUsersName,
diff --git a/chrome/browser/alternative_error_page_override_info_browsertest.cc b/chrome/browser/alternative_error_page_override_info_browsertest.cc
index cf225e6..6692d69 100644
--- a/chrome/browser/alternative_error_page_override_info_browsertest.cc
+++ b/chrome/browser/alternative_error_page_override_info_browsertest.cc
@@ -16,13 +16,27 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_utils.h"
 #include "skia/ext/skia_utils_base.h"
+#include "third_party/blink/public/common/features.h"
+#include "ui/native_theme/native_theme.h"
 #include "url/gurl.h"
 
+namespace {
+const std::string kYellow = skia::SkColorToHexString(SK_ColorYELLOW);
+const std::string kGreen = skia::SkColorToHexString(SK_ColorGREEN);
+const std::string kRed = skia::SkColorToHexString(SK_ColorRED);
+const std::string kBlue = skia::SkColorToHexString(SK_ColorBLUE);
+const std::string kBlack = skia::SkColorToHexString(SK_ColorBLACK);
+const std::string kWhite = skia::SkColorToHexString(SK_ColorWHITE);
+}  // namespace
 // Class to test browser error page display info.
 class AlternativeErrorPageOverrideInfoBrowserTest
     : public InProcessBrowserTest {
  public:
-  AlternativeErrorPageOverrideInfoBrowserTest() = default;
+  AlternativeErrorPageOverrideInfoBrowserTest() {
+    feature_list_.InitWithFeatures({features::kDesktopPWAsDefaultOfflinePage,
+                                    blink::features::kWebAppEnableDarkMode},
+                                   {});
+  }
 
   // Helper function to prepare PWA and retrieve information from the
   // alternative error page function.
@@ -48,9 +62,7 @@
   void TearDownOnMainThread() override {
     InProcessBrowserTest::TearDownOnMainThread();
   }
-
-  base::test::ScopedFeatureList feature_list_{
-      features::kDesktopPWAsDefaultOfflinePage};
+  base::test::ScopedFeatureList feature_list_;
 };
 
 // Testing app manifest with no theme or background color.
@@ -63,9 +75,9 @@
   EXPECT_TRUE(info);
   EXPECT_EQ(*info->alternative_error_page_params.FindKey(
                 "customized_background_color"),
-            base::Value(skia::SkColorToHexString(SK_ColorWHITE)));
+            base::Value(kWhite));
   EXPECT_EQ(*info->alternative_error_page_params.FindKey("theme_color"),
-            base::Value(skia::SkColorToHexString(SK_ColorBLACK)));
+            base::Value(kBlack));
 }
 
 // Testing app manifest with theme color.
@@ -80,7 +92,7 @@
   EXPECT_TRUE(info);
   EXPECT_EQ(*info->alternative_error_page_params.FindKey(
                 "customized_background_color"),
-            base::Value(skia::SkColorToHexString(SK_ColorWHITE)));
+            base::Value(kWhite));
   EXPECT_EQ(
       *info->alternative_error_page_params.FindKey("theme_color"),
       base::Value(skia::SkColorToHexString(SkColorSetRGB(0xAA, 0xCC, 0xEE))));
@@ -98,9 +110,9 @@
   EXPECT_TRUE(info);
   EXPECT_EQ(*info->alternative_error_page_params.FindKey(
                 "customized_background_color"),
-            base::Value(skia::SkColorToHexString(SK_ColorBLUE)));
+            base::Value(kBlue));
   EXPECT_EQ(*info->alternative_error_page_params.FindKey("theme_color"),
-            base::Value(skia::SkColorToHexString(SK_ColorBLACK)));
+            base::Value(kBlack));
 }
 
 // Testing url outside the scope of an installed app.
@@ -197,7 +209,44 @@
   EXPECT_TRUE(info);
   EXPECT_EQ(*info->alternative_error_page_params.FindKey(
                 "customized_background_color"),
-            base::Value(skia::SkColorToHexString(SK_ColorYELLOW)));
+            base::Value(kYellow));
   EXPECT_EQ(*info->alternative_error_page_params.FindKey("theme_color"),
-            base::Value(skia::SkColorToHexString(SK_ColorGREEN)));
+            base::Value(kGreen));
+}
+
+// Testing app manifest with dark mode theme and background colors.
+IN_PROC_BROWSER_TEST_F(AlternativeErrorPageOverrideInfoBrowserTest,
+                       ManifestWithDarkModeThemeAndBackgroundColor) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  ui::NativeTheme::GetInstanceForNativeUi()->set_use_dark_colors(true);
+  content::mojom::AlternativeErrorPageOverrideInfoPtr info =
+      GetErrorPageInfo("/web_apps/get_manifest.html?color_scheme_dark.json");
+
+  // Expect mojom struct with dark mode theme color and dark mode background
+  // color.
+  EXPECT_TRUE(info);
+  EXPECT_EQ(*info->alternative_error_page_params.FindKey(
+                "dark_mode_background_color"),
+            base::Value(kRed));
+  EXPECT_EQ(
+      *info->alternative_error_page_params.FindKey("dark_mode_theme_color"),
+      base::Value(kRed));
+}
+
+// Testing app manifest with no dark mode theme or background color.
+IN_PROC_BROWSER_TEST_F(AlternativeErrorPageOverrideInfoBrowserTest,
+                       ManifestWithNoDarkModeThemeAndBackgroundColor) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  ui::NativeTheme::GetInstanceForNativeUi()->set_use_dark_colors(true);
+  content::mojom::AlternativeErrorPageOverrideInfoPtr info =
+      GetErrorPageInfo("/banners/no-sw-with-colors.html");
+
+  // Expect mojom struct light mode background and theme color stored.
+  EXPECT_TRUE(info);
+  EXPECT_EQ(*info->alternative_error_page_params.FindKey(
+                "dark_mode_background_color"),
+            base::Value(kYellow));
+  EXPECT_EQ(
+      *info->alternative_error_page_params.FindKey("dark_mode_theme_color"),
+      base::Value(kGreen));
 }
diff --git a/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc b/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc
index 32bfd0c..14307f8 100644
--- a/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc
+++ b/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc
@@ -248,9 +248,10 @@
   EXPECT_TRUE(GetFirstAppWindow()->GetBaseWindow()->IsFullscreen());
 }
 
-#if BUILDFLAG(IS_MAC) || defined(THREAD_SANITIZER)
+#if BUILDFLAG(IS_MAC) || defined(THREAD_SANITIZER) || BUILDFLAG(IS_LINUX)
 // http://crbug.com/404081
 // http://crbug.com/1263448 (tsan)
+// http://crbug.com/1263661 (linux)
 #define MAYBE_TestInnerBounds DISABLED_TestInnerBounds
 #else
 #define MAYBE_TestInnerBounds TestInnerBounds
diff --git a/chrome/browser/ash/DEPS b/chrome/browser/ash/DEPS
index 38cb2ad61..5036510 100644
--- a/chrome/browser/ash/DEPS
+++ b/chrome/browser/ash/DEPS
@@ -13,6 +13,7 @@
   "+chrome/services/keymaster/public", # nocheck
   "+chrome/services/wilco_dtc_supportd/public",
   "+components/account_manager_core",
+  "+components/app_constants",
   "+components/app_restore",
   "+components/guest_os",
   "+components/services/app_service/public",
diff --git a/chrome/browser/ash/app_restore/app_launch_handler.cc b/chrome/browser/ash/app_restore/app_launch_handler.cc
index edd75ca..c9e6165d 100644
--- a/chrome/browser/ash/app_restore/app_launch_handler.cc
+++ b/chrome/browser/ash/app_restore/app_launch_handler.cc
@@ -16,10 +16,10 @@
 #include "chrome/browser/apps/app_service/browser_app_launcher.h"
 #include "chrome/browser/apps/app_service/metrics/app_platform_metrics.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/app_constants/constants.h"
 #include "components/app_restore/full_restore_read_handler.h"
 #include "components/services/app_service/public/cpp/types_util.h"
 #include "extensions/browser/extension_registry.h"
-#include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
 
 namespace ash {
@@ -64,7 +64,7 @@
 }
 
 void AppLaunchHandler::OnAppUpdate(const apps::AppUpdate& update) {
-  if (update.AppId() == extension_misc::kChromeAppId || !restore_data_ ||
+  if (update.AppId() == app_constants::kChromeAppId || !restore_data_ ||
       !update.ReadinessChanged()) {
     return;
   }
@@ -134,7 +134,7 @@
   for (const auto& app_id : app_ids) {
     // Chrome browser web pages are restored separately, so we don't need to
     // launch browser windows.
-    if (app_id == extension_misc::kChromeAppId)
+    if (app_id == app_constants::kChromeAppId)
       continue;
 
 #if !defined(OFFICIAL_BUILD)
@@ -167,7 +167,7 @@
 void AppLaunchHandler::LaunchApp(apps::mojom::AppType app_type,
                                  const std::string& app_id) {
   DCHECK(restore_data_);
-  DCHECK_NE(app_id, extension_misc::kChromeAppId);
+  DCHECK_NE(app_id, app_constants::kChromeAppId);
 
   const auto it = restore_data_->app_id_to_launch_list().find(app_id);
   if (it == restore_data_->app_id_to_launch_list().end() ||
diff --git a/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc b/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc
index 5f2242ee..ecd20e6 100644
--- a/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc
+++ b/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc
@@ -28,10 +28,10 @@
 #include "chrome/browser/sessions/session_service_log.h"
 #include "chrome/browser/ui/startup/startup_tab.h"
 #include "chrome/common/chrome_switches.h"
+#include "components/app_constants/constants.h"
 #include "components/app_restore/features.h"
 #include "components/app_restore/full_restore_read_handler.h"
 #include "components/app_restore/full_restore_save_handler.h"
-#include "extensions/common/constants.h"
 
 namespace ash {
 namespace full_restore {
@@ -253,7 +253,7 @@
   // If the browser is not launched before reboot, don't launch browser during
   // the startup phase.
   const auto& launch_list = restore_data()->app_id_to_launch_list();
-  if (launch_list.find(extension_misc::kChromeAppId) == launch_list.end())
+  if (launch_list.find(app_constants::kChromeAppId) == launch_list.end())
     return;
 
   SessionRestore::AddObserver(this);
@@ -261,7 +261,7 @@
   VLOG(1) << "Restore browser for " << profile()->GetPath();
   RecordRestoredAppLaunch(apps::AppTypeName::kChromeBrowser);
 
-  restore_data()->RemoveApp(extension_misc::kChromeAppId);
+  restore_data()->RemoveApp(app_constants::kChromeAppId);
 
   if (ExitTypeService::GetLastSessionExitType(profile()) ==
       ExitType::kCrashed) {
@@ -338,11 +338,11 @@
   // 2. Handle the migration scenario, e.g. from flag disable to enable.
   // 3. Add metrics to check whether the Lacros is restored successfully.
   if (!base::Contains(restore_data()->app_id_to_launch_list(),
-                      extension_misc::kLacrosAppId)) {
+                      app_constants::kLacrosAppId)) {
     return;
   }
 
-  restore_data()->RemoveApp(extension_misc::kLacrosAppId);
+  restore_data()->RemoveApp(app_constants::kLacrosAppId);
 
   if (crosapi::BrowserManager::Get()->IsRunning()) {
     crosapi::BrowserManager::Get()->NewWindow(
@@ -441,7 +441,7 @@
   int arc_app_count = 0;
   int other_app_count = 0;
   for (const auto& it : restore_data()->app_id_to_launch_list()) {
-    if (it.first == extension_misc::kChromeAppId || it.second.empty())
+    if (it.first == app_constants::kChromeAppId || it.second.empty())
       continue;
 
     if (it.second.begin()->second->event_flag.has_value()) {
@@ -476,7 +476,7 @@
   }
 
   if (base::Contains(restore_data()->app_id_to_launch_list(),
-                     extension_misc::kChromeAppId)) {
+                     app_constants::kChromeAppId)) {
     // If the browser hasn't been restored yet, Wait for the browser
     // restoration. LaunchBrowser will call this function again to start the
     // save timer after restore the browser sessions.
diff --git a/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
index 8b3f423..8628a6bc 100644
--- a/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
+++ b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
@@ -46,6 +46,7 @@
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "components/app_constants/constants.h"
 #include "components/app_restore/app_launch_info.h"
 #include "components/app_restore/full_restore_info.h"
 #include "components/app_restore/full_restore_read_handler.h"
@@ -320,7 +321,7 @@
   // Add app launch info.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kWindowId1));
+                                app_constants::kChromeAppId, kWindowId1));
 
   WaitForAppLaunchInfoSaved();
 
@@ -431,7 +432,7 @@
   // Add app launch infos.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kWindowId1));
+                                app_constants::kChromeAppId, kWindowId1));
 
   WaitForAppLaunchInfoSaved();
 
@@ -452,7 +453,7 @@
   // Add app launch infos.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kWindowId1));
+                                app_constants::kChromeAppId, kWindowId1));
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(),
       std::make_unique<::app_restore::AppLaunchInfo>(
@@ -486,10 +487,10 @@
   // Add the chrome browser launch info.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kWindowId1));
+                                app_constants::kChromeAppId, kWindowId1));
 
   auto app_launch_info = std::make_unique<::app_restore::AppLaunchInfo>(
-      extension_misc::kChromeAppId, kWindowId2);
+      app_constants::kChromeAppId, kWindowId2);
   app_launch_info->app_type_browser = true;
   ::full_restore::SaveAppLaunchInfo(profile()->GetPath(),
                                     std::move(app_launch_info));
@@ -517,10 +518,10 @@
   // Add the chrome browser launch info.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kWindowId1));
+                                app_constants::kChromeAppId, kWindowId1));
 
   auto app_launch_info = std::make_unique<::app_restore::AppLaunchInfo>(
-      extension_misc::kChromeAppId, kWindowId2);
+      app_constants::kChromeAppId, kWindowId2);
   app_launch_info->app_type_browser = true;
   ::full_restore::SaveAppLaunchInfo(profile()->GetPath(),
                                     std::move(app_launch_info));
@@ -570,10 +571,10 @@
   // Add the chrome browser launch info.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kWindowId1));
+                                app_constants::kChromeAppId, kWindowId1));
 
   auto app_launch_info = std::make_unique<::app_restore::AppLaunchInfo>(
-      extension_misc::kChromeAppId, kWindowId2);
+      app_constants::kChromeAppId, kWindowId2);
   app_launch_info->app_type_browser = true;
   ::full_restore::SaveAppLaunchInfo(profile()->GetPath(),
                                     std::move(app_launch_info));
@@ -637,7 +638,7 @@
 
   // Remove the browser app to mock no browser launch info.
   ::full_restore::FullRestoreSaveHandler::GetInstance()->RemoveApp(
-      profile()->GetPath(), extension_misc::kChromeAppId);
+      profile()->GetPath(), app_constants::kChromeAppId);
 
   WaitForAppLaunchInfoSaved();
 
@@ -660,10 +661,10 @@
   // Add the chrome browser launch info.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kWindowId1));
+                                app_constants::kChromeAppId, kWindowId1));
 
   auto app_launch_info = std::make_unique<::app_restore::AppLaunchInfo>(
-      extension_misc::kChromeAppId, kWindowId2);
+      app_constants::kChromeAppId, kWindowId2);
   app_launch_info->app_type_browser = true;
   ::full_restore::SaveAppLaunchInfo(profile()->GetPath(),
                                     std::move(app_launch_info));
@@ -695,7 +696,7 @@
   // Add app launch infos.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kWindowId1));
+                                app_constants::kChromeAppId, kWindowId1));
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(),
       std::make_unique<::app_restore::AppLaunchInfo>(
@@ -728,7 +729,7 @@
   // Add app launch infos.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kWindowId1));
+                                app_constants::kChromeAppId, kWindowId1));
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(),
       std::make_unique<::app_restore::AppLaunchInfo>(
@@ -762,7 +763,7 @@
 
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kWindowId1));
+                                app_constants::kChromeAppId, kWindowId1));
 
   CreateAndSaveWindowInfo(kDeskId, kCurrentBounds, kWindowStateType);
   WaitForAppLaunchInfoSaved();
@@ -820,7 +821,7 @@
   // Full Restore data being saved prior to restart.
   ::full_restore::SaveAppLaunchInfo(
       profile()->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kRestoreId));
+                                app_constants::kChromeAppId, kRestoreId));
   CreateAndSaveWindowInfo(kDeskId, kCurrentBounds,
                           chromeos::WindowStateType::kNormal,
                           ui::SHOW_STATE_DEFAULT, kRestoreId);
diff --git a/chrome/browser/ash/app_restore/full_restore_service_unittest.cc b/chrome/browser/ash/app_restore/full_restore_service_unittest.cc
index e38bad1..aeecc59d 100644
--- a/chrome/browser/ash/app_restore/full_restore_service_unittest.cc
+++ b/chrome/browser/ash/app_restore/full_restore_service_unittest.cc
@@ -23,6 +23,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/account_id/account_id.h"
+#include "components/app_constants/constants.h"
 #include "components/app_restore/app_launch_info.h"
 #include "components/app_restore/full_restore_info.h"
 #include "components/app_restore/full_restore_read_handler.h"
@@ -43,7 +44,6 @@
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_utils.h"
-#include "extensions/common/constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/message_center/public/cpp/notification.h"
@@ -267,7 +267,7 @@
     // Add app launch infos.
     ::full_restore::SaveAppLaunchInfo(
         profile->GetPath(), std::make_unique<::app_restore::AppLaunchInfo>(
-                                extension_misc::kChromeAppId, kWindowId));
+                                app_constants::kChromeAppId, kWindowId));
 
     ::full_restore::FullRestoreSaveHandler* save_handler =
         ::full_restore::FullRestoreSaveHandler::GetInstance();
diff --git a/chrome/browser/ash/child_accounts/child_user_service.cc b/chrome/browser/ash/child_accounts/child_user_service.cc
index ae3a7189..b7d5f8d 100644
--- a/chrome/browser/ash/child_accounts/child_user_service.cc
+++ b/chrome/browser/ash/child_accounts/child_user_service.cc
@@ -16,9 +16,9 @@
 #include "chrome/browser/ash/child_accounts/usage_time_limit_processor.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
+#include "components/app_constants/constants.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_context.h"
-#include "extensions/common/constants.h"
 #include "url/gurl.h"
 
 namespace ash {
@@ -107,7 +107,7 @@
   DCHECK(app_time_controller_);
 
   // Pause web activity only if the app is chrome.
-  if (app_service_id != extension_misc::kChromeAppId)
+  if (app_service_id != app_constants::kChromeAppId)
     return;
 
   app_time::WebTimeLimitEnforcer* web_time_enforcer =
@@ -127,7 +127,7 @@
   DCHECK(app_time_controller_);
 
   // Only unpause web activity if the app is chrome.
-  if (app_service_id != extension_misc::kChromeAppId)
+  if (app_service_id != app_constants::kChromeAppId)
     return;
 
   app_time::WebTimeLimitEnforcer* web_time_enforcer =
diff --git a/chrome/browser/ash/child_accounts/child_user_service_unittest.cc b/chrome/browser/ash/child_accounts/child_user_service_unittest.cc
index 452163c8..76462ad 100644
--- a/chrome/browser/ash/child_accounts/child_user_service_unittest.cc
+++ b/chrome/browser/ash/child_accounts/child_user_service_unittest.cc
@@ -18,8 +18,8 @@
 #include "chrome/browser/ash/child_accounts/time_limits/app_types.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/app_constants/constants.h"
 #include "content/public/test/browser_task_environment.h"
-#include "extensions/common/constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
@@ -91,7 +91,7 @@
   EnableWebTimeLimits();
   EXPECT_FALSE(service()->WebTimeLimitReached());
 
-  const std::string app_id = extension_misc::kChromeAppId;
+  const std::string app_id = app_constants::kChromeAppId;
   service()->PauseWebActivity(app_id);
   EXPECT_TRUE(service()->WebTimeLimitReached());
 
@@ -104,7 +104,7 @@
   EnableWebTimeLimits();
   EXPECT_FALSE(service()->WebTimeLimitReached());
 
-  const std::string app_id = extension_misc::kChromeAppId;
+  const std::string app_id = app_constants::kChromeAppId;
   service()->PauseWebActivity(app_id);
   EXPECT_TRUE(service()->WebTimeLimitReached());
 
@@ -116,7 +116,7 @@
   EnableWebTimeLimits();
   EXPECT_FALSE(service()->WebTimeLimitReached());
 
-  const std::string app_id = extension_misc::kChromeAppId;
+  const std::string app_id = app_constants::kChromeAppId;
   service()->ResumeWebActivity(app_id);
 
   EXPECT_FALSE(service()->WebTimeLimitReached());
@@ -132,7 +132,7 @@
   EnableWebTimeLimits();
   EXPECT_FALSE(service()->WebTimeLimitReached());
 
-  const std::string chrome_app_id = extension_misc::kChromeAppId;
+  const std::string chrome_app_id = app_constants::kChromeAppId;
   service()->PauseWebActivity(chrome_app_id);
 
   EXPECT_TRUE(service()->WebTimeLimitReached());
diff --git a/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc b/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc
index 5652dfb4a..944d7e06 100644
--- a/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc
+++ b/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc
@@ -25,6 +25,7 @@
 #include "chrome/test/base/test_browser_window_aura.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
+#include "components/app_constants/constants.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "components/session_manager/core/session_manager.h"
@@ -78,7 +79,7 @@
 
     // Install Chrome.
     scoped_refptr<extensions::Extension> chrome = app_time::CreateExtension(
-        extension_misc::kChromeAppId, kExtensionNameChrome, kExtensionAppUrl);
+        app_constants::kChromeAppId, kExtensionNameChrome, kExtensionAppUrl);
     extension_service_->AddComponentExtension(chrome.get());
 
     PushChromeApp();
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper_unittest.cc b/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper_unittest.cc
index 479345a..4c431ef 100644
--- a/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper_unittest.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper_unittest.cc
@@ -37,11 +37,11 @@
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/app_constants/constants.h"
 #include "components/services/app_service/public/cpp/app_update.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
 #include "content/public/test/browser_task_environment.h"
-#include "extensions/common/constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -120,7 +120,7 @@
 
     // Install Chrome.
     scoped_refptr<extensions::Extension> chrome = CreateExtension(
-        extension_misc::kChromeAppId, kExtensionNameChrome, kExtensionAppUrl);
+        app_constants::kChromeAppId, kExtensionNameChrome, kExtensionAppUrl);
     extension_service_->AddComponentExtension(chrome.get());
     task_environment_.RunUntilIdle();
   }
@@ -258,7 +258,7 @@
 TEST_F(AppServiceWrapperTest, GetInstalledApps) {
   // Chrome is the only 'preinstalled' app.
   const AppId chrome =
-      AppId(apps::mojom::AppType::kChromeApp, extension_misc::kChromeAppId);
+      AppId(apps::mojom::AppType::kChromeApp, app_constants::kChromeAppId);
   std::vector<AppId> installed_apps = tested_wrapper().GetInstalledApps();
   EXPECT_EQ(1u, installed_apps.size());
   EXPECT_TRUE(base::Contains(installed_apps, chrome));
@@ -295,7 +295,7 @@
 
 TEST_F(AppServiceWrapperTest, GetAppName) {
   const AppId chrome(apps::mojom::AppType::kChromeApp,
-                     extension_misc::kChromeAppId);
+                     app_constants::kChromeAppId);
   EXPECT_EQ(kExtensionNameChrome, tested_wrapper().GetAppName(chrome));
 
   const AppId app1(apps::mojom::AppType::kArc, kArcPackage1);
@@ -423,7 +423,7 @@
 // PATL v1 does not support 'extensions' other than Chrome.
 TEST_F(AppServiceWrapperTest, IgnoreOtherExtensions) {
   const AppId chrome(apps::mojom::AppType::kChromeApp,
-                     extension_misc::kChromeAppId);
+                     app_constants::kChromeAppId);
   std::vector<AppId> installed_apps = tested_wrapper().GetInstalledApps();
   EXPECT_TRUE(base::Contains(installed_apps, chrome));
 
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_time_limit_utils.cc b/chrome/browser/ash/child_accounts/time_limits/app_time_limit_utils.cc
index 144062be..76d07e3d 100644
--- a/chrome/browser/ash/child_accounts/time_limits/app_time_limit_utils.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/app_time_limit_utils.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/ash/child_accounts/time_limits/app_types.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "components/app_constants/constants.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "extensions/common/constants.h"
 #include "url/gurl.h"
@@ -34,7 +35,7 @@
 }
 
 AppId GetChromeAppId() {
-  return AppId(apps::mojom::AppType::kChromeApp, extension_misc::kChromeAppId);
+  return AppId(apps::mojom::AppType::kChromeApp, app_constants::kChromeAppId);
 }
 
 bool IsWebAppOrExtension(const AppId& app_id) {
diff --git a/chrome/browser/ash/login/chrome_restart_request.cc b/chrome/browser/ash/login/chrome_restart_request.cc
index e53c54a..f07c8b8 100644
--- a/chrome/browser/ash/login/chrome_restart_request.cc
+++ b/chrome/browser/ash/login/chrome_restart_request.cc
@@ -225,6 +225,7 @@
     switches::kNaturalScrollDefault,
     switches::kRlzPingDelay,
     chromeos::switches::kSystemInDevMode,
+    switches::kTouchscreenUsableWhileScreenOff,
     policy::switches::kDeviceManagementUrl,
     wm::switches::kWindowAnimationsDisabled,
   };
diff --git a/chrome/browser/ash/settings/cros_settings_unittest.cc b/chrome/browser/ash/settings/cros_settings_unittest.cc
index 69595db..34b3ca9 100644
--- a/chrome/browser/ash/settings/cros_settings_unittest.cc
+++ b/chrome/browser/ash/settings/cros_settings_unittest.cc
@@ -263,6 +263,49 @@
   ExpectPref(kAccountsPrefAllowNewUser, base::Value(true));
 }
 
+// It's possible for the user_allowlist to be not present, and for the
+// user_whitelist to be present instead. This test simulates this by
+// doing something similar to the "RestrictSignInToAListOfUsers" test
+// but using user_whitelist instead
+TEST_F(CrosSettingsTest, WhitelistUsedWhenAllowlistNotPresent) {
+  // clear user_allowlist
+  device_policy_.payload().clear_user_allowlist();
+  // set non-empty user_whitelist
+  device_policy_.payload().mutable_user_whitelist()->add_user_whitelist(kOwner);
+  // Set allow_new_users to false.
+  device_policy_.payload().mutable_allow_new_users()->set_allow_new_users(
+      false);
+  StoreDevicePolicy();
+
+  // Expect the same - a non-empty allowlist and no new users allowed.
+  base::Value allowlist(base::Value::Type::LIST);
+  allowlist.Append(kOwner);
+  ExpectPref(kAccountsPrefUsers, allowlist);
+  ExpectPref(kAccountsPrefAllowNewUser, base::Value(false));
+}
+
+// In cases where both the user_allowlist and the user_whitelist are present,
+// we should use the user_allowlist. This test simulates this by
+// doing something similar to the "RestrictSignInToAListOfUsers" test
+// but providing both user_allowlist and user_whitelist, and asserting that
+// user_allowlist is being used.
+TEST_F(CrosSettingsTest, AllowlistUsedWhenAllowlistAndWhitelistPresent) {
+  // clear user_allowlist
+  device_policy_.payload().mutable_user_allowlist()->add_user_allowlist(kUser1);
+  // set non-empty user_whitelist
+  device_policy_.payload().mutable_user_whitelist()->add_user_whitelist(kOwner);
+  // Set allow_new_users to false.
+  device_policy_.payload().mutable_allow_new_users()->set_allow_new_users(
+      false);
+  StoreDevicePolicy();
+
+  // Expect the same - a non-empty allowlist and no new users allowed.
+  base::Value allowlist(base::Value::Type::LIST);
+  allowlist.Append(kUser1);
+  ExpectPref(kAccountsPrefUsers, allowlist);
+  ExpectPref(kAccountsPrefAllowNewUser, base::Value(false));
+}
+
 TEST_F(CrosSettingsTest, FindEmailInList) {
   auto* oss = CreateOwnerSettingsService(kOwner);
 
diff --git a/chrome/browser/ash/settings/device_settings_provider.cc b/chrome/browser/ash/settings/device_settings_provider.cc
index 60b392b0..dd61c35 100644
--- a/chrome/browser/ash/settings/device_settings_provider.cc
+++ b/chrome/browser/ash/settings/device_settings_provider.cc
@@ -228,18 +228,24 @@
 }
 
 // Returns:
-// - an empty absl::optional if the user_allowlist outer wrapper message is
-//   not present
+// - an empty absl::optional if the user_allowlist and user_whitelist
+// outer wrapper message is not present.
 // - true if the user_allowlist outer wrapper message is present and the
-//   user_allowlist inner list is empty
+//   user_allowlist inner list is empty, or when it's not present,
+//   if the user_whitelist is non-empty.
 // - false if the user_allowlist outer wrapper message is present and the
-//   user_allowlist inner list has at least one element.
+//   user_allowlist inner list has at least one element, or when it's not
+//   present, and the user_whitelist has at least one element.
 absl::optional<bool> GetIsEmptyAllowList(
     const em::ChromeDeviceSettingsProto& policy) {
-  if (!policy.has_user_allowlist())
+  if (!policy.has_user_whitelist() && !policy.has_user_allowlist())
     return absl::nullopt;
-  return absl::optional<bool>{policy.user_allowlist().user_allowlist_size() ==
-                              0};
+  // use user_whitelist only if user_allowlist is not present
+  return !policy.has_user_allowlist()
+             ? absl::optional<bool>{policy.user_whitelist()
+                                        .user_whitelist_size() == 0}
+             : absl::optional<bool>{
+                   policy.user_allowlist().user_allowlist_size() == 0};
 }
 
 // Decodes the allow_new_users (DeviceAllowNewUsers) and user_allowlist
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 091852b..1ee8e617 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -3766,8 +3766,9 @@
 
 // Ensure that autofill suggestions are properly read out via ChromeVox.
 // This is a regressions test for crbug.com/1208913.
+// Disabled due to flakiness. crbug.com/1294266
 IN_PROC_BROWSER_TEST_F(AutofillChromeVoxTest,
-                       TestNotificationOfAutofillDropdown) {
+                       DISABLED_TestNotificationOfAutofillDropdown) {
   CreateTestProfile();
 
   // Load the test page.
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index aaf8619..6086ddc 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -61,10 +61,6 @@
 class RulesetService;
 }
 
-namespace federated_learning {
-class FlocSortingLshClustersService;
-}
-
 namespace variations {
 class VariationsService;
 }
@@ -221,11 +217,6 @@
   virtual subresource_filter::RulesetService*
   subresource_filter_ruleset_service() = 0;
 
-  // Returns the service providing versioned storage for a list of limit values
-  // for calculating the floc based on SortingLSH.
-  virtual federated_learning::FlocSortingLshClustersService*
-  floc_sorting_lsh_clusters_service() = 0;
-
   // Returns the StartupData which owns any pre-created objects in //chrome
   // before the full browser starts.
   virtual StartupData* startup_data() = 0;
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index cd8c5f9e..ccc87a0 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -97,8 +97,6 @@
 #include "components/component_updater/component_updater_service.h"
 #include "components/component_updater/timer_update_scheduler.h"
 #include "components/crash/core/common/crash_key.h"
-#include "components/federated_learning/floc_constants.h"
-#include "components/federated_learning/floc_sorting_lsh_clusters_service.h"
 #include "components/gcm_driver/gcm_driver.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/metrics/metrics_pref_names.h"
@@ -1036,14 +1034,6 @@
   return subresource_filter_ruleset_service_.get();
 }
 
-federated_learning::FlocSortingLshClustersService*
-BrowserProcessImpl::floc_sorting_lsh_clusters_service() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!floc_sorting_lsh_clusters_service_)
-    CreateFlocSortingLshClustersService();
-  return floc_sorting_lsh_clusters_service_.get();
-}
-
 StartupData* BrowserProcessImpl::startup_data() {
   return startup_data_;
 }
@@ -1310,12 +1300,6 @@
       subresource_filter::RulesetService::Create(local_state(), user_data_dir);
 }
 
-void BrowserProcessImpl::CreateFlocSortingLshClustersService() {
-  DCHECK(!floc_sorting_lsh_clusters_service_);
-  floc_sorting_lsh_clusters_service_ =
-      std::make_unique<federated_learning::FlocSortingLshClustersService>();
-}
-
 #if !BUILDFLAG(IS_ANDROID)
 // Android's GCMDriver currently makes the assumption that it's a singleton.
 // Until this gets fixed, instantiating multiple Java GCMDrivers will throw an
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index e61312a..1784761 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -192,8 +192,6 @@
   safe_browsing::SafeBrowsingService* safe_browsing_service() override;
   subresource_filter::RulesetService* subresource_filter_ruleset_service()
       override;
-  federated_learning::FlocSortingLshClustersService*
-  floc_sorting_lsh_clusters_service() override;
 
   StartupData* startup_data() override;
 
@@ -243,8 +241,6 @@
   void CreateBackgroundPrintingManager();
   void CreateSafeBrowsingService();
   void CreateSubresourceFilterRulesetService();
-  void CreateFlocBlocklistService();
-  void CreateFlocSortingLshClustersService();
   void CreateOptimizationGuideService();
   void CreateStatusTray();
   void CreateBackgroundModeManager();
@@ -346,9 +342,6 @@
   std::unique_ptr<subresource_filter::RulesetService>
       subresource_filter_ruleset_service_;
 
-  std::unique_ptr<federated_learning::FlocSortingLshClustersService>
-      floc_sorting_lsh_clusters_service_;
-
   bool shutting_down_ = false;
 
   bool tearing_down_ = false;
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index 66e7a1f..5e8d19f 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -32,8 +32,6 @@
 #include "chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals.mojom.h"
 #include "chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.h"
 #include "chrome/browser/ui/webui/engagement/site_engagement_ui.h"
-#include "chrome/browser/ui/webui/federated_learning/floc_internals.mojom.h"
-#include "chrome/browser/ui/webui/federated_learning/floc_internals_ui.h"
 #include "chrome/browser/ui/webui/history/history_ui.h"
 #include "chrome/browser/ui/webui/internals/internals_ui.h"
 #include "chrome/browser/ui/webui/media/media_engagement_ui.h"
@@ -704,9 +702,6 @@
   RegisterWebUIControllerInterfaceBinder<::mojom::UsbInternalsPageHandler,
                                          UsbInternalsUI>(map);
 
-  RegisterWebUIControllerInterfaceBinder<federated_learning::mojom::PageHandler,
-                                         FlocInternalsUI>(map);
-
   RegisterWebUIControllerInterfaceBinder<
       segmentation_internals::mojom::PageHandlerFactory,
       SegmentationInternalsUI>(map);
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 0e08cd8..d244ae5 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -51,9 +51,6 @@
 #include "chrome/browser/extensions/chrome_extension_cookies.h"
 #include "chrome/browser/external_protocol/external_protocol_handler.h"
 #include "chrome/browser/favicon/favicon_utils.h"
-#include "chrome/browser/federated_learning/floc_eligibility_observer.h"
-#include "chrome/browser/federated_learning/floc_id_provider.h"
-#include "chrome/browser/federated_learning/floc_id_provider_factory.h"
 #include "chrome/browser/first_party_sets/first_party_sets_pref_names.h"
 #include "chrome/browser/first_party_sets/first_party_sets_util.h"
 #include "chrome/browser/font_family_cache.h"
@@ -307,7 +304,6 @@
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "third_party/blink/public/common/navigation/navigation_policy.h"
 #include "third_party/blink/public/common/switches.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
 #include "third_party/blink/public/public_buildflags.h"
 #include "third_party/widevine/cdm/buildflags.h"
 #include "ui/base/clipboard/clipboard_format_type.h"
@@ -5922,25 +5918,6 @@
   }
 }
 
-blink::mojom::InterestCohortPtr
-ChromeContentBrowserClient::GetInterestCohortForJsApi(
-    content::WebContents* web_contents,
-    const GURL& url,
-    const absl::optional<url::Origin>& top_frame_origin) {
-  federated_learning::FlocEligibilityObserver::GetOrCreateForCurrentDocument(
-      web_contents->GetMainFrame())
-      ->OnInterestCohortApiUsed();
-
-  federated_learning::FlocIdProvider* floc_id_provider =
-      federated_learning::FlocIdProviderFactory::GetForProfile(
-          Profile::FromBrowserContext(web_contents->GetBrowserContext()));
-
-  if (!floc_id_provider)
-    return blink::mojom::InterestCohort::New();
-
-  return floc_id_provider->GetInterestCohortForJsApi(url, top_frame_origin);
-}
-
 bool ChromeContentBrowserClient::IsBluetoothScanningBlocked(
     content::BrowserContext* browser_context,
     const url::Origin& requesting_origin,
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 2ccd15d..ebfb1275 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -665,11 +665,6 @@
       bool user_gesture,
       blink::NavigationDownloadPolicy* download_policy) override;
 
-  blink::mojom::InterestCohortPtr GetInterestCohortForJsApi(
-      content::WebContents* web_contents,
-      const GURL& url,
-      const absl::optional<url::Origin>& top_frame_origin) override;
-
   bool IsBluetoothScanningBlocked(content::BrowserContext* browser_context,
                                   const url::Origin& requesting_origin,
                                   const url::Origin& embedding_origin) override;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 719faef..36c3bb7 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -342,6 +342,7 @@
     "//chromeos/ui/frame",
     "//chromeos/ui/wm",
     "//chromeos/utils",
+    "//components/app_constants",
     "//components/app_restore",
     "//components/arc",
     "//components/arc/common",
@@ -4847,6 +4848,7 @@
     "//chromeos/tpm:test_support",
     "//chromeos/ui/frame:test_support",
     "//components/account_manager_core:test_support",
+    "//components/app_constants",
     "//components/arc",
     "//components/arc/common",
     "//components/arc/common:arc_test_support",
diff --git a/chrome/browser/chromeos/DEPS b/chrome/browser/chromeos/DEPS
index ab5255c..251c8bac 100644
--- a/chrome/browser/chromeos/DEPS
+++ b/chrome/browser/chromeos/DEPS
@@ -13,6 +13,7 @@
   "+chrome/services/keymaster/public",
   "+chrome/services/wilco_dtc_supportd/public",
   "+components/account_manager_core",
+  "+components/app_constants",
   "+components/app_restore",
   "+components/guest_os",
   "+components/reporting",
diff --git a/chrome/browser/chromeos/extensions/default_app_order.cc b/chrome/browser/chromeos/extensions/default_app_order.cc
index b0bc8ba..9e16fb6 100644
--- a/chrome/browser/chromeos/extensions/default_app_order.cc
+++ b/chrome/browser/chromeos/extensions/default_app_order.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/ui/app_list/page_break_constants.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "components/app_constants/constants.h"
 #include "extensions/common/constants.h"
 
 namespace chromeos {
@@ -42,7 +43,7 @@
 
 // Canonical ordering specified in: go/default-apps
 const char* const kDefaultAppOrder[] = {
-    extension_misc::kChromeAppId,
+    app_constants::kChromeAppId,
     arc::kPlayStoreAppId,
 
     extension_misc::kFilesManagerAppId,
diff --git a/chrome/browser/chromeos/extensions/default_app_order_unittest.cc b/chrome/browser/chromeos/extensions/default_app_order_unittest.cc
index cb660c3..34fe98a 100644
--- a/chrome/browser/chromeos/extensions/default_app_order_unittest.cc
+++ b/chrome/browser/chromeos/extensions/default_app_order_unittest.cc
@@ -15,7 +15,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/scoped_path_override.h"
-#include "extensions/common/constants.h"
+#include "components/app_constants/constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
@@ -141,7 +141,7 @@
   default_app_order::Get(&apps);
   EXPECT_EQ(default_app_order::kDefaultAppOrderCount + 2, apps.size());
   EXPECT_EQ(std::string("app1"), apps[0]);
-  EXPECT_EQ(extension_misc::kChromeAppId, apps[1]);
+  EXPECT_EQ(app_constants::kChromeAppId, apps[1]);
   EXPECT_EQ(std::string("app2"),
             apps[default_app_order::kDefaultAppOrderCount + 1]);
 }
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler.cc b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler.cc
index b2edf7f..c1c0480 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/pref_names.h"
+#include "components/app_constants/constants.h"
 #include "components/prefs/pref_service.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
@@ -18,8 +19,8 @@
 
 // Extensions that should not be attempted to be uninstalled and reinstalled.
 const char* const kExemptExtensions[] = {
-    extension_misc::kChromeAppId,
-    extension_misc::kLacrosAppId,
+    app_constants::kChromeAppId,
+    app_constants::kLacrosAppId,
 };
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_browsertest.cc b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_browsertest.cc
index 4a9e304..be86623 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_browsertest.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_browsertest.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/extensions/pending_extension_manager.h"
 #include "chrome/browser/extensions/policy_test_utils.h"
 #include "chrome/browser/policy/extension_force_install_mixin.h"
+#include "components/app_constants/constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/test/policy_builder.h"
 #include "content/public/test/browser_test.h"
@@ -33,8 +34,8 @@
 namespace {
 
 const char* const kExemptExtensions[] = {
-    extension_misc::kChromeAppId,
-    extension_misc::kLacrosAppId,
+    app_constants::kChromeAppId,
+    app_constants::kLacrosAppId,
 };
 
 const char kAccountId[] = "public-session@test";
diff --git a/chrome/browser/component_updater/floc_component_installer.cc b/chrome/browser/component_updater/floc_component_installer.cc
deleted file mode 100644
index e9663c9..0000000
--- a/chrome/browser/component_updater/floc_component_installer.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2020 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/component_updater/floc_component_installer.h"
-
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/version.h"
-#include "components/component_updater/component_updater_paths.h"
-#include "components/federated_learning/floc_constants.h"
-#include "components/federated_learning/floc_sorting_lsh_clusters_service.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-
-namespace component_updater {
-
-// The extension id is: cmahhnpholdijhjokonmfdjbfmklppij
-constexpr uint8_t kFlocComponentPublicKeySHA256[32] = {
-    0x2c, 0x07, 0x7d, 0xf7, 0xeb, 0x38, 0x97, 0x9e, 0xae, 0xdc, 0x53,
-    0x91, 0x5c, 0xab, 0xff, 0x89, 0xbc, 0xf0, 0xd9, 0x30, 0xd2, 0x2e,
-    0x8f, 0x68, 0x3a, 0xf9, 0x21, 0x91, 0x9f, 0xc1, 0x84, 0xa1};
-
-constexpr char kFlocComponentFetcherManifestName[] =
-    "Federated Learning of Cohorts";
-
-FlocComponentInstallerPolicy::FlocComponentInstallerPolicy(
-    federated_learning::FlocSortingLshClustersService*
-        floc_sorting_lsh_clusters_service)
-    : floc_sorting_lsh_clusters_service_(floc_sorting_lsh_clusters_service) {}
-
-FlocComponentInstallerPolicy::~FlocComponentInstallerPolicy() = default;
-
-bool FlocComponentInstallerPolicy::SupportsGroupPolicyEnabledComponentUpdates()
-    const {
-  return true;
-}
-
-// Public data is delivered via this component, no need for encryption.
-bool FlocComponentInstallerPolicy::RequiresNetworkEncryption() const {
-  return false;
-}
-
-update_client::CrxInstaller::Result
-FlocComponentInstallerPolicy::OnCustomInstall(
-    const base::Value& manifest,
-    const base::FilePath& install_dir) {
-  return update_client::CrxInstaller::Result(0);  // Nothing custom here.
-}
-
-void FlocComponentInstallerPolicy::OnCustomUninstall() {}
-
-void FlocComponentInstallerPolicy::ComponentReady(
-    const base::Version& version,
-    const base::FilePath& install_dir,
-    base::Value manifest) {
-  DCHECK(!install_dir.empty());
-
-  floc_sorting_lsh_clusters_service_->OnSortingLshClustersFileReady(
-      install_dir.Append(federated_learning::kSortingLshClustersFileName),
-      version);
-}
-
-// Called during startup and installation before ComponentReady().
-bool FlocComponentInstallerPolicy::VerifyInstallation(
-    const base::Value& manifest,
-    const base::FilePath& install_dir) const {
-  if (!base::PathExists(install_dir))
-    return false;
-
-  absl::optional<int> floc_component_format =
-      manifest.FindIntKey(federated_learning::kManifestFlocComponentFormatKey);
-  if (!floc_component_format ||
-      *floc_component_format !=
-          federated_learning::kCurrentFlocComponentFormatVersion) {
-    return false;
-  }
-
-  return true;
-}
-
-base::FilePath FlocComponentInstallerPolicy::GetRelativeInstallDir() const {
-  return base::FilePath(federated_learning::kTopLevelDirectoryName);
-}
-
-void FlocComponentInstallerPolicy::GetHash(std::vector<uint8_t>* hash) const {
-  hash->assign(std::begin(kFlocComponentPublicKeySHA256),
-               std::end(kFlocComponentPublicKeySHA256));
-}
-
-std::string FlocComponentInstallerPolicy::GetName() const {
-  return kFlocComponentFetcherManifestName;
-}
-
-update_client::InstallerAttributes
-FlocComponentInstallerPolicy::GetInstallerAttributes() const {
-  return update_client::InstallerAttributes();
-}
-
-void RegisterFlocComponent(
-    ComponentUpdateService* cus,
-    federated_learning::FlocSortingLshClustersService*
-        floc_sorting_lsh_clusters_service) {
-  auto installer = base::MakeRefCounted<ComponentInstaller>(
-      std::make_unique<FlocComponentInstallerPolicy>(
-          floc_sorting_lsh_clusters_service));
-  installer->Register(cus, base::OnceClosure());
-}
-
-}  // namespace component_updater
diff --git a/chrome/browser/component_updater/floc_component_installer.h b/chrome/browser/component_updater/floc_component_installer.h
deleted file mode 100644
index 880a1cb..0000000
--- a/chrome/browser/component_updater/floc_component_installer.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2020 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_COMPONENT_UPDATER_FLOC_COMPONENT_INSTALLER_H_
-#define CHROME_BROWSER_COMPONENT_UPDATER_FLOC_COMPONENT_INSTALLER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/memory/raw_ptr.h"
-#include "components/component_updater/component_installer.h"
-
-namespace base {
-class Value;
-}  // namespace base
-
-namespace federated_learning {
-class FlocSortingLshClustersService;
-}  // namespace federated_learning
-
-namespace component_updater {
-
-class ComponentUpdateService;
-
-// Component for receiving FLoC files, e.g. sorting-lsh, etc.
-class FlocComponentInstallerPolicy : public ComponentInstallerPolicy {
- public:
-  explicit FlocComponentInstallerPolicy(
-      federated_learning::FlocSortingLshClustersService*
-          floc_sorting_lsh_clusters_service);
-  ~FlocComponentInstallerPolicy() override;
-
-  FlocComponentInstallerPolicy(const FlocComponentInstallerPolicy&) = delete;
-  FlocComponentInstallerPolicy& operator=(const FlocComponentInstallerPolicy&) =
-      delete;
-
- private:
-  friend class FlocComponentInstallerTest;
-
-  // ComponentInstallerPolicy implementation.
-  bool SupportsGroupPolicyEnabledComponentUpdates() const override;
-  bool RequiresNetworkEncryption() const override;
-  update_client::CrxInstaller::Result OnCustomInstall(
-      const base::Value& manifest,
-      const base::FilePath& install_dir) override;
-  void OnCustomUninstall() override;
-  bool VerifyInstallation(const base::Value& manifest,
-                          const base::FilePath& install_dir) const override;
-  void ComponentReady(const base::Version& version,
-                      const base::FilePath& install_dir,
-                      base::Value manifest) override;
-  base::FilePath GetRelativeInstallDir() const override;
-  void GetHash(std::vector<uint8_t>* hash) const override;
-  std::string GetName() const override;
-  update_client::InstallerAttributes GetInstallerAttributes() const override;
-
-  raw_ptr<federated_learning::FlocSortingLshClustersService>
-      floc_sorting_lsh_clusters_service_;
-};
-
-void RegisterFlocComponent(
-    ComponentUpdateService* cus,
-    federated_learning::FlocSortingLshClustersService*
-        floc_sorting_lsh_clusters_service);
-
-}  // namespace component_updater
-
-#endif  // CHROME_BROWSER_COMPONENT_UPDATER_FLOC_COMPONENT_INSTALLER_H_
diff --git a/chrome/browser/component_updater/floc_component_installer_unittest.cc b/chrome/browser/component_updater/floc_component_installer_unittest.cc
deleted file mode 100644
index c7f28ff6..0000000
--- a/chrome/browser/component_updater/floc_component_installer_unittest.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2020 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/component_updater/floc_component_installer.h"
-
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/raw_ptr.h"
-#include "base/run_loop.h"
-#include "base/strings/string_util.h"
-#include "base/task/sequenced_task_runner.h"
-#include "base/test/bind.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "components/component_updater/mock_component_updater_service.h"
-#include "components/federated_learning/floc_constants.h"
-#include "components/federated_learning/floc_sorting_lsh_clusters_service.h"
-#include "content/public/test/browser_task_environment.h"
-#include "testing/gmock/include/gmock/gmock-actions.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace component_updater {
-
-namespace {
-
-ACTION_P(QuitMessageLoop, loop) {
-  loop->Quit();
-  return true;
-}
-
-// This class monitors the OnSortingLshClustersFileReady method calls.
-class MockFlocSortingLshClustersService
-    : public federated_learning::FlocSortingLshClustersService {
- public:
-  MockFlocSortingLshClustersService() = default;
-
-  MockFlocSortingLshClustersService(const MockFlocSortingLshClustersService&) =
-      delete;
-  MockFlocSortingLshClustersService& operator=(
-      const MockFlocSortingLshClustersService&) = delete;
-
-  ~MockFlocSortingLshClustersService() override = default;
-
-  void OnSortingLshClustersFileReady(const base::FilePath& file_path,
-                                     const base::Version& version) override {
-    file_paths_.push_back(file_path);
-    versions_.push_back(version);
-  }
-
-  const std::vector<base::FilePath>& file_paths() const { return file_paths_; }
-  const std::vector<base::Version>& versions() const { return versions_; }
-
- private:
-  std::vector<base::FilePath> file_paths_;
-  std::vector<base::Version> versions_;
-};
-
-}  //  namespace
-
-class FlocComponentInstallerTest : public PlatformTest {
- public:
-  FlocComponentInstallerTest() = default;
-
-  FlocComponentInstallerTest(const FlocComponentInstallerTest&) = delete;
-  FlocComponentInstallerTest& operator=(const FlocComponentInstallerTest&) =
-      delete;
-
-  ~FlocComponentInstallerTest() override = default;
-
-  void SetUp() override {
-    PlatformTest::SetUp();
-
-    ASSERT_TRUE(component_install_dir_.CreateUniqueTempDir());
-
-    auto test_floc_sorting_lsh_clusters_service =
-        std::make_unique<MockFlocSortingLshClustersService>();
-    test_floc_sorting_lsh_clusters_service->SetBackgroundTaskRunnerForTesting(
-        base::SequencedTaskRunnerHandle::Get());
-
-    test_floc_sorting_lsh_clusters_service_ =
-        test_floc_sorting_lsh_clusters_service.get();
-
-    TestingBrowserProcess::GetGlobal()->SetFlocSortingLshClustersService(
-        std::move(test_floc_sorting_lsh_clusters_service));
-
-    policy_ = std::make_unique<FlocComponentInstallerPolicy>(
-        test_floc_sorting_lsh_clusters_service_);
-  }
-
-  void TearDown() override {
-    TestingBrowserProcess::GetGlobal()->SetFlocSortingLshClustersService(
-        nullptr);
-    PlatformTest::TearDown();
-  }
-
-  MockFlocSortingLshClustersService* sorting_lsh_clusters_service() {
-    return test_floc_sorting_lsh_clusters_service_;
-  }
-
-  void WriteStringToFile(const std::string& data, const base::FilePath& path) {
-    ASSERT_EQ(base::WriteFile(path, data.data(), data.length()),
-              static_cast<int32_t>(data.length()));
-  }
-
-  base::FilePath component_install_dir() {
-    return component_install_dir_.GetPath();
-  }
-
-  void CreateTestFlocComponentFiles(const std::string& sorting_lsh_content) {
-    base::FilePath sorting_lsh_file_path = component_install_dir().Append(
-        federated_learning::kSortingLshClustersFileName);
-    ASSERT_NO_FATAL_FAILURE(
-        WriteStringToFile(sorting_lsh_content, sorting_lsh_file_path));
-  }
-
-  void LoadFlocComponent(const std::string& content_version,
-                         int format_version) {
-    base::Value manifest(base::Value::Type::DICTIONARY);
-    manifest.SetIntKey(federated_learning::kManifestFlocComponentFormatKey,
-                       format_version);
-
-    if (!policy_->VerifyInstallation(manifest, component_install_dir()))
-      return;
-
-    policy_->ComponentReady(base::Version(content_version),
-                            component_install_dir(), std::move(manifest));
-  }
-
- protected:
-  content::BrowserTaskEnvironment task_environment_;
-  base::ScopedTempDir component_install_dir_;
-  std::unique_ptr<FlocComponentInstallerPolicy> policy_;
-  raw_ptr<MockFlocSortingLshClustersService>
-      test_floc_sorting_lsh_clusters_service_ = nullptr;
-};
-
-TEST_F(FlocComponentInstallerTest, TestComponentRegistration) {
-  auto component_updater =
-      std::make_unique<component_updater::MockComponentUpdateService>();
-
-  base::RunLoop run_loop;
-  EXPECT_CALL(*component_updater, RegisterComponent(testing::_))
-      .Times(1)
-      .WillOnce(QuitMessageLoop(&run_loop));
-
-  RegisterFlocComponent(component_updater.get(),
-                        sorting_lsh_clusters_service());
-  run_loop.Run();
-}
-
-TEST_F(FlocComponentInstallerTest, LoadFlocComponent) {
-  ASSERT_TRUE(sorting_lsh_clusters_service());
-
-  std::string contents = "abcd";
-  ASSERT_NO_FATAL_FAILURE(CreateTestFlocComponentFiles(contents));
-  ASSERT_NO_FATAL_FAILURE(LoadFlocComponent(
-      "1.0.1", federated_learning::kCurrentFlocComponentFormatVersion));
-
-  ASSERT_EQ(sorting_lsh_clusters_service()->file_paths().size(), 1u);
-  ASSERT_EQ(sorting_lsh_clusters_service()->versions().size(), 1u);
-
-  // Assert that the file path is the concatenation of |component_install_dir_|
-  // and the corresponding file name, which implies that the |version| argument
-  // has no impact. In reality, though, the |component_install_dir_| and the
-  // |version| should always match.
-  ASSERT_EQ(sorting_lsh_clusters_service()->file_paths()[0].AsUTF8Unsafe(),
-            component_install_dir()
-                .Append(federated_learning::kSortingLshClustersFileName)
-                .AsUTF8Unsafe());
-
-  EXPECT_EQ(sorting_lsh_clusters_service()->versions()[0].GetString(), "1.0.1");
-
-  std::string actual_contents;
-  ASSERT_TRUE(base::ReadFileToString(
-      sorting_lsh_clusters_service()->file_paths()[0], &actual_contents));
-  EXPECT_EQ(actual_contents, contents);
-}
-
-TEST_F(FlocComponentInstallerTest, UnsupportedFormatVersionIgnored) {
-  ASSERT_TRUE(sorting_lsh_clusters_service());
-  const std::string contents = "future stuff";
-  ASSERT_NO_FATAL_FAILURE(CreateTestFlocComponentFiles(contents));
-  ASSERT_NO_FATAL_FAILURE(LoadFlocComponent(
-      "1.0.0", federated_learning::kCurrentFlocComponentFormatVersion + 1));
-  EXPECT_EQ(sorting_lsh_clusters_service()->file_paths().size(), 0u);
-}
-
-}  // namespace component_updater
diff --git a/chrome/browser/component_updater/registration.cc b/chrome/browser/component_updater/registration.cc
index e03189a..cc3406e 100644
--- a/chrome/browser/component_updater/registration.cc
+++ b/chrome/browser/component_updater/registration.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/component_updater/crowd_deny_component_installer.h"
 #include "chrome/browser/component_updater/file_type_policies_component_installer.h"
 #include "chrome/browser/component_updater/first_party_sets_component_installer.h"
-#include "chrome/browser/component_updater/floc_component_installer.h"
 #include "chrome/browser/component_updater/hyphenation_component_installer.h"
 #include "chrome/browser/component_updater/mei_preload_component_installer.h"
 #include "chrome/browser/component_updater/pki_metadata_component_installer.h"
@@ -127,8 +126,6 @@
 #endif  // BUILDFLAG(ENABLE_NACL) && !BUILDFLAG(IS_ANDROID)
 
   RegisterSubresourceFilterComponent(cus);
-  RegisterFlocComponent(cus,
-                        g_browser_process->floc_sorting_lsh_clusters_service());
   RegisterOnDeviceHeadSuggestComponent(
       cus, g_browser_process->GetApplicationLocale());
   RegisterOptimizationHintsComponent(cus);
diff --git a/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc b/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc
index cdcec1c6..2bb68c0e 100644
--- a/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc
+++ b/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc
@@ -37,7 +37,6 @@
          host == chrome::kChromeUIDomainReliabilityInternalsHost ||
          host == chrome::kChromeUIDownloadInternalsHost ||
          host == chrome::kChromeUIFamilyLinkUserInternalsHost ||
-         host == chrome::kChromeUIFlocInternalsHost ||
          host == chrome::kChromeUIGCMInternalsHost ||
          host == chrome::kChromeUIInternalsHost ||
          host == chrome::kChromeUIInterstitialHost ||
diff --git a/chrome/browser/enterprise/connectors/reporting/reporting_service_settings.cc b/chrome/browser/enterprise/connectors/reporting/reporting_service_settings.cc
index aa039457..fe0324ed 100644
--- a/chrome/browser/enterprise/connectors/reporting/reporting_service_settings.cc
+++ b/chrome/browser/enterprise/connectors/reporting/reporting_service_settings.cc
@@ -79,14 +79,16 @@
   const base::Value* enabled_opt_in_events_value =
       settings_value.FindListKey(kKeyEnabledOptInEvents);
   if (enabled_opt_in_events_value) {
-    for (const base::Value& event : enabled_opt_in_events_value->GetList()) {
+    for (const base::Value& event :
+         enabled_opt_in_events_value->GetListDeprecated()) {
       DCHECK(event.is_dict());
       const std::string* name = event.FindStringKey(kKeyOptInEventName);
       const base::Value* url_patterns_value =
           event.FindListKey(kKeyOptInEventUrlPatterns);
 
       DCHECK(url_patterns_value->is_list());
-      for (const base::Value& url_pattern : url_patterns_value->GetList()) {
+      for (const base::Value& url_pattern :
+           url_patterns_value->GetListDeprecated()) {
         DCHECK(url_pattern.is_string());
 
         enabled_opt_in_events_[*name].push_back(url_pattern.GetString());
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_util.cc b/chrome/browser/extensions/api/autofill_private/autofill_util.cc
index 8d40be3..55483af 100644
--- a/chrome/browser/extensions/api/autofill_private/autofill_util.cc
+++ b/chrome/browser/extensions/api/autofill_private/autofill_util.cc
@@ -169,6 +169,16 @@
   // |personal_data|.
   metadata->is_migratable = std::make_unique<bool>(
       credit_card.IsValid() && !personal_data.IsServerCard(&credit_card));
+  metadata->is_virtual_card_enrollment_eligible = std::make_unique<bool>(
+      credit_card.virtual_card_enrollment_state() ==
+          autofill::CreditCard::VirtualCardEnrollmentState::ENROLLED ||
+      credit_card.virtual_card_enrollment_state() ==
+          autofill::CreditCard::VirtualCardEnrollmentState::
+              UNENROLLED_AND_ELIGIBLE);
+  metadata->is_virtual_card_enrolled = std::make_unique<bool>(
+      credit_card.virtual_card_enrollment_state() ==
+      autofill::CreditCard::VirtualCardEnrollmentState::ENROLLED);
+
   card.metadata = std::move(metadata);
 
   return card;
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
index 3c81060..1cc324d 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
@@ -125,9 +125,9 @@
 
   const Event& event = *iter->second;
   CHECK(event.event_args);
-  CHECK_GE(1u, event.event_args->GetList().size());
+  CHECK_GE(1u, event.event_args->GetListDeprecated().size());
   auto site_settings = api::developer_private::UserSiteSettings::FromValue(
-      event.event_args->GetList()[0]);
+      event.event_args->GetListDeprecated()[0]);
   if (!site_settings)
     return false;
 
diff --git a/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc b/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
index 64dbc1f2..60427f0 100644
--- a/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
+++ b/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
@@ -19,6 +19,8 @@
 #include "net/base/test_completion_callback.h"
 #include "net/socket/socket_test_util.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_builder.h"
 #include "net/url_request/url_request_test_util.h"
 #include "services/network/network_context.h"
 #include "services/network/public/mojom/network_context.mojom.h"
@@ -35,8 +37,9 @@
 class TCPSocketUnitTestBase : public extensions::ExtensionServiceTestBase {
  public:
   TCPSocketUnitTestBase()
-      : url_request_context_(true /* delay_initialization */) {}
-  ~TCPSocketUnitTestBase() override {}
+      : url_request_context_builder_(
+            net::CreateTestURLRequestContextBuilder()) {}
+  ~TCPSocketUnitTestBase() override = default;
 
   std::unique_ptr<TCPSocket> CreateSocket() {
     auto socket = std::make_unique<TCPSocket>(&profile_, FAKE_ID);
@@ -88,18 +91,19 @@
   void SetUp() override { InitializeEmptyExtensionService(); }
 
   void Initialize() {
-    url_request_context_.Init();
+    url_request_context_ = url_request_context_builder_->Build();
     network_context_ = std::make_unique<network::NetworkContext>(
         nullptr, network_context_remote_.BindNewPipeAndPassReceiver(),
-        &url_request_context_,
+        url_request_context_.get(),
         /*cors_exempt_header_list=*/std::vector<std::string>());
     partition_.set_network_context(network_context_remote_.get());
   }
 
-  net::TestURLRequestContext url_request_context_;
+  std::unique_ptr<net::URLRequestContextBuilder> url_request_context_builder_;
 
  private:
   TestingProfile profile_;
+  std::unique_ptr<net::URLRequestContext> url_request_context_;
   content::TestStoragePartition partition_;
   std::unique_ptr<network::NetworkContext> network_context_;
   mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
@@ -112,7 +116,7 @@
  public:
   TCPSocketUnitTest() : TCPSocketUnitTestBase() {
     mock_client_socket_factory_.set_enable_read_if_ready(true);
-    url_request_context_.set_client_socket_factory(
+    url_request_context_builder_->set_client_socket_factory_for_testing(
         &mock_client_socket_factory_);
     Initialize();
   }
@@ -540,9 +544,9 @@
 class TCPSocketSettingsTest : public TCPSocketUnitTestBase,
                               public ::testing::WithParamInterface<bool> {
  public:
-  TCPSocketSettingsTest()
-      : TCPSocketUnitTestBase(), client_socket_factory_(GetParam()) {
-    url_request_context_.set_client_socket_factory(&client_socket_factory_);
+  TCPSocketSettingsTest() : client_socket_factory_(GetParam()) {
+    url_request_context_builder_->set_client_socket_factory_for_testing(
+        &client_socket_factory_);
     Initialize();
   }
   ~TCPSocketSettingsTest() override {}
diff --git a/chrome/browser/extensions/api/socket/tls_socket_unittest.cc b/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
index e3b8a99..92183e60 100644
--- a/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
+++ b/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
@@ -18,6 +18,8 @@
 #include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
 #include "net/socket/socket_test_util.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_builder.h"
 #include "net/url_request/url_request_test_util.h"
 #include "services/network/network_context.h"
 #include "services/network/public/mojom/network_context.mojom.h"
@@ -33,8 +35,10 @@
 
 class TLSSocketTestBase : public extensions::ExtensionServiceTestBase {
  public:
-  TLSSocketTestBase() : url_request_context_(true) {}
-  ~TLSSocketTestBase() override {}
+  TLSSocketTestBase()
+      : url_request_context_builder_(
+            net::CreateTestURLRequestContextBuilder()) {}
+  ~TLSSocketTestBase() override = default;
 
   // Creates a TCP socket.
   std::unique_ptr<TCPSocket> CreateTCPSocket() {
@@ -90,19 +94,20 @@
   void SetUp() override { InitializeEmptyExtensionService(); }
 
   void Initialize() {
-    url_request_context_.Init();
+    url_request_context_ = url_request_context_builder_->Build();
     network_context_ = std::make_unique<network::NetworkContext>(
         nullptr, network_context_remote_.BindNewPipeAndPassReceiver(),
-        &url_request_context_,
+        url_request_context_.get(),
         /*cors_exempt_header_list=*/std::vector<std::string>());
     partition_.set_network_context(network_context_remote_.get());
   }
 
-  net::TestURLRequestContext url_request_context_;
+  std::unique_ptr<net::URLRequestContextBuilder> url_request_context_builder_;
 
  private:
   static const int kPort = 1234;
   TestingProfile profile_;
+  std::unique_ptr<net::URLRequestContext> url_request_context_;
   content::TestStoragePartition partition_;
   std::unique_ptr<network::NetworkContext> network_context_;
   mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
@@ -115,7 +120,7 @@
  public:
   TLSSocketTest() : TLSSocketTestBase() {
     mock_client_socket_factory_.set_enable_read_if_ready(true);
-    url_request_context_.set_client_socket_factory(
+    url_request_context_builder_->set_client_socket_factory_for_testing(
         &mock_client_socket_factory_);
     Initialize();
   }
diff --git a/chrome/browser/feature_guide/notifications/feature_notification_guide_service.cc b/chrome/browser/feature_guide/notifications/feature_notification_guide_service.cc
index d2218964..90dca81 100644
--- a/chrome/browser/feature_guide/notifications/feature_notification_guide_service.cc
+++ b/chrome/browser/feature_guide/notifications/feature_notification_guide_service.cc
@@ -19,6 +19,9 @@
     "FeatureNotificationGuideSkipCheckForLowEngagedUsers",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kUseFeatureEngagementForUserTargeting{
+    "UseFeatureEngagementForUserTargeting", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 
 FeatureNotificationGuideService::FeatureNotificationGuideService() = default;
diff --git a/chrome/browser/feature_guide/notifications/feature_notification_guide_service.h b/chrome/browser/feature_guide/notifications/feature_notification_guide_service.h
index 3d0d76f..c8f22d3 100644
--- a/chrome/browser/feature_guide/notifications/feature_notification_guide_service.h
+++ b/chrome/browser/feature_guide/notifications/feature_notification_guide_service.h
@@ -32,6 +32,10 @@
 // Feature flag to determine whether to skip check for the low engaged users.
 extern const base::Feature kSkipCheckForLowEngagedUsers;
 
+// Feature flag to determine whether feature engagement tracker should be used
+// instead of segmentation platform.
+extern const base::Feature kUseFeatureEngagementForUserTargeting;
+
 }  // namespace features
 
 // The central class responsible for managing feature notification guide in
diff --git a/chrome/browser/feature_guide/notifications/feature_notification_guide_service_factory.cc b/chrome/browser/feature_guide/notifications/feature_notification_guide_service_factory.cc
index 5baebf1..8dd4062e 100644
--- a/chrome/browser/feature_guide/notifications/feature_notification_guide_service_factory.cc
+++ b/chrome/browser/feature_guide/notifications/feature_notification_guide_service_factory.cc
@@ -32,17 +32,17 @@
 // Default notification time interval in days.
 constexpr int kDefaultNotificationTimeIntervalDays = 7;
 
-void AddFeature(std::vector<FeatureType>& enabled_features,
-                const std::string& feature_name,
-                FeatureType feature_type,
-                int repeat_count) {
+void AddFeatureIfEnabled(std::vector<FeatureType>* enabled_features,
+                         const std::string& feature_name,
+                         FeatureType feature_type,
+                         int repeat_count) {
   if (!base::GetFieldTrialParamByFeatureAsBool(
           features::kFeatureNotificationGuide, feature_name, false)) {
     return;
   }
 
   for (int i = 0; i < repeat_count; i++) {
-    enabled_features.emplace_back(feature_type);
+    enabled_features->emplace_back(feature_type);
   }
 }
 
@@ -52,16 +52,16 @@
       features::kFeatureNotificationGuide, "feature_notification_repeat_count",
       1);
 
-  AddFeature(enabled_features, "enable_feature_incognito_tab",
-             FeatureType::kIncognitoTab, repeat_count);
-  AddFeature(enabled_features, "enable_feature_ntp_suggestion_card",
-             FeatureType::kNTPSuggestionCard, repeat_count);
-  AddFeature(enabled_features, "enable_feature_voice_search",
-             FeatureType::kVoiceSearch, repeat_count);
-  AddFeature(enabled_features, "enable_feature_default_browser",
-             FeatureType::kDefaultBrowser, repeat_count);
-  AddFeature(enabled_features, "enable_feature_sign_in", FeatureType::kSignIn,
-             repeat_count);
+  AddFeatureIfEnabled(&enabled_features, "enable_feature_incognito_tab",
+                      FeatureType::kIncognitoTab, repeat_count);
+  AddFeatureIfEnabled(&enabled_features, "enable_feature_ntp_suggestion_card",
+                      FeatureType::kNTPSuggestionCard, repeat_count);
+  AddFeatureIfEnabled(&enabled_features, "enable_feature_voice_search",
+                      FeatureType::kVoiceSearch, repeat_count);
+  AddFeatureIfEnabled(&enabled_features, "enable_feature_default_browser",
+                      FeatureType::kDefaultBrowser, repeat_count);
+  AddFeatureIfEnabled(&enabled_features, "enable_feature_sign_in",
+                      FeatureType::kSignIn, repeat_count);
   return enabled_features;
 }
 
diff --git a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc
index 3b86bc4d..0e63369 100644
--- a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc
+++ b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/notifications/scheduler/public/notification_params.h"
 #include "chrome/browser/notifications/scheduler/public/notification_schedule_service.h"
 #include "chrome/browser/notifications/scheduler/public/schedule_params.h"
+#include "components/feature_engagement/public/feature_constants.h"
 #include "components/feature_engagement/public/tracker.h"
 #include "components/optimization_guide/proto/models.pb.h"
 #include "components/segmentation_platform/public/config.h"
@@ -75,16 +76,44 @@
   if (!init_success)
     return;
 
-  if (!base::FeatureList::IsEnabled(
-          feature_guide::features::kSegmentationModelLowEngagedUsers)) {
+  CheckForLowEnagedUser();
+  StartCheckingForEligibleFeatures();
+}
+
+void FeatureNotificationGuideServiceImpl::CheckForLowEnagedUser() {
+  // Skip low engagement check if enabled. For testing only.
+  if (base::FeatureList::IsEnabled(
+          feature_guide::features::kSkipCheckForLowEngagedUsers)) {
+    is_low_engaged_user_ = false;
     return;
   }
 
-  segmentation_platform_service_->GetSelectedSegment(
-      segmentation_platform::kChromeLowUserEngagementSegmentationKey,
-      base::BindOnce(
-          &FeatureNotificationGuideServiceImpl::OnQuerySegmentationPlatform,
-          weak_ptr_factory_.GetWeakPtr()));
+  // Use tracker instead of segmentation if enabled.
+  if (base::FeatureList::IsEnabled(
+          feature_guide::features::kUseFeatureEngagementForUserTargeting)) {
+#if BUILDFLAG(IS_ANDROID)
+    if (tracker_->ShouldTriggerHelpUI(
+            feature_engagement::kIPHLowUserEngagementDetectorFeature)) {
+      is_low_engaged_user_ = false;
+    }
+#endif
+    return;
+  }
+
+  if (!base::FeatureList::IsEnabled(
+          feature_guide::features::kSegmentationModelLowEngagedUsers)) {
+    is_low_engaged_user_ = false;
+    return;
+  }
+
+  // Check segmentation model result.
+  auto result = segmentation_platform_service_->GetCachedSegmentResult(
+      segmentation_platform::kChromeLowUserEngagementSegmentationKey);
+  is_low_engaged_user_ =
+      result.is_ready && result.segment.has_value() &&
+      result.segment.value() ==
+          optimization_guide::proto::OptimizationTarget::
+              OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT;
 }
 
 void FeatureNotificationGuideServiceImpl::CloseRedundantNotifications() {
@@ -103,25 +132,6 @@
   }
 }
 
-void FeatureNotificationGuideServiceImpl::OnQuerySegmentationPlatform(
-    const segmentation_platform::SegmentSelectionResult& result) {
-  if (base::FeatureList::IsEnabled(
-          feature_guide::features::kSkipCheckForLowEngagedUsers)) {
-    StartCheckingForEligibleFeatures();
-    return;
-  }
-
-  bool is_low_engaged_user =
-      result.is_ready && result.segment.has_value() &&
-      result.segment.value() ==
-          optimization_guide::proto::OptimizationTarget::
-              OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT;
-  if (!is_low_engaged_user)
-    return;
-
-  StartCheckingForEligibleFeatures();
-}
-
 void FeatureNotificationGuideServiceImpl::StartCheckingForEligibleFeatures() {
   bool schedule_immediately = true;
   for (auto feature : config_.enabled_features) {
@@ -129,6 +139,9 @@
     if (base::Contains(scheduled_feature_guids_, guid))
       continue;
 
+    if (!is_low_engaged_user_ && ShouldTargetLowEngagedUsers(feature))
+      continue;
+
     if (delegate_->ShouldSkipFeature(feature))
       continue;
 
diff --git a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.h b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.h
index f7b3033..061458a7 100644
--- a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.h
+++ b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.h
@@ -58,6 +58,7 @@
   void StartCheckingForEligibleFeatures();
   void ScheduleNotification(FeatureType feature, bool schedule_immediately);
   void CloseRedundantNotifications();
+  void CheckForLowEnagedUser();
 
   std::unique_ptr<FeatureNotificationGuideService::Delegate> delegate_;
   raw_ptr<notifications::NotificationScheduleService> notification_scheduler_;
@@ -69,6 +70,7 @@
 
   std::set<std::string> scheduled_feature_guids_;
   absl::optional<base::Time> last_notification_schedule_time_;
+  bool is_low_engaged_user_{false};
 
   base::WeakPtrFactory<FeatureNotificationGuideServiceImpl> weak_ptr_factory_{
       this};
diff --git a/chrome/browser/feature_guide/notifications/internal/utils.cc b/chrome/browser/feature_guide/notifications/internal/utils.cc
index da47b890..6441fd6 100644
--- a/chrome/browser/feature_guide/notifications/internal/utils.cc
+++ b/chrome/browser/feature_guide/notifications/internal/utils.cc
@@ -76,4 +76,17 @@
 }
 #endif
 
+bool ShouldTargetLowEngagedUsers(FeatureType feature) {
+  switch (feature) {
+    case FeatureType::kIncognitoTab:
+    case FeatureType::kVoiceSearch:
+    case FeatureType::kNTPSuggestionCard:
+      return true;
+    case FeatureType::kDefaultBrowser:
+    case FeatureType::kSignIn:
+    default:
+      return false;
+  }
+}
+
 }  // namespace feature_guide
diff --git a/chrome/browser/feature_guide/notifications/internal/utils.h b/chrome/browser/feature_guide/notifications/internal/utils.h
index 37ab206a..5710061c 100644
--- a/chrome/browser/feature_guide/notifications/internal/utils.h
+++ b/chrome/browser/feature_guide/notifications/internal/utils.h
@@ -33,6 +33,9 @@
 
 #endif
 
+// Whether the feature should only target low engaged users.
+bool ShouldTargetLowEngagedUsers(FeatureType feature);
+
 }  // namespace feature_guide
 
 #endif  // CHROME_BROWSER_FEATURE_GUIDE_NOTIFICATIONS_INTERNAL_UTILS_H_
diff --git a/chrome/browser/feature_guide/notifications/internal/utils_unittest.cc b/chrome/browser/feature_guide/notifications/internal/utils_unittest.cc
index f8e5704..327bc85 100644
--- a/chrome/browser/feature_guide/notifications/internal/utils_unittest.cc
+++ b/chrome/browser/feature_guide/notifications/internal/utils_unittest.cc
@@ -18,4 +18,12 @@
   EXPECT_EQ(FeatureType::kVoiceSearch, FeatureFromCustomData(custom_data));
 }
 
+TEST(FeatureNotificationUtilsTest, LowEngagedUsersCheck) {
+  EXPECT_EQ(true, ShouldTargetLowEngagedUsers(FeatureType::kIncognitoTab));
+  EXPECT_EQ(true, ShouldTargetLowEngagedUsers(FeatureType::kVoiceSearch));
+  EXPECT_EQ(true, ShouldTargetLowEngagedUsers(FeatureType::kNTPSuggestionCard));
+  EXPECT_EQ(false, ShouldTargetLowEngagedUsers(FeatureType::kDefaultBrowser));
+  EXPECT_EQ(false, ShouldTargetLowEngagedUsers(FeatureType::kSignIn));
+}
+
 }  // namespace feature_guide
diff --git a/chrome/browser/federated_learning/COMMON_METADATA b/chrome/browser/federated_learning/COMMON_METADATA
deleted file mode 100644
index 0e6c0305..0000000
--- a/chrome/browser/federated_learning/COMMON_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-team_email: "privacy-sandbox-dev@chromium.org"
diff --git a/chrome/browser/federated_learning/DEPS b/chrome/browser/federated_learning/DEPS
deleted file mode 100644
index 462f899..0000000
--- a/chrome/browser/federated_learning/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+components/federated_learning",
-]
diff --git a/chrome/browser/federated_learning/DIR_METADATA b/chrome/browser/federated_learning/DIR_METADATA
deleted file mode 100644
index 94c4325..0000000
--- a/chrome/browser/federated_learning/DIR_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-mixins: "//chrome/browser/federated_learning/COMMON_METADATA"
diff --git a/chrome/browser/federated_learning/OWNERS b/chrome/browser/federated_learning/OWNERS
deleted file mode 100644
index f8be9e8..0000000
--- a/chrome/browser/federated_learning/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-jkarlin@chromium.org
-yaoxia@chromium.org
diff --git a/chrome/browser/federated_learning/floc_eligibility_browsertest.cc b/chrome/browser/federated_learning/floc_eligibility_browsertest.cc
deleted file mode 100644
index b7d69bd..0000000
--- a/chrome/browser/federated_learning/floc_eligibility_browsertest.cc
+++ /dev/null
@@ -1,627 +0,0 @@
-// Copyright 2021 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/strings/strcat.h"
-#include "base/test/bind.h"
-#include "chrome/browser/federated_learning/floc_id_provider.h"
-#include "chrome/browser/federated_learning/floc_id_provider_factory.h"
-#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/webui/federated_learning/floc_internals.mojom.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "components/embedder_support/switches.h"
-#include "components/federated_learning/features/features.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/page_load_metrics/browser/page_load_metrics_test_waiter.h"
-#include "components/subresource_filter/core/common/test_ruleset_utils.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/test_frame_navigation_observer.h"
-#include "content/public/test/test_host_resolver.h"
-#include "content/public/test/test_navigation_observer.h"
-#include "net/dns/mock_host_resolver.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
-
-namespace {
-
-class FixedFlocIdProvider : public federated_learning::FlocIdProvider {
- public:
-  FixedFlocIdProvider() = default;
-  ~FixedFlocIdProvider() override = default;
-
-  blink::mojom::InterestCohortPtr GetInterestCohortForJsApi(
-      const GURL& url,
-      const absl::optional<url::Origin>& top_frame_origin) const override {
-    blink::mojom::InterestCohortPtr cohort =
-        blink::mojom::InterestCohort::New();
-    cohort->id = "12345";
-    cohort->version = "chrome.6.7.8.9";
-    return cohort;
-  }
-
-  federated_learning::mojom::WebUIFlocStatusPtr GetFlocStatusForWebUi()
-      const override {
-    return nullptr;
-  }
-
-  void MaybeRecordFlocToUkm(ukm::SourceId source_id) override {}
-
-  base::Time GetApproximateNextComputeTime() const override {
-    return base::Time();
-  }
-};
-
-}  // namespace
-
-// Tests behaviors that affect whether the floc API is allowed and/or whether
-// the navigation's associated history entry is eligible for floc computation.
-class FlocEligibilityBrowserTest
-    : public subresource_filter::SubresourceFilterBrowserTest {
- public:
-  FlocEligibilityBrowserTest() {
-    scoped_feature_list_.InitWithFeatures(
-        /*enabled_features=*/{blink::features::kInterestCohortFeaturePolicy},
-        /*disabled_features=*/{
-            federated_learning::
-                kFlocPagesWithAdResourcesDefaultIncludedInFlocComputation});
-  }
-
-  void SetUpOnMainThread() override {
-    subresource_filter::SubresourceFilterBrowserTest::SetUpOnMainThread();
-
-    https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
-    https_server_.AddDefaultHandlers(GetChromeTestDataDir());
-
-    content::SetupCrossSiteRedirector(&https_server_);
-    ASSERT_TRUE(https_server_.Start());
-  }
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
-                                    "InterestCohortAPI");
-  }
-
-  // BrowserTestBase::SetUpInProcessBrowserTestFixture
-  void SetUpInProcessBrowserTestFixture() override {
-    subscription_ =
-        BrowserContextDependencyManager::GetInstance()
-            ->RegisterCreateServicesCallbackForTesting(base::BindRepeating(
-                &FlocEligibilityBrowserTest::OnWillCreateBrowserContextServices,
-                base::Unretained(this)));
-  }
-
-  std::string InvokeInterestCohortJsApi(
-      const content::ToRenderFrameHost& adapter) {
-    return EvalJs(adapter, R"(
-      if (!(document.interestCohort instanceof Function)) {
-        'not a function';
-      } else {
-        document.interestCohort()
-        .then(floc => JSON.stringify(floc, Object.keys(floc).sort()))
-        .catch(error => 'rejected');
-      }
-    )")
-        .ExtractString();
-  }
-
-  // Returns absl::nullopt if there's no matching result in the history query.
-  // Otherwise, the returned absl::optional contains a bit representing whether
-  // the entry is eligible in floc computation.
-  absl::optional<bool> QueryFlocEligibleForURL(const GURL& url) {
-    absl::optional<bool> query_result;
-
-    history::QueryOptions options;
-    options.duplicate_policy = history::QueryOptions::KEEP_ALL_DUPLICATES;
-
-    base::RunLoop run_loop;
-    base::CancelableTaskTracker tracker;
-
-    history_service()->QueryHistory(
-        std::u16string(), options,
-        base::BindLambdaForTesting([&](history::QueryResults results) {
-          size_t num_matches = 0;
-          const size_t* match_index = results.MatchesForURL(url, &num_matches);
-          if (!num_matches) {
-            run_loop.Quit();
-            return;
-          }
-
-          ASSERT_EQ(1u, num_matches);
-
-          query_result =
-              results[*match_index].content_annotations().annotation_flags &
-              history::VisitContentAnnotationFlag::kFlocEligibleRelaxed;
-          run_loop.Quit();
-        }),
-        &tracker);
-
-    run_loop.Run();
-
-    return query_result;
-  }
-
-  void DeleteAllHistory() {
-    base::RunLoop run_loop;
-    base::CancelableTaskTracker tracker;
-    HistoryServiceFactory::GetForProfile(browser()->profile(),
-                                         ServiceAccessType::EXPLICIT_ACCESS)
-        ->ExpireHistoryBetween(
-            /*restrict_urls=*/{}, /*begin_time=*/base::Time(),
-            base::Time::Max(),
-            /*user_initiated=*/true,
-            base::BindLambdaForTesting([&]() { run_loop.Quit(); }), &tracker);
-    run_loop.Run();
-  }
-
-  content::WebContents* web_contents() {
-    return browser()->tab_strip_model()->GetActiveWebContents();
-  }
-
-  history::HistoryService* history_service() {
-    return HistoryServiceFactory::GetForProfile(
-        browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS);
-  }
-
-  void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
-    federated_learning::FlocIdProviderFactory::GetInstance()->SetTestingFactory(
-        context, base::BindRepeating(
-                     &FlocEligibilityBrowserTest::CreateFixedFlocIdProvider,
-                     base::Unretained(this)));
-  }
-
-  std::unique_ptr<KeyedService> CreateFixedFlocIdProvider(
-      content::BrowserContext* context) {
-    return std::make_unique<FixedFlocIdProvider>();
-  }
-
-  void NavigateAndWaitForResourcesCompeletion(const GURL& url,
-                                              int expected_complete_resources) {
-    auto waiter =
-        std::make_unique<page_load_metrics::PageLoadMetricsTestWaiter>(
-            web_contents());
-
-    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
-
-    waiter->AddMinimumCompleteResourcesExpectation(expected_complete_resources);
-    waiter->Wait();
-  }
-
- protected:
-  base::test::ScopedFeatureList scoped_feature_list_;
-  net::EmbeddedTestServer https_server_{
-      net::test_server::EmbeddedTestServer::TYPE_HTTPS};
-  base::CallbackListSubscription subscription_;
-};
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       NotEligibleForHistoryByDefault) {
-  net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
-
-  GURL main_page_url = https_server_.GetURL(
-      "a.test", "/federated_learning/page_with_script_and_iframe.html");
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  // Expect that the navigation history is not eligible for floc computation.
-  absl::optional<bool> query_floc_eligible =
-      QueryFlocEligibleForURL(main_page_url);
-  EXPECT_TRUE(query_floc_eligible);
-  EXPECT_FALSE(query_floc_eligible.value());
-}
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       NotEligibleForHistoryAfterAdResource) {
-  net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
-
-  SetRulesetWithRules(
-      {subresource_filter::testing::CreateSuffixRule("maybe_ad_script.js")});
-
-  GURL main_page_url = https_server_.GetURL(
-      "a.test", "/federated_learning/page_with_script_and_iframe.html");
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  // Expect that the navigation history is not eligible for floc computation.
-  absl::optional<bool> query_floc_eligible =
-      QueryFlocEligibleForURL(main_page_url);
-  EXPECT_TRUE(query_floc_eligible);
-  EXPECT_FALSE(query_floc_eligible.value());
-}
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       EligibleForHistoryAfterApiCall) {
-  net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
-
-  GURL main_page_url = https_server_.GetURL(
-      "a.test", "/federated_learning/page_with_script_and_iframe.html");
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  // Expect that the navigation history is eligible for floc computation after
-  // an API call.
-  EXPECT_EQ("{\"id\":\"12345\",\"version\":\"chrome.6.7.8.9\"}",
-            InvokeInterestCohortJsApi(web_contents()));
-
-  absl::optional<bool> query_floc_eligible =
-      QueryFlocEligibleForURL(main_page_url);
-  EXPECT_TRUE(query_floc_eligible);
-  EXPECT_TRUE(query_floc_eligible.value());
-}
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       NotEligibleForHistoryDueToPermissionsPolicyLegacy) {
-  net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
-
-  GURL main_page_url = https_server_.GetURL(
-      "a.test",
-      "/federated_learning/"
-      "permissions_policy_interest_cohort_none_legacy.html");
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  InvokeInterestCohortJsApi(web_contents());
-
-  // Expect that the navigation history is not eligible for floc computation as
-  // the permissions policy disallows it.
-  absl::optional<bool> query_floc_eligible =
-      QueryFlocEligibleForURL(main_page_url);
-  EXPECT_TRUE(query_floc_eligible);
-  EXPECT_FALSE(query_floc_eligible.value());
-}
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       NotEligibleForHistoryDueToPermissionsPolicy) {
-  net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
-
-  GURL main_page_url = https_server_.GetURL(
-      "a.test",
-      "/federated_learning/permissions_policy_interest_cohort_none.html");
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  InvokeInterestCohortJsApi(web_contents());
-
-  // Expect that the navigation history is not eligible for floc computation as
-  // the permissions policy disallows it.
-  absl::optional<bool> query_floc_eligible =
-      QueryFlocEligibleForURL(main_page_url);
-  EXPECT_TRUE(query_floc_eligible);
-  EXPECT_FALSE(query_floc_eligible.value());
-}
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       NotEligibleForHistoryDueToPrivateIP) {
-  GURL main_page_url = https_server_.GetURL(
-      "a.test", "/federated_learning/page_with_script_and_iframe.html");
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  InvokeInterestCohortJsApi(web_contents());
-
-  // Expect that the navigation history is not eligible for floc computation as
-  // the IP was not publicly routable.
-  absl::optional<bool> query_floc_eligible =
-      QueryFlocEligibleForURL(main_page_url);
-  EXPECT_TRUE(query_floc_eligible);
-  EXPECT_FALSE(query_floc_eligible.value());
-}
-
-// The history query result doesn't contain any subframe navigation entries
-// (auto & manual).
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       NotEligibleForHistorySubframeCommit) {
-  net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
-
-  GURL main_page_url(https_server_.GetURL(
-      "a.test", "/federated_learning/page_with_script_and_iframe.html"));
-  GURL auto_subframe_url(https_server_.GetURL("a.test", "/title1.html"));
-
-  // Navigate to a page that contains an iframe ("title1.html").
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  // The history query result doesn't contain auto subframe navigation entry.
-  EXPECT_FALSE(QueryFlocEligibleForURL(auto_subframe_url));
-
-  // Trigger an user-initiated navigation on the iframe, so that it will show up
-  // in history.
-  GURL manual_subframe_url(https_server_.GetURL("a.test", "/title2.html"));
-  content::NavigateIframeToURL(web_contents(),
-                               /*iframe_id=*/"test", manual_subframe_url);
-
-  EXPECT_EQ("{\"id\":\"12345\",\"version\":\"chrome.6.7.8.9\"}",
-            InvokeInterestCohortJsApi(web_contents()));
-  EXPECT_EQ("{\"id\":\"12345\",\"version\":\"chrome.6.7.8.9\"}",
-            InvokeInterestCohortJsApi(
-                content::ChildFrameAt(web_contents()->GetMainFrame(), 0)));
-
-  // The history query result doesn't contain manual subframe navigation entry
-  // either.
-  EXPECT_FALSE(QueryFlocEligibleForURL(manual_subframe_url));
-}
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       SettingFlocAllowedNoopOnDeletedHistory) {
-  net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
-
-  GURL main_page_url(https_server_.GetURL(
-      "a.test", "/federated_learning/page_with_script_and_iframe.html"));
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  EXPECT_TRUE(QueryFlocEligibleForURL(main_page_url));
-
-  DeleteAllHistory();
-
-  // Expect that attempting to set the "floc allowed" bit will be a no-op if the
-  // page visit doesn't exist.
-  EXPECT_EQ("{\"id\":\"12345\",\"version\":\"chrome.6.7.8.9\"}",
-            InvokeInterestCohortJsApi(web_contents()));
-  EXPECT_FALSE(QueryFlocEligibleForURL(main_page_url));
-}
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest, ApiAllowedByDefault) {
-  GURL main_page_url(https_server_.GetURL(
-      "a.test", "/federated_learning/page_with_script_and_iframe.html"));
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  // Navigate the iframe to a cross-origin site.
-  GURL subframe_url(https_server_.GetURL("b.test", "/title1.html"));
-  content::NavigateIframeToURL(web_contents(),
-                               /*iframe_id=*/"test", subframe_url);
-
-  content::RenderFrameHost* child =
-      content::ChildFrameAt(web_contents()->GetMainFrame(), 0);
-
-  // Expect that both main frame and subframe are allowed to access floc.
-  EXPECT_EQ("{\"id\":\"12345\",\"version\":\"chrome.6.7.8.9\"}",
-            InvokeInterestCohortJsApi(web_contents()));
-  EXPECT_EQ("{\"id\":\"12345\",\"version\":\"chrome.6.7.8.9\"}",
-            InvokeInterestCohortJsApi(child));
-}
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       ApiNotAllowedDueToInsecureContext) {
-  GURL main_page_url(embedded_test_server()->GetURL(
-      "a.test", "/federated_learning/page_with_script_and_iframe.html"));
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  // Navigate the iframe to a https site.
-  GURL subframe_url(https_server_.GetURL("b.test", "/title1.html"));
-  content::NavigateIframeToURL(web_contents(),
-                               /*iframe_id=*/"test", subframe_url);
-
-  content::RenderFrameHost* child =
-      content::ChildFrameAt(web_contents()->GetMainFrame(), 0);
-
-  // Expect that both main frame and subframe are not allowed to access floc.
-  EXPECT_EQ("not a function", InvokeInterestCohortJsApi(web_contents()));
-  EXPECT_EQ("not a function", InvokeInterestCohortJsApi(child));
-}
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       ApiNotAllowedDueToPermissionsPolicy) {
-  GURL main_page_url(https_server_.GetURL(
-      "a.test",
-      "/federated_learning/"
-      "permissions_policy_interest_cohort_none_legacy.html"));
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  // Navigate the iframe to a cross-origin site.
-  GURL subframe_url(https_server_.GetURL("b.test", "/title1.html"));
-  content::NavigateIframeToURL(web_contents(),
-                               /*iframe_id=*/"test", subframe_url);
-
-  content::RenderFrameHost* child =
-      content::ChildFrameAt(web_contents()->GetMainFrame(), 0);
-
-  // Expect that both main frame and subframe are not allowed to access floc.
-  EXPECT_EQ("rejected", InvokeInterestCohortJsApi(web_contents()));
-  EXPECT_EQ("rejected", InvokeInterestCohortJsApi(child));
-}
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       ApiNotAllowedInSubframeDueToPermissionsPolicySelf) {
-  GURL main_page_url(https_server_.GetURL(
-      "a.test",
-      "/federated_learning/"
-      "permissions_policy_interest_cohort_self_legacy.html"));
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  // Navigate the iframe to a cross-origin site.
-  GURL subframe_url(https_server_.GetURL("b.test", "/title1.html"));
-  content::NavigateIframeToURL(web_contents(),
-                               /*iframe_id=*/"test", subframe_url);
-
-  content::RenderFrameHost* child =
-      content::ChildFrameAt(web_contents()->GetMainFrame(), 0);
-
-  // Expect that only the main frame can access floc.
-  EXPECT_EQ("{\"id\":\"12345\",\"version\":\"chrome.6.7.8.9\"}",
-            InvokeInterestCohortJsApi(web_contents()));
-  EXPECT_EQ("rejected", InvokeInterestCohortJsApi(child));
-}
-
-IN_PROC_BROWSER_TEST_F(FlocEligibilityBrowserTest,
-                       ApiNotAllowedInDetachedDocument) {
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(),
-      https_server_.GetURL("a.test",
-                           "/federated_learning/"
-                           "interest_cohort_api_in_detached_document.html")));
-
-  EXPECT_EQ(
-      "[error from subframe document] InvalidAccessError: Failed to execute "
-      "'interestCohort' on 'Document': A browsing context is required when "
-      "calling document.interestCohort.",
-      EvalJs(web_contents()->GetMainFrame(), R"(
-        document.body.textContent
-      )")
-          .ExtractString());
-}
-
-class FlocEligibilityBrowserTestBypassIPIsPubliclyRoutableCheck
-    : public FlocEligibilityBrowserTest {
- public:
-  FlocEligibilityBrowserTestBypassIPIsPubliclyRoutableCheck() {
-    scoped_feature_list_.Reset();
-    scoped_feature_list_.InitWithFeatures(
-        /*enabled_features=*/{blink::features::kInterestCohortFeaturePolicy,
-                              federated_learning::
-                                  kFlocBypassIPIsPubliclyRoutableCheck},
-        /*disabled_features=*/{
-            federated_learning::
-                kFlocPagesWithAdResourcesDefaultIncludedInFlocComputation});
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(
-    FlocEligibilityBrowserTestBypassIPIsPubliclyRoutableCheck,
-    EligibleForHistoryOnPrivateIP) {
-  GURL main_page_url = https_server_.GetURL(
-      "a.test", "/federated_learning/page_with_script_and_iframe.html");
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  InvokeInterestCohortJsApi(web_contents());
-
-  // Expect that the navigation history is eligible for floc computation.
-  absl::optional<bool> query_floc_eligible =
-      QueryFlocEligibleForURL(main_page_url);
-  EXPECT_TRUE(query_floc_eligible);
-  EXPECT_TRUE(query_floc_eligible.value());
-}
-
-class FlocEligibilityBrowserTestPagesWithAdResourcesDefaultIncluded
-    : public FlocEligibilityBrowserTest {
- public:
-  FlocEligibilityBrowserTestPagesWithAdResourcesDefaultIncluded() {
-    scoped_feature_list_.Reset();
-    scoped_feature_list_.InitWithFeatures(
-        {blink::features::kInterestCohortFeaturePolicy,
-         federated_learning::
-             kFlocPagesWithAdResourcesDefaultIncludedInFlocComputation},
-        {});
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(
-    FlocEligibilityBrowserTestPagesWithAdResourcesDefaultIncluded,
-    EligibleForHistoryAfterAdResource) {
-  net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
-
-  SetRulesetWithRules(
-      {subresource_filter::testing::CreateSuffixRule("maybe_ad_script.js")});
-
-  GURL main_page_url = https_server_.GetURL(
-      "a.test", "/federated_learning/page_with_script_and_iframe.html");
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  // Expect that the navigation history is eligible for floc computation as the
-  // page contains an ad resource.
-  absl::optional<bool> query_floc_eligible =
-      QueryFlocEligibleForURL(main_page_url);
-  EXPECT_TRUE(query_floc_eligible);
-  EXPECT_TRUE(query_floc_eligible.value());
-}
-
-IN_PROC_BROWSER_TEST_F(
-    FlocEligibilityBrowserTestPagesWithAdResourcesDefaultIncluded,
-    NotEligibleForHistoryAfterNonAdResource) {
-  net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
-
-  GURL main_page_url = https_server_.GetURL(
-      "a.test", "/federated_learning/page_with_script_and_iframe.html");
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  // Expect that the navigation history is not eligible for floc computation.
-  absl::optional<bool> query_floc_eligible =
-      QueryFlocEligibleForURL(main_page_url);
-  EXPECT_TRUE(query_floc_eligible);
-  EXPECT_FALSE(query_floc_eligible.value());
-}
-
-class FlocEligibilityBrowserTestChromePermissionsPolicyDisabled
-    : public FlocEligibilityBrowserTest {
- public:
-  FlocEligibilityBrowserTestChromePermissionsPolicyDisabled() {
-    scoped_feature_list_.Reset();
-    scoped_feature_list_.InitAndDisableFeature(
-        blink::features::kInterestCohortFeaturePolicy);
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(
-    FlocEligibilityBrowserTestChromePermissionsPolicyDisabled,
-    PermissionsPolicyFeatureNotAvailable) {
-  GURL main_page_url(https_server_.GetURL("a.test", "/title1.html"));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_page_url));
-
-  EXPECT_FALSE(EvalJs(web_contents(), R"(
-      document.featurePolicy.features().includes("interest-cohort")
-    )")
-                   .ExtractBool());
-}
-
-// Try configuring the permissions policy anyway. Check that the API succeeds
-// and the history is eligible for floc computation.
-IN_PROC_BROWSER_TEST_F(
-    FlocEligibilityBrowserTestChromePermissionsPolicyDisabled,
-    PermissionsPolicyFeatureNotEffective) {
-  net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
-
-  GURL main_page_url(https_server_.GetURL(
-      "a.test",
-      "/federated_learning/"
-      "permissions_policy_interest_cohort_none_legacy.html"));
-
-  // Three resources in the main frame and one favicon.
-  NavigateAndWaitForResourcesCompeletion(main_page_url, 4);
-
-  // Navigate the iframe to a cross-origin site.
-  GURL subframe_url(https_server_.GetURL("b.test", "/title1.html"));
-  content::NavigateIframeToURL(web_contents(),
-                               /*iframe_id=*/"test", subframe_url);
-
-  content::RenderFrameHost* child =
-      content::ChildFrameAt(web_contents()->GetMainFrame(), 0);
-
-  // Expect that both main frame and subframe are allowed to access floc.
-  EXPECT_EQ("{\"id\":\"12345\",\"version\":\"chrome.6.7.8.9\"}",
-            InvokeInterestCohortJsApi(web_contents()));
-  EXPECT_EQ("{\"id\":\"12345\",\"version\":\"chrome.6.7.8.9\"}",
-            InvokeInterestCohortJsApi(child));
-
-  // Expect that the navigation history is eligible for floc computation.
-  absl::optional<bool> query_floc_eligible =
-      QueryFlocEligibleForURL(main_page_url);
-  EXPECT_TRUE(query_floc_eligible);
-  EXPECT_TRUE(query_floc_eligible.value());
-}
diff --git a/chrome/browser/federated_learning/floc_eligibility_observer.cc b/chrome/browser/federated_learning/floc_eligibility_observer.cc
deleted file mode 100644
index 47434e2..0000000
--- a/chrome/browser/federated_learning/floc_eligibility_observer.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2021 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/federated_learning/floc_eligibility_observer.h"
-
-#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "components/federated_learning/features/features.h"
-#include "components/history/content/browser/history_context_helper.h"
-#include "components/history/core/browser/history_service.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/web_contents.h"
-#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom.h"
-
-namespace federated_learning {
-
-namespace {
-
-history::HistoryService* GetHistoryService(content::WebContents* web_contents) {
-  DCHECK(web_contents);
-
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents->GetBrowserContext());
-  if (profile->IsOffTheRecord())
-    return nullptr;
-
-  return HistoryServiceFactory::GetForProfile(
-      profile, ServiceAccessType::IMPLICIT_ACCESS);
-}
-
-}  // namespace
-
-FlocEligibilityObserver::~FlocEligibilityObserver() = default;
-
-page_load_metrics::PageLoadMetricsObserver::ObservePolicy
-FlocEligibilityObserver::OnCommit(
-    content::NavigationHandle* navigation_handle) {
-  // At this point the add-page-to-history decision should have been made,
-  // because history is added in HistoryTabHelper::DidFinishNavigation, and this
-  // OnEligibleCommit method is invoked in the same broadcasting family through
-  // MetricsWebContentsObserver::DidFinishNavigation.
-
-  // TODO(yaoxia): Perhaps we want an explicit signal for "the page was added
-  // to history or was ineligible". This way we don't need to count on the above
-  // relation, and can also stop observing if the history was not added.
-
-  // If the IP was not publicly routable, the navigation history is not eligible
-  // for floc. We can stop observing now.
-  if (!navigation_handle->GetSocketAddress().address().IsPubliclyRoutable() &&
-      !base::FeatureList::IsEnabled(kFlocBypassIPIsPubliclyRoutableCheck)) {
-    return ObservePolicy::STOP_OBSERVING;
-  }
-
-  // If the interest-cohort permissions policy in the main document disallows
-  // the floc inclusion, the navigation history is not eligible for floc. We can
-  // stop observing now.
-  if (!navigation_handle->GetRenderFrameHost()->IsFeatureEnabled(
-          blink::mojom::PermissionsPolicyFeature::kInterestCohort)) {
-    return ObservePolicy::STOP_OBSERVING;
-  }
-
-  DCHECK(!eligible_commit_);
-  eligible_commit_ = true;
-
-  return ObservePolicy::CONTINUE_OBSERVING;
-}
-
-void FlocEligibilityObserver::OnAdResource() {
-  if (!base::FeatureList::IsEnabled(
-          kFlocPagesWithAdResourcesDefaultIncludedInFlocComputation)) {
-    return;
-  }
-
-  OnOptInSignalObserved();
-}
-
-void FlocEligibilityObserver::OnInterestCohortApiUsed() {
-  OnOptInSignalObserved();
-}
-
-FlocEligibilityObserver::FlocEligibilityObserver(content::RenderFrameHost* rfh)
-    : content::DocumentUserData<FlocEligibilityObserver>(rfh),
-      web_contents_(content::WebContents::FromRenderFrameHost(rfh)) {}
-
-void FlocEligibilityObserver::OnOptInSignalObserved() {
-  if (!eligible_commit_ || observed_opt_in_signal_)
-    return;
-
-  if (history::HistoryService* hs = GetHistoryService(web_contents_)) {
-    hs->SetFlocAllowed(
-        history::ContextIDForWebContents(web_contents_),
-        web_contents_->GetController().GetLastCommittedEntry()->GetUniqueID(),
-        web_contents_->GetLastCommittedURL());
-  }
-
-  observed_opt_in_signal_ = true;
-}
-
-DOCUMENT_USER_DATA_KEY_IMPL(FlocEligibilityObserver);
-
-}  // namespace federated_learning
diff --git a/chrome/browser/federated_learning/floc_eligibility_observer.h b/chrome/browser/federated_learning/floc_eligibility_observer.h
deleted file mode 100644
index f1b3a4e..0000000
--- a/chrome/browser/federated_learning/floc_eligibility_observer.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2021 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_FEDERATED_LEARNING_FLOC_ELIGIBILITY_OBSERVER_H_
-#define CHROME_BROWSER_FEDERATED_LEARNING_FLOC_ELIGIBILITY_OBSERVER_H_
-
-#include "base/memory/raw_ptr.h"
-#include "components/page_load_metrics/browser/page_load_metrics_observer.h"
-#include "content/public/browser/document_user_data.h"
-
-namespace content {
-class WebContents;
-}  // namespace content
-
-namespace federated_learning {
-
-// This observer monitors page-level (i.e. main document) signals to determine
-// whether the navigation's associated history entry is eligible for floc
-// computation. The history entry is eligible for floc computation if all of the
-// following conditions hold:
-// 1) the IP of the navigation was publicly routable.
-// 2) the interest-cohort permissions policy in the main document allows the
-// floc history inclusion.
-// 3) either the page has an ad resource, or the document.interestCohort API is
-// used in the page.
-//
-// When the page is considered eligible for floc computation, a corresponding
-// HistoryService API will be called to persistently set the eligibility bit.
-class FlocEligibilityObserver
-    : public content::DocumentUserData<FlocEligibilityObserver> {
- public:
-  using ObservePolicy =
-      page_load_metrics::PageLoadMetricsObserver::ObservePolicy;
-
-  ~FlocEligibilityObserver() override;
-
-  // Called when the navigation has committed. Returns whether it should
-  // continue observing floc related signals.
-  ObservePolicy OnCommit(content::NavigationHandle* navigation_handle);
-
-  // Called when an ad resource is seen in the page.
-  void OnAdResource();
-
-  // Called when the document.interestCohort API is used in the page.
-  void OnInterestCohortApiUsed();
-
- private:
-  explicit FlocEligibilityObserver(content::RenderFrameHost* rfh);
-
-  friend class content::DocumentUserData<FlocEligibilityObserver>;
-
-  void OnOptInSignalObserved();
-
-  raw_ptr<content::WebContents> web_contents_;
-
-  // |eligible_commit_| means all the commit time prerequisites are met
-  // (i.e. IP was publicly routable AND permissions policy is "allow"). It can
-  // only be set to true at commit time. When it's set, it also implies that the
-  // add-page-to-history decision has been made, i.e. either the page has been
-  // added to history, or has been skipped.
-  bool eligible_commit_ = false;
-
-  bool observed_opt_in_signal_ = false;
-
-  DOCUMENT_USER_DATA_KEY_DECL();
-};
-
-}  // namespace federated_learning
-
-#endif  // CHROME_BROWSER_FEDERATED_LEARNING_FLOC_ELIGIBILITY_OBSERVER_H_
diff --git a/chrome/browser/federated_learning/floc_eligibility_unittest.cc b/chrome/browser/federated_learning/floc_eligibility_unittest.cc
deleted file mode 100644
index b3c9399..0000000
--- a/chrome/browser/federated_learning/floc_eligibility_unittest.cc
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright 2021 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/memory/raw_ptr.h"
-#include "base/test/bind.h"
-#include "chrome/browser/federated_learning/floc_eligibility_observer.h"
-#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/page_load_metrics/observers/ad_metrics/floc_page_load_metrics_observer.h"
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "components/federated_learning/features/features.h"
-#include "components/federated_learning/floc_sorting_lsh_clusters_service.h"
-#include "components/history/content/browser/history_context_helper.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.h"
-#include "components/page_load_metrics/browser/page_load_tracker.h"
-#include "components/page_load_metrics/common/page_load_metrics.mojom.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/test/navigation_simulator.h"
-#include "content/public/test/web_contents_tester.h"
-
-namespace federated_learning {
-
-class FlocEligibilityUnitTest : public ChromeRenderViewHostTestHarness {
- public:
-  FlocEligibilityUnitTest() = default;
-  ~FlocEligibilityUnitTest() override = default;
-
-  void SetUp() override {
-    ChromeRenderViewHostTestHarness::SetUp();
-
-    TestingBrowserProcess::GetGlobal()->SetFlocSortingLshClustersService(
-        std::make_unique<federated_learning::FlocSortingLshClustersService>());
-
-    InitWebContents();
-
-    tester_ =
-        std::make_unique<page_load_metrics::PageLoadMetricsObserverTester>(
-            GetWebContents(), this,
-            base::BindRepeating(&FlocEligibilityUnitTest::RegisterObservers,
-                                base::Unretained(this)));
-  }
-
-  TestingProfile::TestingFactories GetTestingFactories() const override {
-    return {{HistoryServiceFactory::GetInstance(),
-             HistoryServiceFactory::GetDefaultFactory()}};
-  }
-
-  // Can be overridden in child class to initialize an incognito web_contents.
-  virtual void InitWebContents() {}
-
-  virtual content::WebContents* GetWebContents() { return web_contents(); }
-
-  history::HistoryService* history_service() {
-    return HistoryServiceFactory::GetForProfile(
-        profile(), ServiceAccessType::EXPLICIT_ACCESS);
-  }
-
-  bool IsUrlVisitEligibleToComputeFloc(const GURL& url) {
-    bool eligible = false;
-
-    history::QueryOptions options;
-    options.duplicate_policy = history::QueryOptions::KEEP_ALL_DUPLICATES;
-
-    base::RunLoop run_loop;
-    base::CancelableTaskTracker tracker;
-
-    history_service()->QueryHistory(
-        std::u16string(), options,
-        base::BindLambdaForTesting([&](history::QueryResults results) {
-          ASSERT_EQ(1u, results.size());
-          eligible = results[0].content_annotations().annotation_flags &
-                     history::VisitContentAnnotationFlag::kFlocEligibleRelaxed;
-          run_loop.Quit();
-        }),
-        &tracker);
-
-    run_loop.Run();
-
-    return eligible;
-  }
-
-  void SimulateResourceDataUseUpdate(bool is_ad_resource) {
-    page_load_metrics::mojom::ResourceDataUpdatePtr resource =
-        page_load_metrics::mojom::ResourceDataUpdate::New();
-    resource->reported_as_ad_resource = is_ad_resource;
-    resource->received_data_length = 1;
-
-    std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr> resources;
-    resources.push_back(std::move(resource));
-
-    tester_->SimulateResourceDataUseUpdate(resources,
-                                           GetWebContents()->GetMainFrame());
-  }
-
-  void NavigateToPage(const GURL& url,
-                      bool publicly_routable,
-                      bool floc_permissions_policy_enabled) {
-    auto simulator = content::NavigationSimulator::CreateBrowserInitiated(
-        url, GetWebContents());
-    simulator->SetTransition(ui::PageTransition::PAGE_TRANSITION_TYPED);
-
-    if (!publicly_routable) {
-      net::IPAddress address;
-      EXPECT_TRUE(address.AssignFromIPLiteral("0.0.0.0"));
-      simulator->SetSocketAddress(net::IPEndPoint(address, /*port=*/0));
-    }
-
-    if (!floc_permissions_policy_enabled) {
-      simulator->SetPermissionsPolicyHeader(
-          {{blink::mojom::PermissionsPolicyFeature::kInterestCohort,
-            /*values=*/{}, /*matches_all_origins=*/false,
-            /*matches_opaque_src=*/false}});
-    }
-
-    simulator->Commit();
-
-    history_service()->AddPage(
-        url, base::Time::Now(),
-        history::ContextIDForWebContents(GetWebContents()),
-        GetWebContents()
-            ->GetController()
-            .GetLastCommittedEntry()
-            ->GetUniqueID(),
-        /*referrer=*/GURL(),
-        /*redirects=*/{}, ui::PageTransition::PAGE_TRANSITION_TYPED,
-        history::VisitSource::SOURCE_BROWSED,
-        /*did_replace_entry=*/false,
-        /*floc_allowed=*/false);
-  }
-
-  FlocEligibilityObserver* GetFlocEligibilityObserver() {
-    return FlocEligibilityObserver::GetOrCreateForCurrentDocument(
-        GetWebContents()->GetMainFrame());
-  }
-
- private:
-  void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) {
-    auto floc_plm_observer = std::make_unique<FlocPageLoadMetricsObserver>();
-    floc_plm_observer_ = floc_plm_observer.get();
-    tracker->AddObserver(std::move(floc_plm_observer));
-  }
-
-  raw_ptr<FlocPageLoadMetricsObserver> floc_plm_observer_;
-  std::unique_ptr<page_load_metrics::PageLoadMetricsObserverTester> tester_;
-};
-
-TEST_F(FlocEligibilityUnitTest, OnInterestCohortApiUsed) {
-  GURL url("https://foo.com");
-  NavigateToPage(url, /*publicly_routable=*/true,
-                 /*floc_permissions_policy_enabled=*/true);
-
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-
-  GetFlocEligibilityObserver()->OnInterestCohortApiUsed();
-  EXPECT_TRUE(IsUrlVisitEligibleToComputeFloc(url));
-}
-
-TEST_F(FlocEligibilityUnitTest, OnAdResourceObserved) {
-  GURL url("https://foo.com");
-  NavigateToPage(url, /*publicly_routable=*/true,
-                 /*floc_permissions_policy_enabled=*/true);
-
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-
-  SimulateResourceDataUseUpdate(/*is_ad_resource=*/true);
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-}
-
-TEST_F(FlocEligibilityUnitTest, OnNonAdResourceObserved) {
-  GURL url("https://foo.com");
-  NavigateToPage(url, /*publicly_routable=*/true,
-                 /*floc_permissions_policy_enabled=*/true);
-
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-
-  SimulateResourceDataUseUpdate(/*is_ad_resource=*/false);
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-}
-
-TEST_F(FlocEligibilityUnitTest, StopObservingPrivateIP) {
-  GURL url("https://foo.com");
-  NavigateToPage(url, /*publicly_routable=*/false,
-                 /*floc_permissions_policy_enabled=*/true);
-
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-
-  SimulateResourceDataUseUpdate(/*is_ad_resource=*/true);
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-
-  GetFlocEligibilityObserver()->OnInterestCohortApiUsed();
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-}
-
-TEST_F(FlocEligibilityUnitTest, StopObservingFlocPermissionsPolicyDisabled) {
-  GURL url("https://foo.com");
-  NavigateToPage(url, /*publicly_routable=*/true,
-                 /*floc_permissions_policy_enabled=*/false);
-
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-
-  SimulateResourceDataUseUpdate(/*is_ad_resource=*/true);
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-
-  GetFlocEligibilityObserver()->OnInterestCohortApiUsed();
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-}
-
-class FlocEligibilityUnitTestkBypassIPIsPubliclyRoutableCheck
-    : public FlocEligibilityUnitTest {
- public:
-  FlocEligibilityUnitTestkBypassIPIsPubliclyRoutableCheck() {
-    feature_list_.InitAndEnableFeature(kFlocBypassIPIsPubliclyRoutableCheck);
-  }
-
- protected:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-TEST_F(FlocEligibilityUnitTestkBypassIPIsPubliclyRoutableCheck,
-       ContinueObservingPrivateIP) {
-  GURL url("https://foo.com");
-  NavigateToPage(url, /*publicly_routable=*/false,
-                 /*floc_permissions_policy_enabled=*/true);
-
-  GetFlocEligibilityObserver()->OnInterestCohortApiUsed();
-  EXPECT_TRUE(IsUrlVisitEligibleToComputeFloc(url));
-}
-
-class FlocEligibilityUnitTestPagesWithAdResourcesDefaultIncluded
-    : public FlocEligibilityUnitTest {
- public:
-  FlocEligibilityUnitTestPagesWithAdResourcesDefaultIncluded() {
-    feature_list_.InitAndEnableFeature(
-        kFlocPagesWithAdResourcesDefaultIncludedInFlocComputation);
-  }
-
- protected:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-TEST_F(FlocEligibilityUnitTestPagesWithAdResourcesDefaultIncluded,
-       OnAdResourceObserved) {
-  GURL url("https://foo.com");
-  NavigateToPage(url, /*publicly_routable=*/true,
-                 /*floc_permissions_policy_enabled=*/true);
-
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-
-  SimulateResourceDataUseUpdate(/*is_ad_resource=*/true);
-  EXPECT_TRUE(IsUrlVisitEligibleToComputeFloc(url));
-}
-
-TEST_F(FlocEligibilityUnitTestPagesWithAdResourcesDefaultIncluded,
-       OnNonAdResourceObserved) {
-  GURL url("https://foo.com");
-  NavigateToPage(url, /*publicly_routable=*/true,
-                 /*floc_permissions_policy_enabled=*/true);
-
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-
-  SimulateResourceDataUseUpdate(/*is_ad_resource=*/false);
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-}
-
-class FlocEligibilityIncognitoUnitTest : public FlocEligibilityUnitTest {
- public:
-  FlocEligibilityIncognitoUnitTest() = default;
-  ~FlocEligibilityIncognitoUnitTest() override = default;
-
-  void InitWebContents() override {
-    TestingProfile::Builder().BuildIncognito(profile());
-    incognito_web_contents_ = content::WebContentsTester::CreateTestWebContents(
-        profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true),
-        content::SiteInstance::Create(
-            profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true)));
-  }
-
-  content::WebContents* GetWebContents() override {
-    return incognito_web_contents_.get();
-  }
-
-  void TearDown() override {
-    incognito_web_contents_.reset();
-    FlocEligibilityUnitTest::TearDown();
-  }
-
- private:
-  std::unique_ptr<content::WebContents> incognito_web_contents_;
-};
-
-TEST_F(FlocEligibilityIncognitoUnitTest, SkipSettingFlocAllowedInIncognito) {
-  GURL url("https://foo.com");
-  NavigateToPage(url, /*publicly_routable=*/true,
-                 /*floc_permissions_policy_enabled=*/true);
-
-  SimulateResourceDataUseUpdate(/*is_ad_resource=*/true);
-
-  EXPECT_FALSE(IsUrlVisitEligibleToComputeFloc(url));
-}
-
-}  // namespace federated_learning
diff --git a/chrome/browser/federated_learning/floc_event_logger.cc b/chrome/browser/federated_learning/floc_event_logger.cc
deleted file mode 100644
index 702066b..0000000
--- a/chrome/browser/federated_learning/floc_event_logger.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2021 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/federated_learning/floc_event_logger.h"
-
-#include "base/threading/thread_task_runner_handle.h"
-#include "chrome/browser/federated_learning/floc_remote_permission_service.h"
-#include "components/federated_learning/features/features.h"
-#include "components/sync/driver/sync_service.h"
-#include "components/sync_user_events/user_event_service.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace federated_learning {
-
-namespace {
-
-const base::TimeDelta kSecondAttemptDelay = base::Seconds(10);
-
-}  // namespace
-
-FlocEventLogger::FlocEventLogger(
-    syncer::SyncService* sync_service,
-    FlocRemotePermissionService* floc_remote_permission_service,
-    syncer::UserEventService* user_event_service)
-    : sync_service_(sync_service),
-      floc_remote_permission_service_(floc_remote_permission_service),
-      user_event_service_(user_event_service) {}
-
-FlocEventLogger::~FlocEventLogger() = default;
-
-void FlocEventLogger::LogFlocComputedEvent(Event event) {
-  if (!base::FeatureList::IsEnabled(kFlocIdComputedEventLogging))
-    return;
-
-  auto can_log_event_decided_callback =
-      base::BindOnce(&FlocEventLogger::OnCanLogEventDecided,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(event));
-
-  if (!IsSyncHistoryEnabled()) {
-    // Give it a second chance 10 seconds later. This is because the first floc
-    // event logging for a browser session can happen before sync finishes
-    // setting up, and we want to ensure that the event will eventually be
-    // logged if sync is supposed to be enabled.
-    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&FlocEventLogger::CheckCanLogEvent,
-                       weak_ptr_factory_.GetWeakPtr(),
-                       std::move(can_log_event_decided_callback)),
-        kSecondAttemptDelay);
-    return;
-  }
-
-  CheckCanLogEvent(std::move(can_log_event_decided_callback));
-}
-
-void FlocEventLogger::CheckCanLogEvent(CanLogEventCallback callback) {
-  if (!IsSyncHistoryEnabled()) {
-    std::move(callback).Run(false);
-    return;
-  }
-
-  IsSwaaNacAccountEnabled(std::move(callback));
-}
-
-void FlocEventLogger::OnCanLogEventDecided(Event event, bool can_log_event) {
-  if (!can_log_event)
-    return;
-
-  auto specifics = std::make_unique<sync_pb::UserEventSpecifics>();
-  specifics->set_event_time_usec(
-      event.time.ToDeltaSinceWindowsEpoch().InMicroseconds());
-
-  sync_pb::UserEventSpecifics_FlocIdComputed* const floc_id_computed_event =
-      specifics->mutable_floc_id_computed_event();
-
-  if (event.sim_hash_computed)
-    floc_id_computed_event->set_floc_id(event.sim_hash);
-
-  user_event_service_->RecordUserEvent(std::move(specifics));
-}
-
-bool FlocEventLogger::IsSyncHistoryEnabled() const {
-  return sync_service_->IsSyncFeatureActive() &&
-         sync_service_->GetActiveDataTypes().Has(
-             syncer::HISTORY_DELETE_DIRECTIVES);
-}
-
-void FlocEventLogger::IsSwaaNacAccountEnabled(CanLogEventCallback callback) {
-  net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
-      net::DefinePartialNetworkTrafficAnnotation(
-          "floc_event_logger", "floc_remote_permission_service",
-          R"(
-        semantics {
-          description:
-            "Queries Google to find out if user has enabled 'web and app "
-            "activity' and 'ad personalization', and if the account type is "
-            "NOT a child account. Those permission bits will be checked before "
-            "logging the FLoC (Federated Learning of Cohorts) ID - an "
-            "anonymous similarity hash value of user’s navigation history. "
-            "This ensures that the logged ID is derived from data that Google "
-            "already owns and the user has explicitly granted permission on "
-            "what they will be used for."
-          trigger:
-            "This request is sent after each time the FLoC (Federated Learning "
-            "of Cohorts) ID is computed. A FLoC ID is an anonymous similarity "
-            "hash value of user’s navigation history. It'll be computed at the "
-            "start of each browser profile session and will be refreshed "
-            "regularly."
-          data:
-            "Google credentials if user is signed in."
-        }
-        policy {
-            setting:
-              "This feature can be disabled by disabling sync or third-party "
-              "cookies."
-        })");
-
-  floc_remote_permission_service_->QueryFlocPermission(
-      std::move(callback), partial_traffic_annotation);
-}
-
-}  // namespace federated_learning
diff --git a/chrome/browser/federated_learning/floc_event_logger.h b/chrome/browser/federated_learning/floc_event_logger.h
deleted file mode 100644
index afb6d57..0000000
--- a/chrome/browser/federated_learning/floc_event_logger.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2021 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_FEDERATED_LEARNING_FLOC_EVENT_LOGGER_H_
-#define CHROME_BROWSER_FEDERATED_LEARNING_FLOC_EVENT_LOGGER_H_
-
-#include <stddef.h>
-
-#include "base/callback_forward.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/raw_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "components/sync/driver/sync_service_observer.h"
-
-namespace syncer {
-class UserEventService;
-class SyncService;
-}  // namespace syncer
-
-namespace federated_learning {
-
-class FlocRemotePermissionService;
-
-// Provide an interface to log the FlocIdComputed event after each time floc is
-// computed. For each logging request, a floc is eligible to be logged if the
-// following conditons are met:
-// 1) Sync & sync-history are enabled.
-// 2) Supplemental Web and App Activity is enabled.
-// 3) Supplemental Ad Personalization is enabled.
-// 4) The account type is NOT a child account.
-//
-// Given that the sync service is often ready a few moments after the browser
-// start, but the floc may already have been computed before then, for practical
-// purposes, each request that fails the initial sync-history check will be
-// given a second chance 10 seconds later.
-class FlocEventLogger {
- public:
-  struct Event {
-    bool sim_hash_computed = false;
-    uint64_t sim_hash = 0;
-    base::Time time;
-  };
-
-  using CanLogEventCallback = base::OnceCallback<void(bool)>;
-
-  FlocEventLogger(syncer::SyncService* sync_service,
-                  FlocRemotePermissionService* floc_remote_permission_service,
-                  syncer::UserEventService* user_event_service);
-
-  virtual ~FlocEventLogger();
-
-  // Log a user event. It'll first go though a few permission checks to
-  // determine whether the logging is allowed (see class comments). If
-  // sync-history is not enabled in particular, it will do a second attempt 10
-  // seconds later.
-  virtual void LogFlocComputedEvent(Event event);
-
- private:
-  friend class FlocEventLoggerUnitTest;
-  friend class MockFlocEventLogger;
-
-  void CheckCanLogEvent(CanLogEventCallback callback);
-  void OnCanLogEventDecided(Event event, bool can_log_event);
-
-  bool IsSyncHistoryEnabled() const;
-
-  void IsSwaaNacAccountEnabled(CanLogEventCallback callback);
-
-  // The following raw pointer references are guaranteed to outlive this object.
-  raw_ptr<syncer::SyncService> sync_service_;
-  raw_ptr<FlocRemotePermissionService> floc_remote_permission_service_;
-  raw_ptr<syncer::UserEventService> user_event_service_;
-
-  base::WeakPtrFactory<FlocEventLogger> weak_ptr_factory_{this};
-};
-
-}  // namespace federated_learning
-
-#endif  // CHROME_BROWSER_FEDERATED_LEARNING_FLOC_EVENT_LOGGER_H_
diff --git a/chrome/browser/federated_learning/floc_event_logger_unittest.cc b/chrome/browser/federated_learning/floc_event_logger_unittest.cc
deleted file mode 100644
index 902c385..0000000
--- a/chrome/browser/federated_learning/floc_event_logger_unittest.cc
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_event_logger.h"
-
-#include "base/strings/strcat.h"
-#include "base/test/bind.h"
-#include "build/build_config.h"
-#include "chrome/browser/federated_learning/floc_remote_permission_service.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "components/content_settings/core/common/pref_names.h"
-#include "components/federated_learning/features/features.h"
-#include "components/sync/driver/test_sync_service.h"
-#include "components/sync_user_events/fake_user_event_service.h"
-#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/test_utils.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace federated_learning {
-
-class FakeFlocRemotePermissionService : public FlocRemotePermissionService {
- public:
-  using FlocRemotePermissionService::FlocRemotePermissionService;
-
-  void QueryFlocPermission(QueryFlocPermissionCallback callback,
-                           const net::PartialNetworkTrafficAnnotationTag&
-                               partial_traffic_annotation) override {
-    ++number_of_permission_queries_;
-    std::move(callback).Run(swaa_nac_account_enabled_);
-  }
-
-  size_t number_of_permission_queries() const {
-    return number_of_permission_queries_;
-  }
-
-  void set_swaa_nac_account_enabled(bool enabled) {
-    swaa_nac_account_enabled_ = enabled;
-  }
-
- private:
-  size_t number_of_permission_queries_ = 0;
-  bool swaa_nac_account_enabled_ = true;
-};
-
-class FlocEventLoggerUnitTest : public testing::Test {
- public:
-  FlocEventLoggerUnitTest()
-      : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
-
-  FlocEventLoggerUnitTest(const FlocEventLoggerUnitTest&) = delete;
-  FlocEventLoggerUnitTest& operator=(const FlocEventLoggerUnitTest&) = delete;
-
-  ~FlocEventLoggerUnitTest() override = default;
-
-  void SetUp() override {
-    test_sync_service_ = std::make_unique<syncer::TestSyncService>();
-    test_sync_service_->SetTransportState(
-        syncer::SyncService::TransportState::DISABLED);
-
-    fake_user_event_service_ = std::make_unique<syncer::FakeUserEventService>();
-
-    fake_floc_remote_permission_service_ =
-        std::make_unique<FakeFlocRemotePermissionService>(
-            /*url_loader_factory=*/nullptr);
-
-    floc_event_logger_ = std::make_unique<FlocEventLogger>(
-        test_sync_service_.get(), fake_floc_remote_permission_service_.get(),
-        fake_user_event_service_.get());
-  }
-
-  void DisableSyncHistory() {
-    test_sync_service_->SetTransportState(
-        syncer::SyncService::TransportState::DISABLED);
-    test_sync_service_->FireStateChanged();
-  }
-
-  void EnableSyncHistory() {
-    test_sync_service_->SetTransportState(
-        syncer::SyncService::TransportState::ACTIVE);
-    test_sync_service_->FireStateChanged();
-  }
-
-  void SetRemoteSwaaNacAccountEnabled(bool enabled) {
-    fake_floc_remote_permission_service_->set_swaa_nac_account_enabled(enabled);
-  }
-
-  size_t GetNumberOfRemotePermissionQueries() {
-    return fake_floc_remote_permission_service_->number_of_permission_queries();
-  }
-
-  size_t GetLoggedEventSize() const {
-    return fake_user_event_service_->GetRecordedUserEvents().size();
-  }
-
-  FlocEventLogger::Event GetEventAtIndex(size_t i) {
-    CHECK_LT(i, fake_user_event_service_->GetRecordedUserEvents().size());
-
-    const sync_pb::UserEventSpecifics& specifics =
-        fake_user_event_service_->GetRecordedUserEvents()[i];
-    EXPECT_EQ(sync_pb::UserEventSpecifics::kFlocIdComputedEvent,
-              specifics.event_case());
-    const sync_pb::UserEventSpecifics_FlocIdComputed& e =
-        specifics.floc_id_computed_event();
-
-    return {e.has_floc_id(), e.has_floc_id() ? e.floc_id() : 0,
-            base::Time::FromDeltaSinceWindowsEpoch(
-                base::Microseconds(specifics.event_time_usec()))};
-  }
-
- protected:
-  content::BrowserTaskEnvironment task_environment_;
-
-  std::unique_ptr<syncer::TestSyncService> test_sync_service_;
-  std::unique_ptr<syncer::FakeUserEventService> fake_user_event_service_;
-  std::unique_ptr<FakeFlocRemotePermissionService>
-      fake_floc_remote_permission_service_;
-  std::unique_ptr<FlocEventLogger> floc_event_logger_;
-};
-
-TEST_F(FlocEventLoggerUnitTest, DefaultSyncDisabled_EventLogging) {
-  // Expect no loggings as sync is disabled.
-  floc_event_logger_->LogFlocComputedEvent(
-      {true, 33, base::Time::FromTimeT(44)});
-  EXPECT_EQ(0u, GetLoggedEventSize());
-
-  // After 10 seconds, still no loggings.
-  task_environment_.FastForwardBy(base::Seconds(10));
-  EXPECT_EQ(0u, GetLoggedEventSize());
-}
-
-TEST_F(FlocEventLoggerUnitTest, SyncEnabledWithinTenSeconds) {
-  // Expect no loggings as sync is disabled.
-  floc_event_logger_->LogFlocComputedEvent(
-      {true, 33, base::Time::FromTimeT(44)});
-  EXPECT_EQ(0u, GetLoggedEventSize());
-
-  task_environment_.FastForwardBy(base::Seconds(9));
-  EnableSyncHistory();
-  EXPECT_EQ(0u, GetLoggedEventSize());
-
-  // After 10 seconds, expect a logging as the previous logging is attempted for
-  // the second time.
-  task_environment_.FastForwardBy(base::Seconds(1));
-  EXPECT_EQ(1u, GetLoggedEventSize());
-  EXPECT_EQ(1u, GetNumberOfRemotePermissionQueries());
-  EXPECT_EQ(true, GetEventAtIndex(0).sim_hash_computed);
-  EXPECT_EQ(33u, GetEventAtIndex(0).sim_hash);
-  EXPECT_EQ(base::Time::FromTimeT(44), GetEventAtIndex(0).time);
-}
-
-TEST_F(FlocEventLoggerUnitTest, SyncEnabledAfterTenSeconds) {
-  // Expect no loggings as sync is disabled.
-  floc_event_logger_->LogFlocComputedEvent(
-      {true, 33, base::Time::FromTimeT(44)});
-  EXPECT_EQ(0u, GetLoggedEventSize());
-
-  task_environment_.FastForwardBy(base::Seconds(11));
-
-  // If sync is enabled after 10 seconds after the logging time, the event won't
-  // be handled.
-  EnableSyncHistory();
-  task_environment_.FastForwardBy(base::Seconds(10000));
-  EXPECT_EQ(0u, GetLoggedEventSize());
-}
-
-TEST_F(FlocEventLoggerUnitTest, MultipleEventsBeforeSyncEnabled) {
-  floc_event_logger_->LogFlocComputedEvent(
-      {true, 33, base::Time::FromTimeT(44)});
-
-  task_environment_.FastForwardBy(base::Seconds(5));
-
-  floc_event_logger_->LogFlocComputedEvent(
-      {false, 999, base::Time::FromTimeT(55)});
-
-  EXPECT_EQ(0u, GetLoggedEventSize());
-
-  EnableSyncHistory();
-
-  task_environment_.FastForwardBy(base::Seconds(5));
-
-  // At time 10, the first event will be given its second attempt.
-  EXPECT_EQ(1u, GetLoggedEventSize());
-  EXPECT_EQ(1u, GetNumberOfRemotePermissionQueries());
-  EXPECT_EQ(true, GetEventAtIndex(0).sim_hash_computed);
-  EXPECT_EQ(33u, GetEventAtIndex(0).sim_hash);
-  EXPECT_EQ(base::Time::FromTimeT(44), GetEventAtIndex(0).time);
-
-  // At time 15, the second event will be given its second attempt.
-  // The sim_hash field of the 2nd event (i.e. 999) was ignored because the
-  // sim_hash_computed field is false.
-  task_environment_.FastForwardBy(base::Seconds(15));
-  EXPECT_EQ(2u, GetLoggedEventSize());
-  EXPECT_EQ(2u, GetNumberOfRemotePermissionQueries());
-  EXPECT_EQ(false, GetEventAtIndex(1).sim_hash_computed);
-  EXPECT_EQ(0u, GetEventAtIndex(1).sim_hash);
-  EXPECT_EQ(base::Time::FromTimeT(55), GetEventAtIndex(1).time);
-}
-
-// Sync-enabled followed by event logging.
-TEST_F(FlocEventLoggerUnitTest, SyncEnabled_EventLogging) {
-  // When sync gets enabled first, following requests should succeed
-  // immediately.
-  EnableSyncHistory();
-  EXPECT_EQ(0u, GetLoggedEventSize());
-
-  // Log an event. Expect it to be logged immediately.
-  floc_event_logger_->LogFlocComputedEvent(
-      {true, 33, base::Time::FromTimeT(44)});
-  EXPECT_EQ(1u, GetLoggedEventSize());
-  EXPECT_EQ(true, GetEventAtIndex(0).sim_hash_computed);
-  EXPECT_EQ(33u, GetEventAtIndex(0).sim_hash);
-  EXPECT_EQ(base::Time::FromTimeT(44), GetEventAtIndex(0).time);
-}
-
-// Sync is enabled but remote permission is disabled, the request should also
-// fail immediately.
-TEST_F(FlocEventLoggerUnitTest,
-       SyncEnabled_RemotePermissionDisabled_EventLogging) {
-  EnableSyncHistory();
-  SetRemoteSwaaNacAccountEnabled(false);
-
-  // Log an event. Expect it to fail immediately, as if failed the remote
-  // permission check.
-  floc_event_logger_->LogFlocComputedEvent(
-      {true, 33, base::Time::FromTimeT(44)});
-  EXPECT_EQ(0u, GetLoggedEventSize());
-
-  SetRemoteSwaaNacAccountEnabled(true);
-  task_environment_.FastForwardBy(base::Seconds(10));
-  EXPECT_EQ(0u, GetLoggedEventSize());
-}
-
-}  // namespace federated_learning
diff --git a/chrome/browser/federated_learning/floc_id_provider.h b/chrome/browser/federated_learning/floc_id_provider.h
deleted file mode 100644
index bc14928b..0000000
--- a/chrome/browser/federated_learning/floc_id_provider.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2020 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_FEDERATED_LEARNING_FLOC_ID_PROVIDER_H_
-#define CHROME_BROWSER_FEDERATED_LEARNING_FLOC_ID_PROVIDER_H_
-
-#include "chrome/browser/ui/webui/federated_learning/floc_internals.mojom-forward.h"
-#include "components/federated_learning/floc_id.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "net/cookies/site_for_cookies.h"
-#include "services/metrics/public/cpp/ukm_source_id.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom-forward.h"
-#include "url/origin.h"
-
-namespace federated_learning {
-
-// KeyedService which computes the floc id regularly, and notifies relevant
-// components about the updated id. The floc id represents a cohort of people
-// with similar browsing habits. For more context, see the explainer at
-// https://github.com/jkarlin/floc/blob/master/README.md.
-class FlocIdProvider : public KeyedService {
- public:
-  // Get the interest cohort in a particular context. Use the requesting
-  // context's |url| and the first-party context |top_frame_origin| for the
-  // access permission check.
-  virtual blink::mojom::InterestCohortPtr GetInterestCohortForJsApi(
-      const GURL& url,
-      const absl::optional<url::Origin>& top_frame_origin) const = 0;
-
-  // Get the relevant floc status to show in the chrome://floc-internals/ page.
-  virtual mojom::WebUIFlocStatusPtr GetFlocStatusForWebUi() const = 0;
-
-  // Record the floc id to UKM if this is the first recording attempt after each
-  // time the floc is (re-)computed. No-op if the existing floc was already
-  // recorded to UKM before.
-  virtual void MaybeRecordFlocToUkm(ukm::SourceId source_id) = 0;
-
-  // Returns the approximate time the floc will be next computed. This is not
-  // a guaranetee that floc computation will run at the returned time. The
-  // accuracy of the return value also cannot be guaranteed, for example it will
-  // return current time if a computation is currently in progress.
-  virtual base::Time GetApproximateNextComputeTime() const = 0;
-
-  ~FlocIdProvider() override = default;
-};
-
-}  // namespace federated_learning
-
-#endif  // CHROME_BROWSER_FEDERATED_LEARNING_FLOC_ID_PROVIDER_H_
diff --git a/chrome/browser/federated_learning/floc_id_provider_browsertest.cc b/chrome/browser/federated_learning/floc_id_provider_browsertest.cc
deleted file mode 100644
index e11e029..0000000
--- a/chrome/browser/federated_learning/floc_id_provider_browsertest.cc
+++ /dev/null
@@ -1,779 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_id_provider_impl.h"
-
-#include "base/memory/raw_ptr.h"
-#include "base/strings/strcat.h"
-#include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/threading/thread_restrictions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/browsing_data/chrome_browsing_data_remover_constants.h"
-#include "chrome/browser/chrome_content_browser_client.h"
-#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/federated_learning/floc_event_logger.h"
-#include "chrome/browser/federated_learning/floc_id_provider_factory.h"
-#include "chrome/browser/federated_learning/floc_remote_permission_service.h"
-#include "chrome/browser/federated_learning/floc_remote_permission_service_factory.h"
-#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/history/web_history_service_factory.h"
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/sync_service_factory.h"
-#include "chrome/browser/sync/user_event_service_factory.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "components/content_settings/core/browser/host_content_settings_map.h"
-#include "components/federated_learning/features/features.h"
-#include "components/federated_learning/floc_constants.h"
-#include "components/history/core/test/fake_web_history_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/privacy_sandbox/privacy_sandbox_settings.h"
-#include "components/sync/driver/test_sync_service.h"
-#include "components/sync_user_events/fake_user_event_service.h"
-#include "components/ukm/test_ukm_recorder.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test.h"
-#include "content/public/test/browsing_data_remover_test_util.h"
-#include "net/dns/mock_host_resolver.h"
-#include "net/test/embedded_test_server/http_request.h"
-#include "net/test/embedded_test_server/http_response.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/protobuf/src/google/protobuf/io/coded_stream.h"
-#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h"
-
-namespace federated_learning {
-
-class CopyingFileOutputStream
-    : public google::protobuf::io::CopyingOutputStream {
- public:
-  explicit CopyingFileOutputStream(base::File file) : file_(std::move(file)) {}
-
-  CopyingFileOutputStream(const CopyingFileOutputStream&) = delete;
-  CopyingFileOutputStream& operator=(const CopyingFileOutputStream&) = delete;
-
-  ~CopyingFileOutputStream() override = default;
-
-  // google::protobuf::io::CopyingOutputStream:
-  bool Write(const void* buffer, int size) override {
-    return file_.WriteAtCurrentPos(static_cast<const char*>(buffer), size) ==
-           size;
-  }
-
- private:
-  base::File file_;
-};
-
-class FlocIdProviderComputationDisabledBrowserTest
-    : public InProcessBrowserTest {};
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderComputationDisabledBrowserTest,
-                       NoProvider) {
-  EXPECT_FALSE(FlocIdProviderFactory::GetForProfile(browser()->profile()));
-}
-
-class FlocIdProviderBrowserTest : public InProcessBrowserTest {
- public:
-  FlocIdProviderBrowserTest() {
-    scoped_feature_list_.InitAndEnableFeatureWithParameters(
-        kFederatedLearningOfCohorts,
-        {{"minimum_history_domain_size_required", "1"}});
-  }
-
-  void SetUpOnMainThread() override {
-    host_resolver()->AddRule("*", "127.0.0.1");
-    https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
-    https_server_.AddDefaultHandlers(GetChromeTestDataDir());
-
-    RegisterRequestHandler();
-
-    content::SetupCrossSiteRedirector(&https_server_);
-    ASSERT_TRUE(https_server_.Start());
-  }
-
-  virtual void RegisterRequestHandler() {}
-
-  FlocIdProvider* floc_id_provider() {
-    return FlocIdProviderFactory::GetForProfile(browser()->profile());
-  }
-
-  PrefService* floc_prefs() {
-    return static_cast<FlocIdProviderImpl*>(floc_id_provider())->prefs_;
-  }
-
-  FlocId GetFlocId() {
-    return static_cast<FlocIdProviderImpl*>(floc_id_provider())->floc_id_;
-  }
-
-  std::string test_host() const { return "a.test"; }
-
- protected:
-  base::test::ScopedFeatureList scoped_feature_list_;
-
-  net::EmbeddedTestServer https_server_{
-      net::test_server::EmbeddedTestServer::TYPE_HTTPS};
-};
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderBrowserTest, NoProviderInIncognitoMode) {
-  FlocIdProvider* original_provider = floc_id_provider();
-  ASSERT_TRUE(original_provider);
-
-  GURL url = https_server_.GetURL(test_host(), "/title1.html");
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(CreateIncognitoBrowser(), url));
-
-  ASSERT_TRUE(browser()->profile()->HasPrimaryOTRProfile());
-
-  Profile* off_the_record_profile =
-      browser()->profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true);
-  ASSERT_TRUE(off_the_record_profile);
-
-  FlocIdProvider* incognito_floc_id_provider =
-      FlocIdProviderFactory::GetForProfile(off_the_record_profile);
-  ASSERT_FALSE(incognito_floc_id_provider);
-}
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderBrowserTest, PrefsMember) {
-  EXPECT_EQ(floc_prefs(), browser()->profile()->GetPrefs());
-  EXPECT_NE(floc_prefs(), g_browser_process->local_state());
-}
-
-class MockFlocRemotePermissionService : public FlocRemotePermissionService {
- public:
-  using FlocRemotePermissionService::FlocRemotePermissionService;
-
-  GURL GetQueryFlocPermissionUrl() const override {
-    GURL query_url = FlocRemotePermissionService::GetQueryFlocPermissionUrl();
-
-    GURL::Replacements replacements;
-    replacements.SetHostStr(replacement_host_);
-    replacements.SetPortStr(replacement_port_);
-
-    query_url = query_url.ReplaceComponents(replacements);
-
-    return query_url;
-  }
-
-  void SetReplacementHostAndPort(const std::string& replacement_host,
-                                 const std::string& replacement_port) {
-    replacement_host_ = replacement_host;
-    replacement_port_ = replacement_port;
-  }
-
- private:
-  std::string replacement_host_;
-  std::string replacement_port_;
-};
-
-// To intercept the request so as to handle it later.
-class MockFlocEventLogger : public FlocEventLogger {
- public:
-  using FlocEventLogger::FlocEventLogger;
-  using FlocEventLogger::FlocEventLogger::Event;
-
-  ~MockFlocEventLogger() override = default;
-
-  void LogFlocComputedEvent(Event event) override {
-    events_.push_back(std::move(event));
-  }
-
-  size_t NumberOfLogAttemptsQueued() const { return events_.size(); }
-
-  void HandleLastRequest() {
-    ASSERT_LT(0u, events_.size());
-    CheckCanLogEvent(base::BindOnce(&FlocEventLogger::OnCanLogEventDecided,
-                                    weak_ptr_factory_.GetWeakPtr(),
-                                    events_.back()));
-  }
-
- private:
-  std::vector<Event> events_;
-};
-
-class FlocIdProviderSortingLshUninitializedBrowserTest
-    : public FlocIdProviderBrowserTest {
- public:
-  void SetUpOnMainThread() override {
-    FlocIdProviderBrowserTest::SetUpOnMainThread();
-    ConfigureReplacementHostAndPortForRemotePermissionService();
-  }
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
-                                    "InterestCohortAPI");
-  }
-
-  // BrowserTestBase::SetUpInProcessBrowserTestFixture
-  void SetUpInProcessBrowserTestFixture() override {
-    subscription_ =
-        BrowserContextDependencyManager::GetInstance()
-            ->RegisterCreateServicesCallbackForTesting(base::BindRepeating(
-                &FlocIdProviderSortingLshUninitializedBrowserTest::
-                    OnWillCreateBrowserContextServices,
-                base::Unretained(this)));
-  }
-
-  // FlocIdProviderBrowserTest::RegisterRequestHandler
-  void RegisterRequestHandler() override {
-    https_server_.RegisterRequestHandler(base::BindRepeating(
-        &FlocIdProviderSortingLshUninitializedBrowserTest::HandleRequest,
-        base::Unretained(this)));
-  }
-
-  std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
-      const net::test_server::HttpRequest& request) {
-    const GURL& url = request.GetURL();
-
-    // Use the default handler for unrelated requests.
-    if (url.path() != "/settings/do_ad_settings_allow_floc_poc")
-      return nullptr;
-
-    auto response = std::make_unique<net::test_server::BasicHttpResponse>();
-
-    if (!ShouldAllowRemotePermission()) {
-      response->set_code(net::HTTP_UNAUTHORIZED);
-      return std::move(response);
-    }
-
-    response->set_code(net::HTTP_OK);
-    response->set_content(std::string("[true, true, true]"));
-    return std::move(response);
-  }
-
-  virtual bool ShouldAllowRemotePermission() const { return true; }
-
-  std::string InvokeInterestCohortJsApi(
-      const content::ToRenderFrameHost& adapter) {
-    return EvalJs(adapter, R"(
-      document.interestCohort()
-      .then(floc => JSON.stringify(floc, Object.keys(floc).sort()))
-      .catch(error => 'rejected');
-    )")
-        .ExtractString();
-  }
-
-  void ConfigureReplacementHostAndPortForRemotePermissionService() {
-    MockFlocRemotePermissionService* remote_permission_service =
-        static_cast<MockFlocRemotePermissionService*>(
-            FlocRemotePermissionServiceFactory::GetForProfile(
-                browser()->profile()));
-    GURL test_host_base_url = https_server_.GetURL(test_host(), "/");
-    remote_permission_service->SetReplacementHostAndPort(
-        test_host_base_url.host(), test_host_base_url.port());
-  }
-
-  std::vector<GURL> GetHistoryUrls() {
-    ui_test_utils::HistoryEnumerator enumerator(browser()->profile());
-    return enumerator.urls();
-  }
-
-  void FinishOutstandingRemotePermissionQueries() {
-    base::RunLoop run_loop;
-    FlocRemotePermissionServiceFactory::GetForProfile(browser()->profile())
-        ->QueryFlocPermission(
-            base::BindLambdaForTesting([&](bool success) { run_loop.Quit(); }),
-            PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
-    run_loop.Run();
-  }
-
-  void FinishOutstandingHistoryQueries() {
-    base::RunLoop run_loop;
-    base::CancelableTaskTracker tracker;
-    HistoryServiceFactory::GetForProfile(browser()->profile(),
-                                         ServiceAccessType::EXPLICIT_ACCESS)
-        ->QueryHistory(
-            std::u16string(), history::QueryOptions(),
-            base::BindLambdaForTesting(
-                [&](history::QueryResults results) { run_loop.Quit(); }),
-            &tracker);
-    run_loop.Run();
-  }
-
-  void FinishOutstandingSortingLshQueries() {
-    base::RunLoop run_loop;
-    const uint64_t dummy_sim_hash = 0u;
-    g_browser_process->floc_sorting_lsh_clusters_service()->ApplySortingLsh(
-        dummy_sim_hash,
-        base::BindLambdaForTesting(
-            [&](absl::optional<uint64_t>, base::Version) { run_loop.Quit(); }));
-    run_loop.Run();
-  }
-
-  void ExpireHistoryBefore(base::Time end_time) {
-    base::RunLoop run_loop;
-    base::CancelableTaskTracker tracker;
-    HistoryServiceFactory::GetForProfile(browser()->profile(),
-                                         ServiceAccessType::EXPLICIT_ACCESS)
-        ->ExpireHistoryBetween(
-            /*restrict_urls=*/{}, /*begin_time=*/base::Time(), end_time,
-            /*user_initiated=*/true,
-            base::BindLambdaForTesting([&]() { run_loop.Quit(); }), &tracker);
-    run_loop.Run();
-  }
-
-  void ClearCookiesBrowsingData() {
-    content::BrowsingDataRemover* remover =
-        browser()->profile()->GetBrowsingDataRemover();
-    content::BrowsingDataRemoverCompletionObserver observer(remover);
-    remover->RemoveAndReply(
-        base::Time(), base::Time::Max(),
-        content::BrowsingDataRemover::DATA_TYPE_COOKIES,
-        content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB, &observer);
-    observer.BlockUntilCompletion();
-  }
-
-  base::FilePath GetUniqueTemporaryPath() {
-    CHECK(scoped_temp_dir_.IsValid() || scoped_temp_dir_.CreateUniqueTempDir());
-    return scoped_temp_dir_.GetPath().AppendASCII(
-        base::NumberToString(next_unique_file_suffix_++));
-  }
-
-  base::FilePath CreateSortingLshFile(
-      const std::vector<std::pair<uint32_t, bool>>& sorting_lsh_entries) {
-    base::ScopedAllowBlockingForTesting allow_blocking;
-
-    base::FilePath file_path = GetUniqueTemporaryPath();
-    base::File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ |
-                                   base::File::FLAG_WRITE);
-    CHECK(file.IsValid());
-
-    CopyingFileOutputStream copying_stream(std::move(file));
-    google::protobuf::io::CopyingOutputStreamAdaptor zero_copy_stream_adaptor(
-        &copying_stream);
-
-    google::protobuf::io::CodedOutputStream output_stream(
-        &zero_copy_stream_adaptor);
-
-    for (const auto& p : sorting_lsh_entries) {
-      uint32_t next = p.first;
-      bool is_blocked = p.second;
-      if (is_blocked) {
-        next |= kSortingLshBlockedMask;
-      }
-      output_stream.WriteVarint32(next);
-    }
-
-    CHECK(!output_stream.HadError());
-
-    return file_path;
-  }
-
-  void FinishOutstandingAsyncQueries() {
-    FinishOutstandingHistoryQueries();
-    FinishOutstandingSortingLshQueries();
-    FinishOutstandingRemotePermissionQueries();
-  }
-
-  // Turn on sync-history, set up the sorting-lsh file, and trigger the
-  // file-ready event.
-  void InitializeSortingLsh(
-      const std::vector<std::pair<uint32_t, bool>>& sorting_lsh_entries,
-      const base::Version& version) {
-    g_browser_process->floc_sorting_lsh_clusters_service()
-        ->OnSortingLshClustersFileReady(
-            CreateSortingLshFile(sorting_lsh_entries), version);
-    FinishOutstandingAsyncQueries();
-  }
-
-  history::HistoryService* history_service() {
-    return HistoryServiceFactory::GetForProfile(
-        browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS);
-  }
-
-  syncer::TestSyncService* sync_service() {
-    return static_cast<syncer::TestSyncService*>(
-        SyncServiceFactory::GetForProfile(browser()->profile()));
-  }
-
-  syncer::FakeUserEventService* user_event_service() {
-    return static_cast<syncer::FakeUserEventService*>(
-        browser_sync::UserEventServiceFactory::GetForProfile(
-            browser()->profile()));
-  }
-
-  content::WebContents* web_contents() {
-    return browser()->tab_strip_model()->GetActiveWebContents();
-  }
-
- protected:
-  void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
-    SyncServiceFactory::GetInstance()->SetTestingFactory(
-        context,
-        base::BindRepeating(&FlocIdProviderSortingLshUninitializedBrowserTest::
-                                CreateSyncService,
-                            base::Unretained(this)));
-
-    browser_sync::UserEventServiceFactory::GetInstance()->SetTestingFactory(
-        context,
-        base::BindRepeating(&FlocIdProviderSortingLshUninitializedBrowserTest::
-                                CreateUserEventService,
-                            base::Unretained(this)));
-
-    FlocRemotePermissionServiceFactory::GetInstance()->SetTestingFactory(
-        context,
-        base::BindRepeating(&FlocIdProviderSortingLshUninitializedBrowserTest::
-                                CreateFlocRemotePermissionService,
-                            base::Unretained(this)));
-
-    FlocIdProviderFactory::GetInstance()->SetTestingFactory(
-        context,
-        base::BindRepeating(&FlocIdProviderSortingLshUninitializedBrowserTest::
-                                CreateFlocIdProvider,
-                            base::Unretained(this)));
-  }
-
-  std::unique_ptr<KeyedService> CreateSyncService(
-      content::BrowserContext* context) {
-    return std::make_unique<syncer::TestSyncService>();
-  }
-
-  std::unique_ptr<KeyedService> CreateUserEventService(
-      content::BrowserContext* context) {
-    return std::make_unique<syncer::FakeUserEventService>();
-  }
-
-  std::unique_ptr<KeyedService> CreateFlocRemotePermissionService(
-      content::BrowserContext* context) {
-    Profile* profile = static_cast<Profile*>(context);
-
-    auto remote_permission_service =
-        std::make_unique<MockFlocRemotePermissionService>(
-            profile->GetDefaultStoragePartition()
-                ->GetURLLoaderFactoryForBrowserProcess());
-    return std::move(remote_permission_service);
-  }
-
-  std::unique_ptr<KeyedService> CreateFlocIdProvider(
-      content::BrowserContext* context) {
-    Profile* profile = Profile::FromBrowserContext(context);
-
-    syncer::SyncService* sync_service =
-        SyncServiceFactory::GetForProfile(profile);
-
-    PrivacySandboxSettings* privacy_sandbox_settings =
-        PrivacySandboxSettingsFactory::GetForProfile(profile);
-
-    FlocRemotePermissionService* floc_remote_permission_service =
-        FlocRemotePermissionServiceFactory::GetForProfile(profile);
-
-    history::HistoryService* history_service =
-        HistoryServiceFactory::GetForProfile(
-            profile, ServiceAccessType::IMPLICIT_ACCESS);
-
-    syncer::UserEventService* user_event_service =
-        browser_sync::UserEventServiceFactory::GetForProfile(profile);
-
-    auto floc_event_logger = std::make_unique<MockFlocEventLogger>(
-        sync_service, floc_remote_permission_service, user_event_service);
-
-    // On ChromeOS, there can be more than one profile, but the tests will only
-    // be using the first one. So we fix the |floc_event_logger_| to the first
-    // one created.
-    if (!floc_event_logger_)
-      floc_event_logger_ = floc_event_logger.get();
-
-    // Before creating the floc id provider, add some initial history.
-    history::HistoryAddPageArgs add_page_args;
-    add_page_args.time = base::Time::Now();
-    add_page_args.context_id = reinterpret_cast<history::ContextID>(1);
-    add_page_args.nav_entry_id = 1;
-
-    add_page_args.url = GURL(base::StrCat({"https://www.initial-history.com"}));
-    history_service->AddPage(add_page_args);
-    history_service->SetFlocAllowed(add_page_args.context_id,
-                                    add_page_args.nav_entry_id,
-                                    add_page_args.url);
-
-    return std::make_unique<FlocIdProviderImpl>(
-        profile->GetPrefs(), privacy_sandbox_settings, history_service,
-        std::move(floc_event_logger));
-  }
-
-  void SetPermission(ContentSettingsType content_type,
-                     const ContentSettingsPattern& primary_pattern,
-                     ContentSetting setting) {
-    auto* settings_map =
-        HostContentSettingsMapFactory::GetForProfile(browser()->profile());
-    DCHECK(settings_map);
-
-    settings_map->SetContentSettingCustomScope(
-        primary_pattern, ContentSettingsPattern::Wildcard(), content_type,
-        setting);
-  }
-
-  // Owned by the floc id provider.
-  raw_ptr<MockFlocEventLogger> floc_event_logger_ = nullptr;
-
-  base::ScopedTempDir scoped_temp_dir_;
-  int next_unique_file_suffix_ = 1;
-
-  base::CallbackListSubscription subscription_;
-};
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderSortingLshUninitializedBrowserTest,
-                       SortingLshBlocked) {
-  // All sim_hash will be encoded as 0 during sorting-lsh, and that result will
-  // be blocked.
-  InitializeSortingLsh({{kMaxNumberOfBitsInFloc, true}}, base::Version("2.0"));
-
-  // Expect that the final id is invalid because it was blocked.
-  EXPECT_FALSE(GetFlocId().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidBlocked, GetFlocId().status());
-
-  EXPECT_EQ(1u, floc_event_logger_->NumberOfLogAttemptsQueued());
-  floc_event_logger_->HandleLastRequest();
-  FinishOutstandingAsyncQueries();
-
-  // Expect that the FlocIdComputed user event is recorded with the desired
-  // sim-hash.
-  ASSERT_EQ(1u, user_event_service()->GetRecordedUserEvents().size());
-  const sync_pb::UserEventSpecifics& specifics =
-      user_event_service()->GetRecordedUserEvents()[0];
-  const sync_pb::UserEventSpecifics_FlocIdComputed& event =
-      specifics.floc_id_computed_event();
-  EXPECT_EQ(FlocId::SimHashHistory({"initial-history.com"}), event.floc_id());
-}
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderSortingLshUninitializedBrowserTest,
-                       CorruptedSortingLSH) {
-  // All sim_hash will be encoded as an invalid id.
-  InitializeSortingLsh({}, base::Version("3"));
-
-  // Expect that the final id is invalid due to unexpected sorting-lsh file
-  // format.
-  EXPECT_FALSE(GetFlocId().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidBlocked, GetFlocId().status());
-
-  EXPECT_EQ(1u, floc_event_logger_->NumberOfLogAttemptsQueued());
-  floc_event_logger_->HandleLastRequest();
-  FinishOutstandingAsyncQueries();
-
-  // Expect that the FlocIdComputed user event is recorded with the desired
-  // sim-hash.
-  ASSERT_EQ(1u, user_event_service()->GetRecordedUserEvents().size());
-  const sync_pb::UserEventSpecifics& specifics =
-      user_event_service()->GetRecordedUserEvents()[0];
-  const sync_pb::UserEventSpecifics_FlocIdComputed& event =
-      specifics.floc_id_computed_event();
-  EXPECT_EQ(FlocId::SimHashHistory({"initial-history.com"}), event.floc_id());
-}
-
-class FlocIdProviderSortingLshInitializedBrowserTest
-    : public FlocIdProviderSortingLshUninitializedBrowserTest {
- public:
-  void SetUpOnMainThread() override {
-    FlocIdProviderSortingLshUninitializedBrowserTest::SetUpOnMainThread();
-    ConfigureReplacementHostAndPortForRemotePermissionService();
-
-    // Initialize the sorting-lsh file to trigger the 1st computation. All
-    // sim_hash will be encoded as 0 during sorting-lsh process.
-    InitializeSortingLsh({{kMaxNumberOfBitsInFloc, false}},
-                         base::Version("9.0"));
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderSortingLshInitializedBrowserTest,
-                       FlocIdValue_ImmediateComputeOnStartUp) {
-  EXPECT_TRUE(GetFlocId().IsValid());
-
-  EXPECT_EQ(1u, floc_event_logger_->NumberOfLogAttemptsQueued());
-  floc_event_logger_->HandleLastRequest();
-  FinishOutstandingAsyncQueries();
-
-  // Check that the original sim_hash is not 0, and we are recording the
-  // sim_hash in the event log.
-  EXPECT_NE(0u, FlocId::SimHashHistory({"initial-history.com"}));
-  ASSERT_EQ(1u, user_event_service()->GetRecordedUserEvents().size());
-  const sync_pb::UserEventSpecifics& specifics =
-      user_event_service()->GetRecordedUserEvents()[0];
-  EXPECT_EQ(sync_pb::UserEventSpecifics::kFlocIdComputedEvent,
-            specifics.event_case());
-  const sync_pb::UserEventSpecifics_FlocIdComputed& event =
-      specifics.floc_id_computed_event();
-  EXPECT_EQ(FlocId::SimHashHistory({"initial-history.com"}), event.floc_id());
-}
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderSortingLshInitializedBrowserTest,
-                       UkmEvent) {
-  ukm::TestAutoSetUkmRecorder ukm_recorder;
-
-  EXPECT_TRUE(GetFlocId().IsValid());
-
-  auto entries =
-      ukm_recorder.GetEntriesByName(ukm::builders::FlocPageLoad::kEntryName);
-  EXPECT_EQ(0u, entries.size());
-
-  GURL main_frame_url = https_server_.GetURL(test_host(), "/title1.html");
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
-
-  entries =
-      ukm_recorder.GetEntriesByName(ukm::builders::FlocPageLoad::kEntryName);
-  EXPECT_EQ(1u, entries.size());
-
-  ukm_recorder.ExpectEntrySourceHasUrl(entries.front(), main_frame_url);
-  ukm_recorder.ExpectEntryMetric(entries.front(),
-                                 ukm::builders::FlocPageLoad::kFlocIdName,
-                                 /*expected_value=*/0);
-}
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderSortingLshInitializedBrowserTest,
-                       ClearCookiesInvalidateFloc) {
-  EXPECT_TRUE(GetFlocId().IsValid());
-
-  EXPECT_EQ(1u, floc_event_logger_->NumberOfLogAttemptsQueued());
-
-  ClearCookiesBrowsingData();
-  FinishOutstandingAsyncQueries();
-
-  // The floc has been invalidated. Expect no additional event logging.
-  EXPECT_FALSE(GetFlocId().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidReset, GetFlocId().status());
-  EXPECT_EQ(1u, floc_event_logger_->NumberOfLogAttemptsQueued());
-}
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderSortingLshInitializedBrowserTest,
-                       HistoryDeleteInvalidateFloc) {
-  EXPECT_TRUE(GetFlocId().IsValid());
-
-  EXPECT_EQ(1u, floc_event_logger_->NumberOfLogAttemptsQueued());
-  floc_event_logger_->HandleLastRequest();
-  FinishOutstandingAsyncQueries();
-
-  ASSERT_EQ(1u, user_event_service()->GetRecordedUserEvents().size());
-
-  ExpireHistoryBefore(base::Time::Now());
-  FinishOutstandingAsyncQueries();
-  EXPECT_EQ(2u, floc_event_logger_->NumberOfLogAttemptsQueued());
-  floc_event_logger_->HandleLastRequest();
-  FinishOutstandingAsyncQueries();
-
-  // Expect that the 2nd FlocIdComputed event has a missing floc field, that
-  // implies invalidation due to history deletion.
-  ASSERT_EQ(2u, user_event_service()->GetRecordedUserEvents().size());
-
-  const sync_pb::UserEventSpecifics& specifics =
-      user_event_service()->GetRecordedUserEvents()[1];
-  EXPECT_EQ(sync_pb::UserEventSpecifics::kFlocIdComputedEvent,
-            specifics.event_case());
-
-  const sync_pb::UserEventSpecifics_FlocIdComputed& event =
-      specifics.floc_id_computed_event();
-  EXPECT_FALSE(event.has_floc_id());
-}
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderSortingLshInitializedBrowserTest,
-                       InterestCohortAPI_FlocNotAvailable) {
-  EXPECT_TRUE(GetFlocId().IsValid());
-
-  ExpireHistoryBefore(base::Time::Now());
-  FinishOutstandingAsyncQueries();
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server_.GetURL(test_host(), "/title1.html")));
-
-  // Promise rejected as the floc is not yet available.
-  EXPECT_EQ("rejected", InvokeInterestCohortJsApi(web_contents()));
-}
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderSortingLshInitializedBrowserTest,
-                       InterestCohortAPI_MainFrame) {
-  EXPECT_TRUE(GetFlocId().IsValid());
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server_.GetURL(test_host(), "/title1.html")));
-
-  // Promise resolved with the expected dictionary object.
-  EXPECT_EQ(base::StrCat({"{\"id\":\"0\",\"version\":\"chrome.1.9\"}"}),
-            InvokeInterestCohortJsApi(web_contents()));
-}
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderSortingLshInitializedBrowserTest,
-                       InterestCohortAPI_SameOriginSubframe) {
-  EXPECT_TRUE(GetFlocId().IsValid());
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server_.GetURL(test_host(), "/iframe_blank.html")));
-
-  content::NavigateIframeToURL(
-      web_contents(),
-      /*iframe_id=*/"test", https_server_.GetURL(test_host(), "/title1.html"));
-
-  content::RenderFrameHost* child =
-      content::ChildFrameAt(web_contents()->GetMainFrame(), 0);
-
-  // Promise resolved with the expected dictionary object.
-  EXPECT_EQ(base::StrCat({"{\"id\":\"0\",\"version\":\"chrome.1.9\"}"}),
-            InvokeInterestCohortJsApi(child));
-}
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderSortingLshInitializedBrowserTest,
-                       InterestCohortAPI_CrossOriginSubframe) {
-  EXPECT_TRUE(GetFlocId().IsValid());
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server_.GetURL(test_host(), "/iframe_blank.html")));
-
-  content::NavigateIframeToURL(web_contents(),
-                               /*iframe_id=*/"test",
-                               https_server_.GetURL("b.test", "/title1.html"));
-
-  content::RenderFrameHost* child =
-      content::ChildFrameAt(web_contents()->GetMainFrame(), 0);
-
-  // Promise resolved with the expected dictionary object.
-  EXPECT_EQ(base::StrCat({"{\"id\":\"0\",\"version\":\"chrome.1.9\"}"}),
-            InvokeInterestCohortJsApi(child));
-}
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderSortingLshInitializedBrowserTest,
-                       InterestCohortAPI_CookiesPermissionDisallow) {
-  EXPECT_TRUE(GetFlocId().IsValid());
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server_.GetURL(test_host(), "/iframe_blank.html")));
-
-  content::NavigateIframeToURL(web_contents(),
-                               /*iframe_id=*/"test",
-                               https_server_.GetURL("b.test", "/title1.html"));
-
-  content::RenderFrameHost* child =
-      content::ChildFrameAt(web_contents()->GetMainFrame(), 0);
-
-  // Block cookies on "b.test".
-  SetPermission(
-      ContentSettingsType::COOKIES,
-      ContentSettingsPattern::FromURL(https_server_.GetURL("b.test", "/")),
-      CONTENT_SETTING_BLOCK);
-
-  // Promise rejected as the cookies permission disallows the child's host.
-  EXPECT_EQ("rejected", InvokeInterestCohortJsApi(child));
-
-  // Promise resolved with the expected dictionary object.
-  EXPECT_EQ(base::StrCat({"{\"id\":\"0\",\"version\":\"chrome.1.9\"}"}),
-            InvokeInterestCohortJsApi(web_contents()));
-}
-
-class FlocIdProviderAutoDenyRemotePermissionBrowserTest
-    : public FlocIdProviderSortingLshInitializedBrowserTest {
- public:
-  bool ShouldAllowRemotePermission() const override { return false; }
-};
-
-IN_PROC_BROWSER_TEST_F(FlocIdProviderAutoDenyRemotePermissionBrowserTest,
-                       CookieNotSent_RemotePermissionDenied_NoEventLogging) {
-  EXPECT_TRUE(GetFlocId().IsValid());
-
-  EXPECT_EQ(1u, floc_event_logger_->NumberOfLogAttemptsQueued());
-  floc_event_logger_->HandleLastRequest();
-  FinishOutstandingAsyncQueries();
-
-  // The event shouldn't have been recorded.
-  ASSERT_EQ(0u, user_event_service()->GetRecordedUserEvents().size());
-}
-
-}  // namespace federated_learning
diff --git a/chrome/browser/federated_learning/floc_id_provider_factory.cc b/chrome/browser/federated_learning/floc_id_provider_factory.cc
deleted file mode 100644
index 1a161ab..0000000
--- a/chrome/browser/federated_learning/floc_id_provider_factory.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_id_provider_factory.h"
-
-#include "base/memory/singleton.h"
-#include "chrome/browser/federated_learning/floc_event_logger.h"
-#include "chrome/browser/federated_learning/floc_id_provider_impl.h"
-#include "chrome/browser/federated_learning/floc_remote_permission_service.h"
-#include "chrome/browser/federated_learning/floc_remote_permission_service_factory.h"
-#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/sync_service_factory.h"
-#include "chrome/browser/sync/user_event_service_factory.h"
-#include "components/federated_learning/features/features.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/privacy_sandbox/privacy_sandbox_settings.h"
-#include "components/sync/driver/sync_service.h"
-#include "components/sync_user_events/user_event_service.h"
-
-namespace federated_learning {
-
-// static
-FlocIdProvider* FlocIdProviderFactory::GetForProfile(Profile* profile) {
-  return static_cast<FlocIdProvider*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
-
-// static
-FlocIdProviderFactory* FlocIdProviderFactory::GetInstance() {
-  return base::Singleton<FlocIdProviderFactory>::get();
-}
-
-FlocIdProviderFactory::FlocIdProviderFactory()
-    : BrowserContextKeyedServiceFactory(
-          "FlocIdProvider",
-          BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(SyncServiceFactory::GetInstance());
-  DependsOn(PrivacySandboxSettingsFactory::GetInstance());
-  DependsOn(FlocRemotePermissionServiceFactory::GetInstance());
-  DependsOn(HistoryServiceFactory::GetInstance());
-  DependsOn(browser_sync::UserEventServiceFactory::GetInstance());
-}
-
-FlocIdProviderFactory::~FlocIdProviderFactory() = default;
-
-KeyedService* FlocIdProviderFactory::BuildServiceInstanceFor(
-    content::BrowserContext* context) const {
-  if (!base::FeatureList::IsEnabled(kFederatedLearningOfCohorts))
-    return nullptr;
-
-  Profile* profile = Profile::FromBrowserContext(context);
-
-  syncer::SyncService* sync_service =
-      SyncServiceFactory::GetForProfile(profile);
-  if (!sync_service)
-    return nullptr;
-
-  PrivacySandboxSettings* privacy_sandbox_settings =
-      PrivacySandboxSettingsFactory::GetForProfile(profile);
-  if (!privacy_sandbox_settings)
-    return nullptr;
-
-  FlocRemotePermissionService* floc_remote_permission_service =
-      FlocRemotePermissionServiceFactory::GetForProfile(profile);
-  if (!floc_remote_permission_service)
-    return nullptr;
-
-  history::HistoryService* history_service =
-      HistoryServiceFactory::GetForProfile(profile,
-                                           ServiceAccessType::IMPLICIT_ACCESS);
-  if (!history_service)
-    return nullptr;
-
-  syncer::UserEventService* user_event_service =
-      browser_sync::UserEventServiceFactory::GetForProfile(profile);
-  if (!user_event_service)
-    return nullptr;
-
-  auto floc_event_logger = std::make_unique<FlocEventLogger>(
-      sync_service, floc_remote_permission_service, user_event_service);
-
-  return new FlocIdProviderImpl(profile->GetPrefs(), privacy_sandbox_settings,
-                                history_service, std::move(floc_event_logger));
-}
-
-}  // namespace federated_learning
diff --git a/chrome/browser/federated_learning/floc_id_provider_factory.h b/chrome/browser/federated_learning/floc_id_provider_factory.h
deleted file mode 100644
index d330b9e..0000000
--- a/chrome/browser/federated_learning/floc_id_provider_factory.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2020 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_FEDERATED_LEARNING_FLOC_ID_PROVIDER_FACTORY_H_
-#define CHROME_BROWSER_FEDERATED_LEARNING_FLOC_ID_PROVIDER_FACTORY_H_
-
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-namespace base {
-template <typename T>
-struct DefaultSingletonTraits;
-}
-
-class Profile;
-
-namespace federated_learning {
-
-class FlocIdProvider;
-
-// Singleton that owns all FlocIdProvider and associates them with Profiles.
-class FlocIdProviderFactory : public BrowserContextKeyedServiceFactory {
- public:
-  static FlocIdProvider* GetForProfile(Profile* profile);
-  static FlocIdProviderFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<FlocIdProviderFactory>;
-
-  FlocIdProviderFactory();
-  ~FlocIdProviderFactory() override;
-
-  // BrowserContextKeyedServiceFactory:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* context) const override;
-};
-
-}  // namespace federated_learning
-
-#endif  // CHROME_BROWSER_FEDERATED_LEARNING_FLOC_ID_PROVIDER_FACTORY_H_
diff --git a/chrome/browser/federated_learning/floc_id_provider_impl.cc b/chrome/browser/federated_learning/floc_id_provider_impl.cc
deleted file mode 100644
index 45e47795..0000000
--- a/chrome/browser/federated_learning/floc_id_provider_impl.cc
+++ /dev/null
@@ -1,459 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_id_provider_impl.h"
-
-#include <unordered_set>
-
-#include "base/strings/strcat.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/federated_learning/floc_event_logger.h"
-#include "chrome/browser/ui/webui/federated_learning/floc_internals.mojom.h"
-#include "components/federated_learning/features/features.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/prefs/pref_service.h"
-#include "components/privacy_sandbox/privacy_sandbox_settings.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/metrics/public/cpp/ukm_recorder.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
-
-namespace federated_learning {
-
-namespace {
-
-constexpr int kQueryHistoryWindowInDays = 7;
-
-struct StartupComputeDecision {
-  bool invalidate_existing_floc = true;
-  // Will be absl::nullopt if should recompute immediately.
-  absl::optional<base::TimeDelta> next_compute_delay;
-};
-
-// Determine whether we can keep using the previous floc and/or when should the
-// next floc computation occur.
-StartupComputeDecision GetStartupComputeDecision(
-    const FlocId& last_floc,
-    base::Time floc_accessible_since) {
-  // The floc has never been computed. This could happen with a fresh profile,
-  // or some early trigger conditions were never met (e.g. sorting-lsh file has
-  // never been ready).
-  if (last_floc.compute_time().is_null()) {
-    return StartupComputeDecision{.invalidate_existing_floc = true,
-                                  .next_compute_delay = absl::nullopt};
-  }
-
-  // The browser started with a kFlocIdFinchConfigVersion param different from
-  // the param when floc was computed last time.
-  //
-  // TODO(yaoxia): Ideally we want to compare the entire version that also
-  // includes the sorting-lsh version. We'll need to postpone those checks to
-  // a point where an existing sorting-lsh file would have been loaded, i.e. not
-  // too soon when the file is not ready yet, but not too late if the file
-  // wouldn't arrive due to e.g. component updater issue.
-  if (last_floc.finch_config_version() !=
-      static_cast<uint32_t>(kFlocIdFinchConfigVersion.Get())) {
-    return StartupComputeDecision{.invalidate_existing_floc = true,
-                                  .next_compute_delay = absl::nullopt};
-  }
-
-  base::TimeDelta presumed_next_compute_delay =
-      kFlocIdScheduledUpdateInterval.Get() + last_floc.compute_time() -
-      base::Time::Now();
-
-  // The last floc has expired.
-  if (presumed_next_compute_delay <= base::TimeDelta()) {
-    return StartupComputeDecision{.invalidate_existing_floc = true,
-                                  .next_compute_delay = absl::nullopt};
-  }
-
-  // This could happen if the machine time has changed since the last
-  // computation. Recompute immediately to align with the expected schedule
-  // rather than potentially stop computing for a very long time.
-  if (presumed_next_compute_delay >= 2 * kFlocIdScheduledUpdateInterval.Get()) {
-    return StartupComputeDecision{.invalidate_existing_floc = true,
-                                  .next_compute_delay = absl::nullopt};
-  }
-
-  // Normally "floc_accessible_since <= last_floc.history_begin_time()" is an
-  // invariant, because we monitor its update and reset the floc accordingly.
-  // But "Clear on exit" may cause a cookie deletion on shutdown (practically on
-  // startup) that will reset floc_accessible_since to base::Time::Now and
-  // break the invariant on startup.
-  if (floc_accessible_since > last_floc.history_begin_time()) {
-    return StartupComputeDecision{
-        .invalidate_existing_floc = true,
-        .next_compute_delay = presumed_next_compute_delay};
-  }
-
-  return StartupComputeDecision{
-      .invalidate_existing_floc = false,
-      .next_compute_delay = presumed_next_compute_delay};
-}
-
-}  // namespace
-
-FlocIdProviderImpl::FlocIdProviderImpl(
-    PrefService* prefs,
-    PrivacySandboxSettings* privacy_sandbox_settings,
-    history::HistoryService* history_service,
-    std::unique_ptr<FlocEventLogger> floc_event_logger)
-    : prefs_(prefs),
-      privacy_sandbox_settings_(privacy_sandbox_settings),
-      history_service_(history_service),
-      floc_event_logger_(std::move(floc_event_logger)),
-      floc_id_(FlocId::ReadFromPrefs(prefs_)) {
-  privacy_sandbox_settings->AddObserver(this);
-  history_service_observation_.Observe(history_service);
-  g_browser_process->floc_sorting_lsh_clusters_service()->AddObserver(this);
-
-  StartupComputeDecision decision = GetStartupComputeDecision(
-      floc_id_, privacy_sandbox_settings->FlocDataAccessibleSince());
-
-  // Invalidate the expired floc and/or assign a better invalid reason.
-  if (decision.invalidate_existing_floc) {
-    // We only switch from one invalid status to another invalid status when
-    // the next cohort computation becomes ready to run (i.e.
-    // kInvalidWaitingToStart).
-    FlocId::Status maybe_new_status =
-        decision.next_compute_delay.has_value()
-            ? (floc_id_.status() == FlocId::Status::kValid)
-                  ? FlocId::Status::kInvalidReset
-                  : floc_id_.status()
-            : FlocId::Status::kInvalidWaitingToStart;
-
-    floc_id_.UpdateStatusAndSaveToPrefs(prefs_, maybe_new_status);
-  }
-
-  // Schedule the next floc computation if a delay is needed; otherwise, the
-  // next computation will occur as soon as the sorting-lsh file is loaded.
-  if (decision.next_compute_delay.has_value())
-    ScheduleFlocComputation(decision.next_compute_delay.value());
-
-  if (g_browser_process->floc_sorting_lsh_clusters_service()
-          ->IsSortingLshClustersFileReady()) {
-    OnSortingLshClustersFileReady();
-  }
-}
-
-FlocIdProviderImpl::~FlocIdProviderImpl() {
-  g_browser_process->floc_sorting_lsh_clusters_service()->RemoveObserver(this);
-}
-
-blink::mojom::InterestCohortPtr FlocIdProviderImpl::GetInterestCohortForJsApi(
-    const GURL& url,
-    const absl::optional<url::Origin>& top_frame_origin) const {
-  // Check the general floc setting.
-  if (!IsFlocAllowed())
-    return blink::mojom::InterestCohort::New();
-
-  // Check the context specific floc setting.
-  if (!privacy_sandbox_settings_->IsFlocAllowedForContext(url,
-                                                          top_frame_origin)) {
-    return blink::mojom::InterestCohort::New();
-  }
-
-  if (!floc_id_.IsValid())
-    return blink::mojom::InterestCohort::New();
-
-  return floc_id_.ToInterestCohortForJsApi();
-}
-
-mojom::WebUIFlocStatusPtr FlocIdProviderImpl::GetFlocStatusForWebUi() const {
-  mojom::WebUIFlocStatusPtr status = mojom::WebUIFlocStatus::New();
-
-  if (floc_id_.IsValid()) {
-    status->id = base::NumberToString(floc_id_.ToUint64());
-    status->version = base::StrCat(
-        {"chrome.", base::NumberToString(floc_id_.finch_config_version()), ".",
-         base::NumberToString(floc_id_.sorting_lsh_version())});
-  }
-
-  status->compute_time = floc_id_.compute_time();
-
-  status->feature_pages_with_ad_resources_default_included_in_floc_computation =
-      base::FeatureList::IsEnabled(
-          kFlocPagesWithAdResourcesDefaultIncludedInFlocComputation);
-  status->feature_interest_cohort_api_origin_trial =
-      base::FeatureList::IsEnabled(
-          blink::features::kInterestCohortAPIOriginTrial);
-  status->feature_interest_cohort_feature_policy = base::FeatureList::IsEnabled(
-      blink::features::kInterestCohortFeaturePolicy);
-
-  status->feature_param_scheduled_update_interval =
-      kFlocIdScheduledUpdateInterval.Get();
-  status->feature_param_minimum_history_domain_size_required =
-      kFlocIdMinimumHistoryDomainSizeRequired.Get();
-  status->feature_param_finch_config_version = kFlocIdFinchConfigVersion.Get();
-
-  return status;
-}
-
-void FlocIdProviderImpl::MaybeRecordFlocToUkm(ukm::SourceId source_id) {
-  if (!need_ukm_recording_)
-    return;
-
-  auto* ukm_recorder = ukm::UkmRecorder::Get();
-  ukm::builders::FlocPageLoad builder(source_id);
-
-  if (floc_id_.IsValid())
-    builder.SetFlocId(floc_id_.ToUint64());
-
-  builder.Record(ukm_recorder->Get());
-
-  need_ukm_recording_ = false;
-}
-
-base::Time FlocIdProviderImpl::GetApproximateNextComputeTime() const {
-  if (!compute_floc_timer_.IsRunning())
-    return base::Time::Now();
-
-  // Convert the TimeTicks type the timer provides to base::Time.
-  return base::Time::Now() +
-         (compute_floc_timer_.desired_run_time() - base::TimeTicks::Now());
-}
-
-void FlocIdProviderImpl::OnComputeFlocCompleted(ComputeFlocResult result) {
-  DCHECK(floc_computation_in_progress_);
-  floc_computation_in_progress_ = false;
-
-  // History-delete event came in when this computation was in progress. Ignore
-  // this computation completely and recompute.
-  if (need_recompute_) {
-    need_recompute_ = false;
-    ComputeFloc();
-    return;
-  }
-
-  LogFlocComputedEvent(result);
-
-  floc_id_ = result.floc_id;
-  floc_id_.SaveToPrefs(prefs_);
-
-  need_ukm_recording_ = true;
-
-  ScheduleFlocComputation(kFlocIdScheduledUpdateInterval.Get());
-}
-
-void FlocIdProviderImpl::LogFlocComputedEvent(const ComputeFlocResult& result) {
-  floc_event_logger_->LogFlocComputedEvent(
-      FlocEventLogger::Event{result.sim_hash_computed, result.sim_hash,
-                             result.floc_id.compute_time()});
-}
-
-void FlocIdProviderImpl::Shutdown() {
-  privacy_sandbox_settings_->RemoveObserver(this);
-  history_service_observation_.Reset();
-  g_browser_process->floc_sorting_lsh_clusters_service()->RemoveObserver(this);
-}
-
-void FlocIdProviderImpl::OnFlocDataAccessibleSinceUpdated(
-    bool reset_compute_timer) {
-  // Set the |need_recompute_| flag so that we will recompute the floc
-  // immediately after the in-progress one finishes, so as to avoid potential
-  // data races. This function maybe have been called in response to a user
-  // deliberately resetting floc, in this case the recomputed floc should be
-  // invalid as the floc-accessible timestamp was just updated to now. The
-  // floc computation is fast so it's exceedingly unlikely to populate enough
-  // history for the recomputed ID to be valid between one floc calculation and
-  // the next.
-  if (floc_computation_in_progress_) {
-    need_recompute_ = true;
-    return;
-  }
-
-  // Clear any pending computes and re-schedule if requested.
-  if (reset_compute_timer) {
-    compute_floc_timer_.AbandonAndStop();
-    ScheduleFlocComputation(kFlocIdScheduledUpdateInterval.Get());
-    floc_id_.ResetComputeTimeAndSaveToPrefs(base::Time::Now(), prefs_);
-  }
-
-  // Note: we only invalidate the floc rather than recomputing, because we don't
-  // want the floc to change more frequently than the scheduled update rate.
-
-  // No-op if the floc is already invalid.
-  if (!floc_id_.IsValid())
-    return;
-
-  // Invalidate the floc if the new floc-accessible-since time is greater than
-  // the begin time of the history used to compute the current floc.
-  if (privacy_sandbox_settings_->FlocDataAccessibleSince() >
-      floc_id_.history_begin_time()) {
-    floc_id_.UpdateStatusAndSaveToPrefs(prefs_, FlocId::Status::kInvalidReset);
-  }
-}
-
-void FlocIdProviderImpl::OnURLsDeleted(
-    history::HistoryService* history_service,
-    const history::DeletionInfo& deletion_info) {
-  // Set the |need_recompute_| flag so that we will recompute the floc
-  // immediately after the in-progress one finishes, so as to avoid potential
-  // data races.
-  if (floc_computation_in_progress_) {
-    need_recompute_ = true;
-    return;
-  }
-
-  if (!floc_id_.IsValid())
-    return;
-
-  // Only invalidate the floc if it's delete-all or if the time range overlaps
-  // with the time range of the history used to compute the current floc.
-  if (!deletion_info.IsAllHistory() && !deletion_info.time_range().IsValid()) {
-    return;
-  }
-
-  if (deletion_info.time_range().begin() > floc_id_.history_end_time() ||
-      deletion_info.time_range().end() < floc_id_.history_begin_time()) {
-    return;
-  }
-
-  // We log the invalidation event although it's technically not a recompute.
-  // It'd give us a better idea how often the floc is invalidated due to
-  // history-delete.
-  LogFlocComputedEvent(
-      ComputeFlocResult(FlocId::Status::kInvalidHistoryDeleted));
-
-  floc_id_.UpdateStatusAndSaveToPrefs(prefs_,
-                                      FlocId::Status::kInvalidHistoryDeleted);
-}
-
-void FlocIdProviderImpl::OnSortingLshClustersFileReady() {
-  // If the floc computation is happening now or is scheduled, no-op; otherwise,
-  // we want to trigger a computation as soon as the sorting-lsh file is loaded.
-  if (floc_computation_in_progress_ || compute_floc_timer_.IsRunning())
-    return;
-
-  ComputeFloc();
-}
-
-void FlocIdProviderImpl::ComputeFloc() {
-  DCHECK(!floc_computation_in_progress_);
-
-  floc_computation_in_progress_ = true;
-
-  auto compute_floc_completed_callback =
-      base::BindOnce(&FlocIdProviderImpl::OnComputeFlocCompleted,
-                     weak_ptr_factory_.GetWeakPtr());
-
-  CheckCanComputeFloc(
-      base::BindOnce(&FlocIdProviderImpl::OnCheckCanComputeFlocCompleted,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     std::move(compute_floc_completed_callback)));
-}
-
-void FlocIdProviderImpl::CheckCanComputeFloc(CanComputeFlocCallback callback) {
-  if (!IsFlocAllowed()) {
-    std::move(callback).Run(false);
-    return;
-  }
-
-  std::move(callback).Run(true);
-}
-
-void FlocIdProviderImpl::OnCheckCanComputeFlocCompleted(
-    ComputeFlocCompletedCallback callback,
-    bool can_compute_floc) {
-  if (!can_compute_floc) {
-    std::move(callback).Run(
-        ComputeFlocResult(FlocId::Status::kInvalidDisallowedByUserSettings));
-    return;
-  }
-
-  GetRecentlyVisitedURLs(
-      base::BindOnce(&FlocIdProviderImpl::OnGetRecentlyVisitedURLsCompleted,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
-}
-
-bool FlocIdProviderImpl::IsFlocAllowed() const {
-  return privacy_sandbox_settings_->IsFlocAllowed();
-}
-
-void FlocIdProviderImpl::GetRecentlyVisitedURLs(
-    GetRecentlyVisitedURLsCallback callback) {
-  base::Time now = base::Time::Now();
-
-  history::QueryOptions options;
-  options.begin_time =
-      std::max(privacy_sandbox_settings_->FlocDataAccessibleSince(),
-               now - base::Days(kQueryHistoryWindowInDays));
-  options.end_time = now;
-  options.duplicate_policy = history::QueryOptions::KEEP_ALL_DUPLICATES;
-
-  history_service_->QueryHistory(std::u16string(), options, std::move(callback),
-                                 &history_task_tracker_);
-}
-
-void FlocIdProviderImpl::OnGetRecentlyVisitedURLsCompleted(
-    ComputeFlocCompletedCallback callback,
-    history::QueryResults results) {
-  std::unordered_set<std::string> domains;
-
-  base::Time history_begin_time = base::Time::Max();
-  base::Time history_end_time = base::Time::Min();
-
-  for (const history::URLResult& url_result : results) {
-    if (!(url_result.content_annotations().annotation_flags &
-          history::VisitContentAnnotationFlag::kFlocEligibleRelaxed)) {
-      continue;
-    }
-
-    if (url_result.visit_time() < history_begin_time)
-      history_begin_time = url_result.visit_time();
-
-    if (url_result.visit_time() > history_end_time)
-      history_end_time = url_result.visit_time();
-
-    domains.insert(net::registry_controlled_domains::GetDomainAndRegistry(
-        url_result.url(),
-        net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
-  }
-
-  if (domains.size() <
-      static_cast<size_t>(kFlocIdMinimumHistoryDomainSizeRequired.Get())) {
-    std::move(callback).Run(ComputeFlocResult(
-        FlocId::Status::kInvalidNotEnoughElgibleHistoryDomains));
-    return;
-  }
-
-  uint64_t sim_hash = FlocId::SimHashHistory(domains);
-
-  // Apply the sorting-lsh post processing to compute the final versioned floc.
-  // The final floc may be invalid if the file is corrupted or the floc is in
-  // the block list.
-  g_browser_process->floc_sorting_lsh_clusters_service()->ApplySortingLsh(
-      sim_hash,
-      base::BindOnce(&FlocIdProviderImpl::DidApplySortingLshPostProcessing,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback),
-                     sim_hash, history_begin_time, history_end_time));
-}
-
-void FlocIdProviderImpl::DidApplySortingLshPostProcessing(
-    ComputeFlocCompletedCallback callback,
-    uint64_t sim_hash,
-    base::Time history_begin_time,
-    base::Time history_end_time,
-    absl::optional<uint64_t> final_hash,
-    base::Version version) {
-  if (!final_hash) {
-    std::move(callback).Run(ComputeFlocResult(
-        sim_hash, FlocId::CreateInvalid(FlocId::Status::kInvalidBlocked)));
-    return;
-  }
-
-  std::move(callback).Run(ComputeFlocResult(
-      sim_hash,
-      FlocId::CreateValid(final_hash.value(), history_begin_time,
-                          history_end_time, version.components().front())));
-}
-
-void FlocIdProviderImpl::ScheduleFlocComputation(base::TimeDelta delay) {
-  compute_floc_timer_.Start(FROM_HERE, delay,
-                            base::BindOnce(&FlocIdProviderImpl::ComputeFloc,
-                                           weak_ptr_factory_.GetWeakPtr()));
-}
-
-}  // namespace federated_learning
diff --git a/chrome/browser/federated_learning/floc_id_provider_impl.h b/chrome/browser/federated_learning/floc_id_provider_impl.h
deleted file mode 100644
index 78350ddf..0000000
--- a/chrome/browser/federated_learning/floc_id_provider_impl.h
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2020 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_FEDERATED_LEARNING_FLOC_ID_PROVIDER_IMPL_H_
-#define CHROME_BROWSER_FEDERATED_LEARNING_FLOC_ID_PROVIDER_IMPL_H_
-
-#include "base/gtest_prod_util.h"
-#include "base/memory/raw_ptr.h"
-#include "base/scoped_observation.h"
-#include "base/task/cancelable_task_tracker.h"
-#include "base/timer/timer.h"
-#include "chrome/browser/federated_learning/floc_id_provider.h"
-#include "components/federated_learning/floc_sorting_lsh_clusters_service.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/history/core/browser/history_service_observer.h"
-#include "components/privacy_sandbox/privacy_sandbox_settings.h"
-
-namespace federated_learning {
-
-class FlocEventLogger;
-
-// A service that regularly computes the floc id and logs it in a user event.
-//
-// For the first browser session of a profile, we'll start computing the floc
-// after the sorting-lsh file is loaded, and another computation will be
-// scheduled every X days. When the browser shuts down and starts up again, it
-// can remember the last state and can still schedule the computation at X days
-// after the last compute time. If we've missed a scheduled update due to the
-// browser not being alive, it'll compute after the next session starts, using
-// the sorting-lsh-file-loaded as the first compute triggering condition.
-//
-// The floc will be computed by:
-// Step 1: sim-hashing navigation URL domains in the last 7 days. This step aims
-// to group together users with similar browsing habit.
-// Step 2: applying the sorting-lsh post processing to the sim-hash value. The
-// sorting-lsh technique groups similar sim-hash values together to ensure the
-// smallest group size / K-anonymity. The mappings / group-size is computed
-// server side in chrome-sync, based on logged sim-hash data, and is pushed to
-// Chrome on a regular basis through the component updater.
-//
-// A computed floc will be valid if:
-// - 3rd party cookies are NOT blocked.
-// - There are at least 3 *eligible* history entries in the last 7 days, where
-// eligible means the IP was publicly routable.
-// - It's not blocked by the sorting-lsh (with encoded blocklist) file.
-//
-// If some of those conditions are not met, an invalid floc will be given.
-//
-// In the event of history deletion, the floc will be invalidated immediately if
-// the time range of the deletion overlaps with the time range used to compute
-// the existing floc. In the event of cookie deletion, the floc will always be
-// invalidated. Note that we only invalidate the floc rather than recomputing,
-// because we don't want the floc to change more frequently than the scheduled
-// update rate (% rare cases such as when the finch version param has changed
-// indicating a new algorithm / experiment, a recompute will be needed).
-class FlocIdProviderImpl : public FlocIdProvider,
-                           public FlocSortingLshClustersService::Observer,
-                           public PrivacySandboxSettings::Observer,
-                           public history::HistoryServiceObserver {
- public:
-  struct ComputeFlocResult {
-    explicit ComputeFlocResult(FlocId::Status status)
-        : floc_id(FlocId::CreateInvalid(status)) {}
-
-    ComputeFlocResult(uint64_t sim_hash, const FlocId& floc_id)
-        : sim_hash_computed(true), sim_hash(sim_hash), floc_id(floc_id) {}
-
-    bool sim_hash_computed = false;
-
-    // Sim-hash of the browsing history. This is the baseline value where the
-    // |floc_id| field should be derived from. We'll log this field for the
-    // server to calculate the sorting-lsh cutting points.
-    uint64_t sim_hash = 0;
-
-    // The floc to be exposed to JS API. It's derived from applying the
-    // sorting-lsh & blocklist post-processing on the |sim_hash|.
-    FlocId floc_id;
-  };
-
-  using CanComputeFlocCallback = base::OnceCallback<void(bool)>;
-  using ComputeFlocCompletedCallback =
-      base::OnceCallback<void(ComputeFlocResult)>;
-  using GetRecentlyVisitedURLsCallback =
-      history::HistoryService::QueryHistoryCallback;
-
-  FlocIdProviderImpl(PrefService* prefs,
-                     PrivacySandboxSettings* privacy_sandbox_settings,
-                     history::HistoryService* history_service,
-                     std::unique_ptr<FlocEventLogger> floc_event_logger);
-  ~FlocIdProviderImpl() override;
-  FlocIdProviderImpl(const FlocIdProviderImpl&) = delete;
-  FlocIdProviderImpl& operator=(const FlocIdProviderImpl&) = delete;
-
-  blink::mojom::InterestCohortPtr GetInterestCohortForJsApi(
-      const GURL& url,
-      const absl::optional<url::Origin>& top_frame_origin) const override;
-
-  mojom::WebUIFlocStatusPtr GetFlocStatusForWebUi() const override;
-
-  void MaybeRecordFlocToUkm(ukm::SourceId source_id) override;
-
-  base::Time GetApproximateNextComputeTime() const override;
-
- protected:
-  // protected virtual for testing.
-  virtual void OnComputeFlocCompleted(ComputeFlocResult result);
-  virtual void LogFlocComputedEvent(const ComputeFlocResult& result);
-
- private:
-  friend class FlocIdProviderUnitTest;
-  friend class FlocIdProviderBrowserTest;
-
-  // KeyedService:
-  void Shutdown() override;
-
-  // PrivacySandboxSettings::Observer
-
-  // When the floc-accessible-since time is updated (due to e.g. cookies
-  // deletion), we'll either invalidate or keep using the floc. This will
-  // depend on the updated time and the begin time of the history used to
-  // compute the current floc. If |reset_compute_timer| is true the timer to
-  // re-compute the floc is reset.
-  void OnFlocDataAccessibleSinceUpdated(bool reset_compute_timer) override;
-
-  // On history deletion, we'll either invalidate or keep using the floc. This
-  // will depend on the deletion type and the time range.
-  void OnURLsDeleted(history::HistoryService* history_service,
-                     const history::DeletionInfo& deletion_info) override;
-
-  // FlocSortingLshClustersService::Observer
-  void OnSortingLshClustersFileReady() override;
-
-  void ComputeFloc();
-
-  void CheckCanComputeFloc(CanComputeFlocCallback callback);
-  void OnCheckCanComputeFlocCompleted(ComputeFlocCompletedCallback callback,
-                                      bool can_compute_floc);
-
-  bool IsSyncHistoryEnabled() const;
-  bool IsFlocAllowed() const;
-
-  void IsSwaaNacAccountEnabled(CanComputeFlocCallback callback);
-
-  void GetRecentlyVisitedURLs(GetRecentlyVisitedURLsCallback callback);
-  void OnGetRecentlyVisitedURLsCompleted(ComputeFlocCompletedCallback callback,
-                                         history::QueryResults results);
-
-  void DidApplySortingLshPostProcessing(ComputeFlocCompletedCallback callback,
-                                        uint64_t sim_hash,
-                                        base::Time history_begin_time,
-                                        base::Time history_end_time,
-                                        absl::optional<uint64_t> final_hash,
-                                        base::Version version);
-
-  // Abandon any scheduled task, and schedule a new compute-floc task with
-  // |delay|.
-  void ScheduleFlocComputation(base::TimeDelta delay);
-
-  // The following raw pointer references are guaranteed to outlive this object.
-  // |prefs_| is owned by Profile, and it won't be destroyed until the
-  // destructor of Profile is called, where all the profile-keyed services
-  // including this object will be destroyed. Other services are all created by
-  // profile-keyed service factories, and the dependency declared in
-  // FlocIdProviderFactory::FlocIdProviderFactory() guarantees that this object
-  // will be destroyed first among those services.
-  raw_ptr<PrefService> prefs_;
-  raw_ptr<PrivacySandboxSettings> privacy_sandbox_settings_;
-  raw_ptr<history::HistoryService> history_service_;
-
-  std::unique_ptr<FlocEventLogger> floc_event_logger_;
-
-  // The id to be exposed to the JS API. It will always be in sync with the one
-  // stored in prefs.
-  FlocId floc_id_;
-
-  // When a floc is computed, we'll record it to the UKM on the next page load.
-  // This flag controls whether the recording is needed. Caveat: given that this
-  // info does not persist across browser sessions, we could miss the recording
-  // when the floc is computed and then the browser is closed before the next
-  // page load occurs.
-  bool need_ukm_recording_ = false;
-
-  bool floc_computation_in_progress_ = false;
-
-  // True if history-delete occurs during an in-progress computation. When the
-  // in-progress one finishes, we would disregard the result (i.e. no loggings
-  // or floc update), and compute again. Potentially we could maintain extra
-  // states to tell if the history-delete would have impact on the in-progress
-  // result, but since this would only happen in rare race situations, we just
-  // always recompute to keep things simple.
-  bool need_recompute_ = false;
-
-  // Used for the async tasks querying the HistoryService.
-  base::CancelableTaskTracker history_task_tracker_;
-
-  // The timer used to schedule a floc computation.
-  base::OneShotTimer compute_floc_timer_;
-
-  base::ScopedObservation<history::HistoryService,
-                          history::HistoryServiceObserver>
-      history_service_observation_{this};
-
-  base::WeakPtrFactory<FlocIdProviderImpl> weak_ptr_factory_{this};
-};
-
-}  // namespace federated_learning
-
-#endif  // CHROME_BROWSER_FEDERATED_LEARNING_FLOC_ID_PROVIDER_IMPL_H_
diff --git a/chrome/browser/federated_learning/floc_id_provider_unittest.cc b/chrome/browser/federated_learning/floc_id_provider_unittest.cc
deleted file mode 100644
index 90b3befc..0000000
--- a/chrome/browser/federated_learning/floc_id_provider_unittest.cc
+++ /dev/null
@@ -1,1565 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_id_provider_impl.h"
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/raw_ptr.h"
-#include "base/strings/strcat.h"
-#include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
-#include "build/build_config.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/federated_learning/floc_event_logger.h"
-#include "chrome/browser/ui/webui/federated_learning/floc_internals.mojom.h"
-#include "chrome/common/chrome_features.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "chrome/test/base/testing_profile.h"
-#include "components/content_settings/core/browser/content_settings_registry.h"
-#include "components/content_settings/core/browser/cookie_settings.h"
-#include "components/content_settings/core/common/pref_names.h"
-#include "components/federated_learning/features/features.h"
-#include "components/federated_learning/floc_constants.h"
-#include "components/history/core/browser/history_database_params.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/history/core/test/test_history_database.h"
-#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
-#include "components/privacy_sandbox/privacy_sandbox_settings.h"
-#include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "components/ukm/test_ukm_recorder.h"
-#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/test_utils.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
-
-namespace federated_learning {
-
-namespace {
-
-using ComputeFlocResult = FlocIdProviderImpl::ComputeFlocResult;
-using ComputeFlocCompletedCallback =
-    FlocIdProviderImpl::ComputeFlocCompletedCallback;
-using CanComputeFlocCallback = FlocIdProviderImpl::CanComputeFlocCallback;
-
-class MockFlocSortingLshService : public FlocSortingLshClustersService {
- public:
-  using FlocSortingLshClustersService::FlocSortingLshClustersService;
-  using MappingFunction =
-      base::RepeatingCallback<absl::optional<uint64_t>(uint64_t)>;
-
-  // Configure the version and the mapping function and trigger the file-ready
-  // event. If |mapping_function| is not provided, it will map any input
-  // sim-hash to the same number.
-  void ConfigureSortingLsh(base::Version version,
-                           MappingFunction mapping_function =
-                               base::BindRepeating([](uint64_t sim_hash) {
-                                 return absl::optional<uint64_t>(sim_hash);
-                               })) {
-    version_ = version;
-    mapping_function_ = mapping_function;
-
-    OnSortingLshClustersFileReady(base::FilePath(), version);
-  }
-
-  void ApplySortingLsh(uint64_t sim_hash,
-                       ApplySortingLshCallback callback) override {
-    DCHECK(mapping_function_);
-    std::move(callback).Run(mapping_function_.Run(sim_hash), version_);
-  }
-
- private:
-  base::Version version_;
-  MappingFunction mapping_function_;
-};
-
-class MockFlocIdProvider : public FlocIdProviderImpl {
- public:
-  using FlocIdProviderImpl::FlocIdProviderImpl;
-
-  void OnComputeFlocCompleted(ComputeFlocResult result) override {
-    if (should_pause_before_compute_floc_completed_) {
-      DCHECK(!paused_);
-      paused_ = true;
-      paused_result_ = result;
-      return;
-    }
-
-    ++compute_floc_completed_count_;
-    FlocIdProviderImpl::OnComputeFlocCompleted(result);
-  }
-
-  void ContinueLastOnComputeFlocCompleted() {
-    DCHECK(paused_);
-    paused_ = false;
-    ++compute_floc_completed_count_;
-    FlocIdProviderImpl::OnComputeFlocCompleted(paused_result_);
-  }
-
-  void LogFlocComputedEvent(const ComputeFlocResult& result) override {
-    ++log_event_count_;
-    last_log_event_result_ = result;
-  }
-
-  size_t compute_floc_completed_count() const {
-    return compute_floc_completed_count_;
-  }
-
-  void set_should_pause_before_compute_floc_completed(bool should_pause) {
-    should_pause_before_compute_floc_completed_ = should_pause;
-  }
-
-  ComputeFlocResult paused_result() const {
-    DCHECK(paused_);
-    return paused_result_;
-  }
-
-  size_t log_event_count() const { return log_event_count_; }
-
-  ComputeFlocResult last_log_event_result() const {
-    DCHECK_LT(0u, log_event_count_);
-    return last_log_event_result_;
-  }
-
- private:
-  base::OnceCallback<void()> callback_before_compute_floc_completed_;
-
-  // Add the support to be able to pause on the OnComputeFlocCompleted
-  // execution and let it yield to other tasks posted to the same task runner.
-  bool should_pause_before_compute_floc_completed_ = false;
-  bool paused_ = false;
-  ComputeFlocResult paused_result_{FlocId::Status::kInvalidWaitingToStart};
-
-  size_t compute_floc_completed_count_ = 0u;
-  size_t log_event_count_ = 0u;
-  ComputeFlocResult last_log_event_result_{
-      FlocId::Status::kInvalidWaitingToStart};
-};
-
-}  // namespace
-
-// Used to create a floc id with non-current finch_config_version or
-// compute_time.
-class FlocIdTester {
- public:
-  static FlocId Create(uint64_t id,
-                       FlocId::Status status,
-                       base::Time history_begin_time,
-                       base::Time history_end_time,
-                       uint32_t finch_config_version,
-                       uint32_t sorting_lsh_version,
-                       base::Time compute_time) {
-    return FlocId(id, status, history_begin_time, history_end_time,
-                  finch_config_version, sorting_lsh_version, compute_time);
-  }
-};
-
-class FlocIdProviderUnitTest : public testing::Test {
- public:
-  FlocIdProviderUnitTest()
-      : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
-
-  FlocIdProviderUnitTest(const FlocIdProviderUnitTest&) = delete;
-  FlocIdProviderUnitTest& operator=(const FlocIdProviderUnitTest&) = delete;
-
-  ~FlocIdProviderUnitTest() override = default;
-
-  void SetUp() override {
-    FlocId::RegisterPrefs(prefs_.registry());
-    privacy_sandbox::RegisterProfilePrefs(prefs_.registry());
-
-    EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
-
-    content_settings::ContentSettingsRegistry::GetInstance()->ResetForTest();
-    content_settings::CookieSettings::RegisterProfilePrefs(prefs_.registry());
-    HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
-    settings_map_ = new HostContentSettingsMap(
-        &prefs_, /*is_off_the_record=*/false, /*store_last_modified=*/false,
-        /*restore_session=*/false);
-
-    auto sorting_lsh_service = std::make_unique<MockFlocSortingLshService>();
-    sorting_lsh_service_ = sorting_lsh_service.get();
-    TestingBrowserProcess::GetGlobal()->SetFlocSortingLshClustersService(
-        std::move(sorting_lsh_service));
-
-    history_service_ = std::make_unique<history::HistoryService>();
-    history_service_->Init(
-        history::TestHistoryDatabaseParamsForPath(temp_dir_.GetPath()));
-
-    cookie_settings_ =
-        new content_settings::CookieSettings(settings_map_.get(), &prefs_,
-                                             /*is_incognito=*/false);
-
-    privacy_sandbox_settings_ = std::make_unique<PrivacySandboxSettings>(
-        settings_map_.get(), cookie_settings_, &prefs_);
-
-    task_environment_.RunUntilIdle();
-  }
-
-  void InitializeFlocIdProvider() {
-    floc_id_provider_ = std::make_unique<MockFlocIdProvider>(
-        &prefs_, privacy_sandbox_settings_.get(), history_service_.get(),
-        nullptr);
-  }
-
-  void InitializeFlocIdProviderAndSortingLsh(
-      base::Version version,
-      MockFlocSortingLshService::MappingFunction mapping_function =
-          base::BindRepeating([](uint64_t sim_hash) {
-            return absl::optional<uint64_t>(sim_hash);
-          })) {
-    InitializeFlocIdProvider();
-    sorting_lsh_service_->ConfigureSortingLsh(version, mapping_function);
-  }
-
-  void TearDown() override {
-    TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
-    settings_map_->ShutdownOnUIThread();
-    history_service_->RemoveObserver(floc_id_provider_.get());
-  }
-
-  void CheckCanComputeFloc(CanComputeFlocCallback callback) {
-    floc_id_provider_->CheckCanComputeFloc(std::move(callback));
-  }
-
-  void OnFlocDataAccessibleSinceUpdated(bool reset_compute_timer) {
-    floc_id_provider_->OnFlocDataAccessibleSinceUpdated(reset_compute_timer);
-  }
-
-  void OnURLsDeleted(history::HistoryService* history_service,
-                     const history::DeletionInfo& deletion_info) {
-    floc_id_provider_->OnURLsDeleted(history_service, deletion_info);
-  }
-
-  void OnGetRecentlyVisitedURLsCompleted(history::QueryResults results) {
-    auto compute_floc_completed_callback =
-        base::BindOnce(&FlocIdProviderImpl::OnComputeFlocCompleted,
-                       base::Unretained(floc_id_provider_.get()));
-
-    floc_id_provider_->OnGetRecentlyVisitedURLsCompleted(
-        std::move(compute_floc_completed_callback), std::move(results));
-  }
-
-  void AddHistoryEntriesForDomains(const std::vector<std::string>& domains,
-                                   base::Time time) {
-    history::HistoryAddPageArgs add_page_args;
-    add_page_args.time = time;
-    add_page_args.context_id = reinterpret_cast<history::ContextID>(1);
-
-    for (const std::string& domain : domains) {
-      static int nav_entry_id = 0;
-      ++nav_entry_id;
-
-      add_page_args.url = GURL(base::StrCat({"https://www.", domain}));
-      add_page_args.nav_entry_id = nav_entry_id;
-
-      history_service_->AddPage(add_page_args);
-      history_service_->SetFlocAllowed(add_page_args.context_id, nav_entry_id,
-                                       add_page_args.url);
-    }
-  }
-
-  void ExpireHistoryBeforeUninclusive(base::Time end_time) {
-    base::CancelableTaskTracker tracker;
-    base::RunLoop run_loop;
-    history_service_->ExpireHistoryBetween(
-        /*restrict_urls=*/{}, /*begin_time=*/base::Time(), end_time,
-        /*user_initiated=*/true, run_loop.QuitClosure(), &tracker);
-    run_loop.Run();
-  }
-
-  FlocId floc_id() const { return floc_id_provider_->floc_id_; }
-
-  void set_floc_id(const FlocId& floc_id) {
-    floc_id_provider_->floc_id_ = floc_id;
-  }
-
-  bool floc_computation_in_progress() const {
-    return floc_id_provider_->floc_computation_in_progress_;
-  }
-
-  void set_floc_computation_in_progress(bool floc_computation_in_progress) {
-    floc_id_provider_->floc_computation_in_progress_ =
-        floc_computation_in_progress;
-  }
-
-  bool floc_computation_scheduled() const {
-    return floc_id_provider_->compute_floc_timer_.IsRunning();
-  }
-
-  bool need_recompute() { return floc_id_provider_->need_recompute_; }
-
- protected:
-  base::test::ScopedFeatureList feature_list_;
-
-  content::BrowserTaskEnvironment task_environment_;
-
-  sync_preferences::TestingPrefServiceSyncable prefs_;
-  scoped_refptr<HostContentSettingsMap> settings_map_;
-
-  std::unique_ptr<history::HistoryService> history_service_;
-  scoped_refptr<content_settings::CookieSettings> cookie_settings_;
-  std::unique_ptr<PrivacySandboxSettings> privacy_sandbox_settings_;
-  std::unique_ptr<MockFlocIdProvider> floc_id_provider_;
-
-  raw_ptr<MockFlocSortingLshService> sorting_lsh_service_;
-
-  base::ScopedTempDir temp_dir_;
-};
-
-TEST_F(FlocIdProviderUnitTest, DefaultSetup_ComputationState) {
-  // Initializing the floc provider should not trigger an immediate computation,
-  // as the sorting-lsh file is not ready.
-  InitializeFlocIdProvider();
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_FALSE(floc_computation_scheduled());
-  EXPECT_EQ(base::Time::Now(),
-            floc_id_provider_->GetApproximateNextComputeTime());
-
-  // Configure the sorting-lsh service to to trigger the 1st floc computation.
-  sorting_lsh_service_->ConfigureSortingLsh(base::Version("2.0.0"));
-  EXPECT_TRUE(floc_computation_in_progress());
-  EXPECT_FALSE(floc_computation_scheduled());
-  EXPECT_EQ(base::Time::Now(),
-            floc_id_provider_->GetApproximateNextComputeTime());
-
-  // Finish any outstanding history queries.
-  task_environment_.RunUntilIdle();
-
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-  EXPECT_EQ(base::Time::Now() + base::Days(7),
-            floc_id_provider_->GetApproximateNextComputeTime());
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-
-  // Advance the clock by 7 days. Expect another computation.
-  task_environment_.FastForwardBy(base::Days(7));
-
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-  EXPECT_EQ(2u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(2u, floc_id_provider_->log_event_count());
-}
-
-TEST_F(FlocIdProviderUnitTest, DefaultSetup_BelowMinimumHistoryDomainSize) {
-  const base::Time kSevenDaysBeforeStart = base::Time::Now() - base::Days(7);
-
-  AddHistoryEntriesForDomains({"foo.com", "bar.com"}, kSevenDaysBeforeStart);
-
-  // Initializing the floc provider and sorting-lsh service should trigger the
-  // 1st floc computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  // Expect that the 1st computation has completed with an invalid floc, due
-  // to insufficient history domains.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidNotEnoughElgibleHistoryDomains,
-            floc_id().status());
-}
-
-TEST_F(FlocIdProviderUnitTest, DefaultSetup_MinimumHistoryDomainSize) {
-  const base::Time kSevenDaysBeforeStart = base::Time::Now() - base::Days(7);
-
-  AddHistoryEntriesForDomains({"foo.com", "bar.com", "baz.com"},
-                              kSevenDaysBeforeStart);
-
-  // Initializing the floc provider and sorting-lsh service should trigger the
-  // 1st floc computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  // Expect that the 1st computation has completed with the expected floc.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_EQ(FlocId::CreateValid(
-                FlocId::SimHashHistory({"foo.com", "bar.com", "baz.com"}),
-                kSevenDaysBeforeStart, kSevenDaysBeforeStart, 2),
-            floc_id());
-}
-
-TEST_F(FlocIdProviderUnitTest, DefaultSetup_ScheduledUpdateInterval) {
-  const base::Time kSevenDaysBeforeStart = base::Time::Now() - base::Days(7);
-
-  AddHistoryEntriesForDomains({"foo.com", "bar.com", "baz.com"},
-                              kSevenDaysBeforeStart);
-
-  // Initializing the floc provider and sorting-lsh service should trigger the
-  // 1st floc computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  // Expect that the 1st computation has completed.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_EQ(FlocId::CreateValid(
-                FlocId::SimHashHistory({"foo.com", "bar.com", "baz.com"}),
-                kSevenDaysBeforeStart, kSevenDaysBeforeStart, 2),
-            floc_id());
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-
-  // Advance the clock by 6 days.
-  task_environment_.FastForwardBy(base::Days(6));
-
-  // Add 3 history entries with a new set of domains.
-  const base::Time kSixDaysAfterStart = base::Time::Now();
-  AddHistoryEntriesForDomains({"bar.com", "baz.com", "qux.com"},
-                              kSixDaysAfterStart);
-
-  task_environment_.RunUntilIdle();
-
-  // Advance the clock by 23 hours. Expect no more computation, as the floc id
-  // refresh interval is 7 days.
-  task_environment_.FastForwardBy(base::Hours(23));
-
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-
-  // Advance the clock by 1 hour. Expect one more computation.
-  task_environment_.FastForwardBy(base::Hours(1));
-
-  EXPECT_EQ(2u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(2u, floc_id_provider_->log_event_count());
-
-  EXPECT_EQ(FlocId::CreateValid(
-                FlocId::SimHashHistory({"bar.com", "baz.com", "qux.com"}),
-                kSixDaysAfterStart, kSixDaysAfterStart, 2),
-            floc_id());
-}
-
-class FlocIdProviderSimpleFeatureParamUnitTest : public FlocIdProviderUnitTest {
- public:
-  FlocIdProviderSimpleFeatureParamUnitTest() {
-    feature_list_.Reset();
-    feature_list_.InitWithFeaturesAndParameters(
-        {{kFederatedLearningOfCohorts,
-          {{"update_interval", "24h"},
-           {"minimum_history_domain_size_required", "1"}}}},
-        {});
-  }
-};
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest, QualifiedInitialHistory) {
-  const base::Time kTime = base::Time::Now() - base::Days(7);
-
-  AddHistoryEntriesForDomains({"foo.com"}, kTime);
-
-  // Initializing the floc provider and sorting-lsh service should trigger the
-  // 1st floc computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  // Expect that the 1st computation has completed.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_EQ(
-      FlocId::CreateValid(FlocId::SimHashHistory({"foo.com"}), kTime, kTime, 2),
-      floc_id());
-  EXPECT_TRUE(floc_id_provider_->last_log_event_result().sim_hash_computed);
-  EXPECT_EQ(FlocId::SimHashHistory({"foo.com"}),
-            floc_id_provider_->last_log_event_result().sim_hash);
-  EXPECT_EQ(base::Time::Now(),
-            floc_id_provider_->last_log_event_result().floc_id.compute_time());
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-
-  // Advance the clock by 1 day. Expect a computation, as there's no history in
-  // the last 7 days so the id has been reset to empty.
-  task_environment_.FastForwardBy(base::Days(1));
-
-  EXPECT_EQ(2u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(2u, floc_id_provider_->log_event_count());
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidNotEnoughElgibleHistoryDomains,
-            floc_id().status());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest, UnqualifiedInitialHistory) {
-  AddHistoryEntriesForDomains({"foo.com"}, base::Time::Now() - base::Days(8));
-
-  // Initializing the floc provider and sorting-lsh service should trigger the
-  // 1st floc computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  // Expect that the 1st computation has completed.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-
-  const base::Time kTime = base::Time::Now() - base::Days(6);
-  AddHistoryEntriesForDomains({"foo.com"}, kTime);
-
-  // Advance the clock by 23 hours. Expect no more computation, as the id
-  // refresh interval is 24 hours.
-  task_environment_.FastForwardBy(base::Hours(23));
-
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-
-  // Advance the clock by 1 hour. Expect one more computation, as the refresh
-  // time is reached and there's a valid history entry in the last 7 days.
-  task_environment_.FastForwardBy(base::Hours(1));
-
-  EXPECT_EQ(2u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(2u, floc_id_provider_->log_event_count());
-
-  EXPECT_EQ(
-      FlocId::CreateValid(FlocId::SimHashHistory({"foo.com"}), kTime, kTime, 2),
-      floc_id());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       HistoryQueryBoundedByFlocAccessibleSince) {
-  const base::Time kStartTime = base::Time::Now();
-  const base::Time kSevenDaysBeforeStart = kStartTime - base::Days(7);
-  const base::Time kSixDaysBeforeStart = kStartTime - base::Days(6);
-
-  prefs_.SetTime(prefs::kPrivacySandboxFlocDataAccessibleSince,
-                 kSixDaysBeforeStart);
-
-  AddHistoryEntriesForDomains({"foo.com"}, kSevenDaysBeforeStart);
-  AddHistoryEntriesForDomains({"bar.com"}, kSixDaysBeforeStart);
-
-  // Initializing the floc provider and sorting-lsh service should trigger the
-  // 1st floc computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  // Expect that the 1st computation has completed.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-
-  // Expected that floc is calculated from only "bar.com".
-  EXPECT_EQ(FlocId::CreateValid(FlocId::SimHashHistory({"bar.com"}),
-                                kSixDaysBeforeStart, kSixDaysBeforeStart, 2),
-            floc_id());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       FlocAccessibleSinceViolationOnStartup) {
-  const base::Time kStartTime = base::Time::Now();
-  const base::Time kSevenDaysBeforeStart = kStartTime - base::Days(7);
-  const base::Time kSixDaysBeforeStart = kStartTime - base::Days(6);
-  const base::Time kTwelveHoursBeforeStart = kStartTime - base::Hours(12);
-
-  FlocId floc_id_in_prefs_before_start =
-      FlocIdTester::Create(123, FlocId::Status::kValid, kSevenDaysBeforeStart,
-                           kSixDaysBeforeStart, 1, 0, kTwelveHoursBeforeStart);
-  floc_id_in_prefs_before_start.SaveToPrefs(&prefs_);
-
-  prefs_.SetTime(prefs::kPrivacySandboxFlocDataAccessibleSince,
-                 kSixDaysBeforeStart);
-
-  AddHistoryEntriesForDomains({"foo.com"}, kSevenDaysBeforeStart);
-  AddHistoryEntriesForDomains({"bar.com"}, kSixDaysBeforeStart);
-
-  // Initializing the floc provider and sorting-lsh service should invalidate
-  // the previous floc but should not trigger an immediate computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_FALSE(FlocId::ReadFromPrefs(&prefs_).IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidReset, floc_id().status());
-  EXPECT_EQ(FlocId::Status::kInvalidReset,
-            FlocId::ReadFromPrefs(&prefs_).status());
-
-  // Fast forward by 12 hours. This should trigger a scheduled update.
-  task_environment_.FastForwardBy(base::Hours(12));
-
-  // Expect a completed computation and an update to the local prefs.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-
-  EXPECT_EQ(floc_id(),
-            FlocId::CreateValid(FlocId::SimHashHistory({"bar.com"}),
-                                kSixDaysBeforeStart, kSixDaysBeforeStart, 2));
-  EXPECT_EQ(floc_id(), FlocId::ReadFromPrefs(&prefs_));
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       HistoryDeleteAndScheduledUpdate) {
-  const base::Time kStartTime = base::Time::Now();
-  const base::Time kSevenDaysBeforeStart = kStartTime - base::Days(7);
-  const base::Time kSixDaysBeforeStart = kStartTime - base::Days(6);
-
-  AddHistoryEntriesForDomains({"foo.com"}, kSevenDaysBeforeStart);
-  AddHistoryEntriesForDomains({"bar.com"}, kSixDaysBeforeStart);
-
-  // Initializing the floc provider and sorting-lsh service should trigger the
-  // 1st floc computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  // Expect that the 1st computation has completed.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_EQ(FlocId::CreateValid(FlocId::SimHashHistory({"foo.com", "bar.com"}),
-                                kSevenDaysBeforeStart, kSixDaysBeforeStart, 2),
-            floc_id());
-
-  // Advance the clock by 12 hours. Expect no more computation.
-  task_environment_.FastForwardBy(base::Hours(12));
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-
-  // Expire the oldest history entry.
-  ExpireHistoryBeforeUninclusive(kSixDaysBeforeStart);
-  task_environment_.RunUntilIdle();
-
-  // Expect that the floc has been invalidated. Expect no more floc computation,
-  // but one more logging.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(2u, floc_id_provider_->log_event_count());
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidHistoryDeleted, floc_id().status());
-
-  // Advance the clock by 12 hours. Expect one more computation, which implies
-  // the timer didn't get reset due to the history invalidation. Expect that
-  // the floc is derived from "bar.com".
-  task_environment_.FastForwardBy(base::Hours(12));
-  EXPECT_EQ(2u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(3u, floc_id_provider_->log_event_count());
-  EXPECT_EQ(FlocId::CreateValid(FlocId::SimHashHistory({"bar.com"}),
-                                kSixDaysBeforeStart, kSixDaysBeforeStart, 2),
-            floc_id());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest, ScheduledUpdateSameFloc) {
-  const base::Time kTime = base::Time::Now() - base::Days(2);
-
-  AddHistoryEntriesForDomains({"foo.com"}, kTime);
-
-  // Initializing the floc provider and sorting-lsh service should trigger the
-  // 1st floc computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  // Expect that the 1st computation has completed.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_EQ(
-      FlocId::CreateValid(FlocId::SimHashHistory({"foo.com"}), kTime, kTime, 2),
-      floc_id());
-
-  // Advance the clock by 1 day. Expect one more computation, but the floc
-  // didn't change.
-  task_environment_.FastForwardBy(base::Days(1));
-
-  EXPECT_EQ(2u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(2u, floc_id_provider_->log_event_count());
-  EXPECT_EQ(
-      FlocId::CreateValid(FlocId::SimHashHistory({"foo.com"}), kTime, kTime, 2),
-      floc_id());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       CheckCanComputeFloc_Default_Success) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  base::OnceCallback<void(bool)> cb = base::BindOnce(
-      [](bool can_compute_floc) { EXPECT_TRUE(can_compute_floc); });
-
-  CheckCanComputeFloc(std::move(cb));
-  task_environment_.RunUntilIdle();
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       CheckCanComputeFloc_Failure_PrivacySandboxDisabled) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  privacy_sandbox_settings_->SetPrivacySandboxEnabled(false);
-
-  base::OnceCallback<void(bool)> cb = base::BindOnce(
-      [](bool can_compute_floc) { EXPECT_FALSE(can_compute_floc); });
-
-  CheckCanComputeFloc(std::move(cb));
-  task_environment_.RunUntilIdle();
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       FlocComputationDisallowedByUserSettings) {
-  privacy_sandbox_settings_->SetPrivacySandboxEnabled(false);
-
-  // Initializing the floc provider and sorting-lsh service should trigger the
-  // 1st floc computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  // Expect that the 1st computation has completed with an invalid floc, due
-  // to insufficient history domains.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidDisallowedByUserSettings,
-            floc_id().status());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       OnFlocDataAccessibleSinceUpdated_TimeRangeNotFullyCovered) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  const base::Time kTime1 = base::Time::FromTimeT(1);
-  const base::Time kTime2 = base::Time::FromTimeT(2);
-
-  set_floc_id(FlocId::CreateValid(123, kTime1, kTime2, 2));
-
-  prefs_.SetTime(prefs::kPrivacySandboxFlocDataAccessibleSince, kTime2);
-  OnFlocDataAccessibleSinceUpdated(/*reset_compute_timer=*/false);
-
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidReset, floc_id().status());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       OnFlocDataAccessibleSinceUpdated_TimeRangeFullyCovered) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  const base::Time kTime1 = base::Time::FromTimeT(1);
-  const base::Time kTime2 = base::Time::FromTimeT(2);
-
-  set_floc_id(FlocId::CreateValid(123, kTime1, kTime2, 2));
-
-  prefs_.SetTime(prefs::kPrivacySandboxFlocDataAccessibleSince, kTime1);
-  OnFlocDataAccessibleSinceUpdated(/*reset_compute_timer=*/false);
-
-  EXPECT_TRUE(floc_id().IsValid());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       OnFlocDataAccessibeSinceUpdated_ResetComputeTimer) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(base::Time::Now(), FlocId::ReadFromPrefs(&prefs_).compute_time());
-  EXPECT_EQ(base::Time::Now() + base::Days(1),
-            floc_id_provider_->GetApproximateNextComputeTime());
-
-  // Move the clock forward 20 hours and update the floc available time,
-  // selecting to reset the compute timer.
-  task_environment_.FastForwardBy(base::Hours(20));
-  OnFlocDataAccessibleSinceUpdated(/*reset_compute_timer=*/true);
-  const base::Time kResetComputeTime = base::Time::Now();
-  EXPECT_EQ(kResetComputeTime, FlocId::ReadFromPrefs(&prefs_).compute_time());
-  EXPECT_EQ(base::Time::Now() + base::Days(1),
-            floc_id_provider_->GetApproximateNextComputeTime());
-
-  // Move the clock forward another 20 hours, moving past the default refresh
-  // interval of 24 hours. A new floc id should not have been computed as the
-  // timer was reset.
-  task_environment_.FastForwardBy(base::Hours(20));
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(base::Time::Now() + base::Hours(4),
-            floc_id_provider_->GetApproximateNextComputeTime());
-
-  // Update the floc available time without resetting compute time.
-  OnFlocDataAccessibleSinceUpdated(
-      /*reset_compute_timer=*/false);
-  EXPECT_EQ(kResetComputeTime, FlocId::ReadFromPrefs(&prefs_).compute_time());
-  EXPECT_EQ(base::Time::Now() + base::Hours(4),
-            floc_id_provider_->GetApproximateNextComputeTime());
-
-  // Move the clock forward 5 hours, making 25 hours since the compute timer was
-  // reset, a new floc id should have been computed.
-  task_environment_.FastForwardBy(base::Hours(5));
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(2u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(base::Time::Now() + base::Hours(23),
-            floc_id_provider_->GetApproximateNextComputeTime());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest, HistoryDelete_AllHistory) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  const base::Time kTime1 = base::Time::FromTimeT(1);
-  const base::Time kTime2 = base::Time::FromTimeT(2);
-
-  set_floc_id(FlocId::CreateValid(123, kTime1, kTime2, 2));
-
-  OnURLsDeleted(history_service_.get(), history::DeletionInfo::ForAllHistory());
-
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidHistoryDeleted, floc_id().status());
-
-  // Check the logged event for history-delete.
-  EXPECT_FALSE(floc_id_provider_->last_log_event_result().sim_hash_computed);
-  EXPECT_EQ(0u, floc_id_provider_->last_log_event_result().sim_hash);
-  EXPECT_EQ(base::Time::Now(),
-            floc_id_provider_->last_log_event_result().floc_id.compute_time());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       HistoryDelete_InvalidTimeRange) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  const base::Time kTime1 = base::Time::FromTimeT(1);
-  const base::Time kTime2 = base::Time::FromTimeT(2);
-
-  GURL url_a = GURL("https://a.test");
-
-  history::URLResult url_result(url_a, kTime1);
-  url_result.set_content_annotations(
-      {history::VisitContentAnnotationFlag::kFlocEligibleRelaxed,
-       /*model_annotations=*/{}, /*related_searches=*/{}});
-
-  history::QueryResults query_results;
-  query_results.SetURLResults({url_result});
-
-  const FlocId expected_floc = FlocId::CreateValid(
-      FlocId::SimHashHistory({"a.test"}), kTime1, kTime2, 2);
-
-  set_floc_id(expected_floc);
-
-  OnURLsDeleted(history_service_.get(),
-                history::DeletionInfo::ForUrls(
-                    {history::URLResult(url_a, kTime1)}, /*favicon_urls=*/{}));
-
-  EXPECT_EQ(expected_floc, floc_id());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       HistoryDelete_TimeRangeNoOverlap) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  const base::Time kTime1 = base::Time::FromTimeT(1);
-  const base::Time kTime2 = base::Time::FromTimeT(2);
-  const base::Time kTime3 = base::Time::FromTimeT(3);
-  const base::Time kTime4 = base::Time::FromTimeT(4);
-
-  const FlocId expected_floc = FlocId::CreateValid(
-      FlocId::SimHashHistory({"a.test"}), kTime1, kTime2, 2);
-
-  set_floc_id(expected_floc);
-
-  history::DeletionInfo deletion_info(
-      history::DeletionTimeRange(kTime3, kTime4),
-      /*is_from_expiration=*/false, /*deleted_rows=*/{}, /*favicon_urls=*/{},
-      /*restrict_urls=*/absl::nullopt);
-  OnURLsDeleted(history_service_.get(), deletion_info);
-
-  EXPECT_EQ(expected_floc, floc_id());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       HistoryDelete_TimeRangePartialOverlap) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  const base::Time kTime1 = base::Time::FromTimeT(1);
-  const base::Time kTime2 = base::Time::FromTimeT(2);
-  const base::Time kTime3 = base::Time::FromTimeT(3);
-
-  const FlocId expected_floc = FlocId::CreateValid(
-      FlocId::SimHashHistory({"a.test"}), kTime1, kTime2, 2);
-
-  set_floc_id(expected_floc);
-
-  history::DeletionInfo deletion_info(
-      history::DeletionTimeRange(kTime2, kTime3),
-      /*is_from_expiration=*/false, /*deleted_rows=*/{}, /*favicon_urls=*/{},
-      /*restrict_urls=*/absl::nullopt);
-  OnURLsDeleted(history_service_.get(), deletion_info);
-
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidHistoryDeleted, floc_id().status());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       HistoryDelete_TimeRangeFullOverlap) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  const base::Time kTime1 = base::Time::FromTimeT(1);
-  const base::Time kTime2 = base::Time::FromTimeT(2);
-
-  const FlocId expected_floc = FlocId::CreateValid(
-      FlocId::SimHashHistory({"a.test"}), kTime1, kTime2, 2);
-
-  set_floc_id(expected_floc);
-
-  history::DeletionInfo deletion_info(
-      history::DeletionTimeRange(kTime1, kTime2),
-      /*is_from_expiration=*/false, /*deleted_rows=*/{}, /*favicon_urls=*/{},
-      /*restrict_urls=*/absl::nullopt);
-  OnURLsDeleted(history_service_.get(), deletion_info);
-
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidHistoryDeleted, floc_id().status());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest, FlocIneligibleHistoryEntries) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  history::QueryResults query_results;
-  query_results.SetURLResults({history::URLResult(
-      GURL("https://a.test"), base::Time::Now() - base::Days(1))});
-
-  set_floc_computation_in_progress(true);
-
-  OnGetRecentlyVisitedURLsCompleted(std::move(query_results));
-
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidNotEnoughElgibleHistoryDomains,
-            floc_id().status());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest, MultipleHistoryEntries) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  const base::Time kTime1 = base::Time::FromTimeT(1);
-  const base::Time kTime2 = base::Time::FromTimeT(2);
-  const base::Time kTime3 = base::Time::FromTimeT(3);
-
-  history::URLResult url_result_a(GURL("https://a.test"), kTime1);
-  url_result_a.set_content_annotations(
-      {history::VisitContentAnnotationFlag::kFlocEligibleRelaxed,
-       /*model_annotations=*/{}, /*related_searches=*/{}});
-
-  history::URLResult url_result_b(GURL("https://b.test"), kTime2);
-  url_result_b.set_content_annotations(
-      {history::VisitContentAnnotationFlag::kFlocEligibleRelaxed,
-       /*model_annotations=*/{}, /*related_searches=*/{}});
-
-  history::URLResult url_result_c(GURL("https://c.test"), kTime3);
-
-  std::vector<history::URLResult> url_results{url_result_a, url_result_b,
-                                              url_result_c};
-
-  history::QueryResults query_results;
-  query_results.SetURLResults(std::move(url_results));
-
-  set_floc_computation_in_progress(true);
-
-  OnGetRecentlyVisitedURLsCompleted(std::move(query_results));
-
-  EXPECT_EQ(FlocId::CreateValid(FlocId::SimHashHistory({"a.test", "b.test"}),
-                                kTime1, kTime2, 2),
-            floc_id());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       MaybeRecordFlocToUkmMethod_FilteredRecording) {
-  ukm::TestAutoSetUkmRecorder ukm_recorder;
-
-  InitializeFlocIdProvider();
-
-  floc_id_provider_->MaybeRecordFlocToUkm(1);
-
-  // Initially the |need_ukm_recording_| is false. The recording attempt should
-  // have been filtered. Expect no events.
-  auto entries =
-      ukm_recorder.GetEntriesByName(ukm::builders::FlocPageLoad::kEntryName);
-  EXPECT_EQ(0u, entries.size());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       MaybeRecordFlocToUkmMethod_RecordInvalidFloc) {
-  ukm::TestAutoSetUkmRecorder ukm_recorder;
-
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-
-  floc_id_provider_->OnComputeFlocCompleted(ComputeFlocResult(
-      FlocId::Status::kInvalidNotEnoughElgibleHistoryDomains));
-  floc_id_provider_->MaybeRecordFlocToUkm(1);
-
-  // Expect an event with a missing metric, meaning the floc id is invalid.
-  auto entries =
-      ukm_recorder.GetEntriesByName(ukm::builders::FlocPageLoad::kEntryName);
-  EXPECT_EQ(1u, entries.size());
-  EXPECT_FALSE(ukm_recorder.EntryHasMetric(
-      entries.back(), ukm::builders::FlocPageLoad::kFlocIdName));
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       MaybeRecordFlocToUkmMethod_RecordValidFloc) {
-  ukm::TestAutoSetUkmRecorder ukm_recorder;
-
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-
-  floc_id_provider_->OnComputeFlocCompleted(ComputeFlocResult(
-      /*sim_hash=*/123,
-      FlocIdTester::Create(123, FlocId::Status::kValid,
-                           base::Time::FromTimeT(4), base::Time::FromTimeT(5),
-                           6, 7, base::Time::FromTimeT(8))));
-  floc_id_provider_->MaybeRecordFlocToUkm(1);
-
-  // Expect an event with a metric having the expected floc value.
-  auto entries =
-      ukm_recorder.GetEntriesByName(ukm::builders::FlocPageLoad::kEntryName);
-  EXPECT_EQ(1u, entries.size());
-  ukm_recorder.ExpectEntryMetric(entries.back(),
-                                 ukm::builders::FlocPageLoad::kFlocIdName,
-                                 /*expected_value=*/123);
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       MaybeRecordFlocToUkmMethod_MultipleRecordings) {
-  ukm::TestAutoSetUkmRecorder ukm_recorder;
-
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-
-  floc_id_provider_->OnComputeFlocCompleted(ComputeFlocResult(
-      /*sim_hash=*/123,
-      FlocIdTester::Create(123, FlocId::Status::kValid,
-                           base::Time::FromTimeT(4), base::Time::FromTimeT(5),
-                           6, 7, base::Time::FromTimeT(8))));
-  floc_id_provider_->MaybeRecordFlocToUkm(1);
-
-  auto entries =
-      ukm_recorder.GetEntriesByName(ukm::builders::FlocPageLoad::kEntryName);
-  EXPECT_EQ(1u, entries.size());
-
-  // Subsequent recoding attempt will be filtered as the last recording has set
-  // |need_ukm_recording_| to false.
-  floc_id_provider_->MaybeRecordFlocToUkm(1);
-  entries =
-      ukm_recorder.GetEntriesByName(ukm::builders::FlocPageLoad::kEntryName);
-  EXPECT_EQ(1u, entries.size());
-
-  // Trigger a new floc computation completion.
-  set_floc_computation_in_progress(true);
-  floc_id_provider_->OnComputeFlocCompleted(ComputeFlocResult(
-      /*sim_hash=*/456,
-      FlocIdTester::Create(456, FlocId::Status::kValid,
-                           base::Time::FromTimeT(4), base::Time::FromTimeT(5),
-                           6, 7, base::Time::FromTimeT(8))));
-  floc_id_provider_->MaybeRecordFlocToUkm(1);
-
-  // The new recording attempt should have succeeded.
-  entries =
-      ukm_recorder.GetEntriesByName(ukm::builders::FlocPageLoad::kEntryName);
-  EXPECT_EQ(2u, entries.size());
-  ukm_recorder.ExpectEntryMetric(entries.back(),
-                                 ukm::builders::FlocPageLoad::kFlocIdName,
-                                 /*expected_value=*/456);
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest, GetFlocStatusForWebUiMethod) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("999.0.0"));
-  task_environment_.RunUntilIdle();
-
-  const base::Time kTime = base::Time::Now() - base::Days(1);
-  set_floc_id(FlocId::CreateValid(123, kTime, kTime, 999));
-
-  mojom::WebUIFlocStatusPtr status = floc_id_provider_->GetFlocStatusForWebUi();
-  EXPECT_EQ(status->id, "123");
-  EXPECT_EQ(status->version, "chrome.1.999");
-  EXPECT_EQ(status->compute_time, base::Time::Now());
-  EXPECT_EQ(
-      status
-          ->feature_pages_with_ad_resources_default_included_in_floc_computation,
-      false);
-  EXPECT_EQ(status->feature_interest_cohort_api_origin_trial, false);
-  EXPECT_EQ(status->feature_interest_cohort_feature_policy, false);
-  EXPECT_EQ(status->feature_param_scheduled_update_interval, base::Days(1));
-  EXPECT_EQ(status->feature_param_minimum_history_domain_size_required, 1);
-  EXPECT_EQ(status->feature_param_finch_config_version, 1);
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       GetInterestCohortForJsApiMethod) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("999.0.0"));
-  task_environment_.RunUntilIdle();
-
-  const base::Time kTime = base::Time::Now() - base::Days(1);
-  const FlocId expected_floc = FlocId::CreateValid(123, kTime, kTime, 999);
-
-  set_floc_id(expected_floc);
-
-  EXPECT_EQ(expected_floc.ToInterestCohortForJsApi(),
-            floc_id_provider_->GetInterestCohortForJsApi(
-                /*requesting_origin=*/{}, /*site_for_cookies=*/{}));
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       GetInterestCohortForJsApiMethod_PrivacySandboxDisabled) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("999.0.0"));
-  task_environment_.RunUntilIdle();
-
-  privacy_sandbox_settings_->SetPrivacySandboxEnabled(false);
-
-  const base::Time kTime = base::Time::Now() - base::Days(1);
-
-  set_floc_id(FlocId::CreateValid(123, kTime, kTime, 999));
-
-  EXPECT_EQ(blink::mojom::InterestCohort::New(),
-            floc_id_provider_->GetInterestCohortForJsApi(
-                /*requesting_origin=*/{}, /*site_for_cookies=*/{}));
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       GetInterestCohortForJsApiMethod_FlocUnavailable) {
-  InitializeFlocIdProviderAndSortingLsh(base::Version("2.0.0"));
-  task_environment_.RunUntilIdle();
-
-  EXPECT_EQ(blink::mojom::InterestCohort::New(),
-            floc_id_provider_->GetInterestCohortForJsApi(
-                /*requesting_origin=*/{}, /*site_for_cookies=*/{}));
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       HistoryDeleteDuringInProgressComputation) {
-  const base::Time kStartTime = base::Time::Now();
-  const base::Time kSevenDaysBeforeStart = kStartTime - base::Days(7);
-  const base::Time kSixDaysBeforeStart = kStartTime - base::Days(6);
-  const base::Time kFiveDaysBeforeStart = kStartTime - base::Days(5);
-
-  AddHistoryEntriesForDomains({"foo.com"}, kSevenDaysBeforeStart);
-  AddHistoryEntriesForDomains({"bar.com"}, kSixDaysBeforeStart);
-  AddHistoryEntriesForDomains({"baz.com"}, kFiveDaysBeforeStart);
-
-  // Initializing the floc provider and sorting-lsh service should trigger the
-  // 1st floc computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("999.0.0"));
-  task_environment_.RunUntilIdle();
-
-  // Expect that the 1st computation has completed.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_TRUE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::CreateValid(
-                FlocId::SimHashHistory({"foo.com", "bar.com", "baz.com"}),
-                kSevenDaysBeforeStart, kFiveDaysBeforeStart, 999),
-            floc_id());
-
-  base::Time time_before_advancing = base::Time::Now();
-
-  // Advance the clock by 1 day. The "foo.com" should expire. However, we pause
-  // before the computation completes.
-  floc_id_provider_->set_should_pause_before_compute_floc_completed(true);
-  task_environment_.FastForwardBy(base::Days(1));
-
-  EXPECT_TRUE(floc_computation_in_progress());
-  EXPECT_EQ(base::Time::Now(),
-            floc_id_provider_->GetApproximateNextComputeTime());
-  EXPECT_FALSE(need_recompute());
-  EXPECT_EQ(FlocIdTester::Create(
-                FlocId::SimHashHistory({"foo.com", "bar.com", "baz.com"}),
-                FlocId::Status::kValid, kSevenDaysBeforeStart,
-                kFiveDaysBeforeStart, 1, 999, time_before_advancing),
-            floc_id());
-  EXPECT_EQ(FlocId::CreateValid(FlocId::SimHashHistory({"bar.com", "baz.com"}),
-                                kSixDaysBeforeStart, kFiveDaysBeforeStart, 999),
-            floc_id_provider_->paused_result().floc_id);
-
-  // Expire the "bar.com" history entry right before the floc computation
-  // completes. Since the computation is still considered to be in-progress, we
-  // will recompute right after this computation completes.
-  ExpireHistoryBeforeUninclusive(kFiveDaysBeforeStart);
-
-  EXPECT_TRUE(need_recompute());
-
-  floc_id_provider_->set_should_pause_before_compute_floc_completed(false);
-  floc_id_provider_->ContinueLastOnComputeFlocCompleted();
-  task_environment_.RunUntilIdle();
-
-  // Expect 2 more compute completion events and 1 more log event. This is
-  // because we won't send log event if there's a recompute event scheduled.
-  // The compute trigger should be the original trigger (i.e. kScheduledUpdate),
-  // rather than kHistoryDelete.
-  EXPECT_EQ(3u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(2u, floc_id_provider_->log_event_count());
-  EXPECT_FALSE(need_recompute());
-  EXPECT_EQ(base::Time::Now() + base::Days(1),
-            floc_id_provider_->GetApproximateNextComputeTime());
-
-  // The final floc should be derived from "baz.com".
-  EXPECT_TRUE(floc_id().IsValid());
-  EXPECT_EQ(
-      FlocId::CreateValid(FlocId::SimHashHistory({"baz.com"}),
-                          kFiveDaysBeforeStart, kFiveDaysBeforeStart, 999),
-      floc_id());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest, NonDefaultSortingLshMapping) {
-  const base::Time kTime = base::Time::Now() - base::Days(7);
-
-  AddHistoryEntriesForDomains({"foo.com"}, kTime);
-
-  // Map the sim-hash to 2
-  InitializeFlocIdProviderAndSortingLsh(
-      base::Version("99.0.0"), base::BindRepeating([](uint64_t sim_hash) {
-        if (sim_hash == FlocId::SimHashHistory({"foo.com"}))
-          return absl::optional<uint64_t>(2);
-        return absl::optional<uint64_t>();
-      }));
-
-  task_environment_.RunUntilIdle();
-
-  EXPECT_EQ(FlocId::CreateValid(2, kTime, kTime, 99), floc_id());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       NonDefaultSortingLshMapping_Blocked) {
-  const base::Time kTime = base::Time::Now() - base::Days(7);
-
-  AddHistoryEntriesForDomains({"foo.com"}, kTime);
-
-  // Block the sim-hash.
-  InitializeFlocIdProviderAndSortingLsh(
-      base::Version("999.0.0"), base::BindRepeating([](uint64_t sim_hash) {
-        return absl::optional<uint64_t>();
-      }));
-
-  task_environment_.RunUntilIdle();
-
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidBlocked, floc_id().status());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest, MultipleSortingLshUpdate) {
-  const base::Time kTime = base::Time::Now() - base::Days(1);
-
-  AddHistoryEntriesForDomains({"foo.com"}, kTime);
-
-  // Initializing the floc provider and sorting-lsh service should trigger the
-  // 1st floc computation.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("99.0.0"));
-  task_environment_.RunUntilIdle();
-
-  // Expect a computation. The floc should be equal to the sim-hash.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(1u, floc_id_provider_->log_event_count());
-  EXPECT_EQ(FlocId::CreateValid(FlocId::SimHashHistory({"foo.com"}), kTime,
-                                kTime, 99),
-            floc_id());
-
-  // Configure the |sorting_lsh_service_| to block any input sim-hash.
-  sorting_lsh_service_->ConfigureSortingLsh(
-      base::Version("3.4.5"), base::BindRepeating([](uint64_t sim_hash) {
-        return absl::optional<uint64_t>();
-      }));
-
-  task_environment_.FastForwardBy(base::Days(1));
-
-  // Expect one more computation, where the result contains a valid sim_hash and
-  // an invalid floc_id, as it was blocked. The internal floc is set to the
-  // invalid one.
-  EXPECT_EQ(2u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(2u, floc_id_provider_->log_event_count());
-  EXPECT_TRUE(floc_id_provider_->last_log_event_result().sim_hash_computed);
-  EXPECT_EQ(floc_id_provider_->last_log_event_result().sim_hash,
-            FlocId::SimHashHistory({"foo.com"}));
-  EXPECT_FALSE(floc_id_provider_->last_log_event_result().floc_id.IsValid());
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidBlocked, floc_id().status());
-
-  // Configure the |sorting_lsh_service_| to map sim-hash to 6789.
-  sorting_lsh_service_->ConfigureSortingLsh(
-      base::Version("999.0"), base::BindRepeating([](uint64_t sim_hash) {
-        if (sim_hash == FlocId::SimHashHistory({"foo.com"}))
-          return absl::optional<uint64_t>(6789);
-        return absl::optional<uint64_t>();
-      }));
-
-  task_environment_.FastForwardBy(base::Days(1));
-
-  // Expect one more computation. The floc should be equal to 6789.
-  EXPECT_EQ(3u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(3u, floc_id_provider_->log_event_count());
-  EXPECT_EQ(FlocId::CreateValid(6789, kTime, kTime, 999), floc_id());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       LastFlocUnexpired_NextScheduledUpdate) {
-  // Setups before session start.
-  const base::Time kStartTime = base::Time::Now();
-  const base::Time kFourDaysBeforeStart = kStartTime - base::Days(4);
-  const base::Time kThreeDaysBeforeStart = kStartTime - base::Days(3);
-  const base::Time kLastComputeTime = kStartTime - base::Hours(12);
-
-  FlocId floc_id_in_prefs_before_start =
-      FlocIdTester::Create(123, FlocId::Status::kValid, kFourDaysBeforeStart,
-                           kThreeDaysBeforeStart, 1, 999, kLastComputeTime);
-  floc_id_in_prefs_before_start.SaveToPrefs(&prefs_);
-
-  AddHistoryEntriesForDomains({"domain1.com"}, kFourDaysBeforeStart);
-  AddHistoryEntriesForDomains({"domain2.com"}, kThreeDaysBeforeStart);
-
-  // Start of session.
-  InitializeFlocIdProvider();
-
-  // Initially the floc is set to the entry from the prefs. No computation has
-  // occurred for this session.
-  EXPECT_EQ(floc_id(), floc_id_in_prefs_before_start);
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-  EXPECT_EQ(0u, floc_id_provider_->compute_floc_completed_count());
-
-  // Finish any outstanding history queries.
-  task_environment_.RunUntilIdle();
-
-  // Expect that the floc prefs hasn't changed at this stage.
-  EXPECT_EQ(floc_id(), FlocId::ReadFromPrefs(&prefs_));
-
-  // Set up the sorting-lsh service so that the next computation will compute a
-  // valid floc.
-  sorting_lsh_service_->ConfigureSortingLsh(base::Version("99.0"));
-
-  // Fast forward by 12 hours. This should trigger a scheduled update.
-  task_environment_.FastForwardBy(base::Hours(12));
-
-  // Expect a completed computation and an update to the local prefs.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(floc_id(),
-            FlocId::CreateValid(
-                FlocId::SimHashHistory({"domain1.com", "domain2.com"}),
-                kFourDaysBeforeStart, kThreeDaysBeforeStart, 99));
-
-  EXPECT_EQ(floc_id(), FlocId::ReadFromPrefs(&prefs_));
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       LastFlocUnexpired_HistoryDelete) {
-  // Setups before session start.
-  const base::Time kStartTime = base::Time::Now();
-  const base::Time kFourDaysBeforeStart = kStartTime - base::Days(4);
-  const base::Time kThreeDaysBeforeStart = kStartTime - base::Days(3);
-  const base::Time kLastComputeTime = kStartTime - base::Hours(12);
-
-  FlocId floc_id_in_prefs_before_start =
-      FlocIdTester::Create(123, FlocId::Status::kValid, kFourDaysBeforeStart,
-                           kThreeDaysBeforeStart, 1, 999, kLastComputeTime);
-  floc_id_in_prefs_before_start.SaveToPrefs(&prefs_);
-
-  AddHistoryEntriesForDomains({"domain1.com"}, kFourDaysBeforeStart);
-  AddHistoryEntriesForDomains({"domain2.com"}, kThreeDaysBeforeStart);
-
-  // Start of session.
-  InitializeFlocIdProvider();
-
-  // Initially the floc is set to the entry from the prefs. No computation has
-  // occurred for this session.
-  EXPECT_EQ(floc_id(), floc_id_in_prefs_before_start);
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-  EXPECT_EQ(0u, floc_id_provider_->compute_floc_completed_count());
-
-  // Expire all previous history.
-  ExpireHistoryBeforeUninclusive(base::Time::Now());
-
-  // Expect no explicit recompute, but the floc has been invalidated and is
-  // written to the local prefs. The last floc compute time in the pref hasn't
-  // changed.
-  EXPECT_EQ(0u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_FALSE(floc_id().IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidHistoryDeleted, floc_id().status());
-
-  FlocId floc_id_in_prefs = FlocId::ReadFromPrefs(&prefs_);
-  EXPECT_FALSE(floc_id_in_prefs.IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidHistoryDeleted, floc_id_in_prefs.status());
-  EXPECT_EQ(kLastComputeTime, floc_id_in_prefs.compute_time());
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       LastFlocExpired_ImmediateCompute) {
-  // Setups before session start.
-  const base::Time kStartTime = base::Time::Now();
-  const base::Time kTwentyDaysBeforeStart = kStartTime - base::Days(20);
-  const base::Time kNineteenDaysBeforeStart = kStartTime - base::Days(19);
-  const base::Time kTwoDaysBeforeStart = kStartTime - base::Days(2);
-  const base::Time kLastComputeTime = kStartTime - base::Hours(25);
-
-  FlocId floc_id_in_prefs_before_start =
-      FlocIdTester::Create(123, FlocId::Status::kValid, kTwentyDaysBeforeStart,
-                           kNineteenDaysBeforeStart, 1, 888, kLastComputeTime);
-  floc_id_in_prefs_before_start.SaveToPrefs(&prefs_);
-
-  AddHistoryEntriesForDomains({"domain1.com"}, kTwentyDaysBeforeStart);
-  AddHistoryEntriesForDomains({"domain2.com"}, kNineteenDaysBeforeStart);
-  AddHistoryEntriesForDomains({"foo.com"}, kTwoDaysBeforeStart);
-
-  // Start of session.
-  InitializeFlocIdProvider();
-
-  FlocId initial_invalid_floc_id = FlocIdTester::Create(
-      123, FlocId::Status::kInvalidWaitingToStart, kTwentyDaysBeforeStart,
-      kNineteenDaysBeforeStart, 1, 888, kLastComputeTime);
-
-  // Initially the floc is invalidated as the last floc has expired, but other
-  // fields remains unchanged. The invalidation is also written to the prefs.
-  // Expect no immediate computation as the sorting-lsh file is not ready.
-  EXPECT_EQ(floc_id(), initial_invalid_floc_id);
-  EXPECT_EQ(FlocId::ReadFromPrefs(&prefs_), initial_invalid_floc_id);
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_FALSE(floc_computation_scheduled());
-  EXPECT_EQ(0u, floc_id_provider_->compute_floc_completed_count());
-
-  // Set up the sorting-lsh service to trigger the 1st floc computation.
-  sorting_lsh_service_->ConfigureSortingLsh(base::Version("99.0"));
-  task_environment_.RunUntilIdle();
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-
-  // Expect a completed computation and an update to the local prefs.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(floc_id(),
-            FlocId::CreateValid(FlocId::SimHashHistory({"foo.com"}),
-                                kTwoDaysBeforeStart, kTwoDaysBeforeStart, 99));
-  EXPECT_EQ(floc_id(), FlocId::ReadFromPrefs(&prefs_));
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       NextComputeDelayTooBig_ImmediateCompute) {
-  // Setups before session start.
-  const base::Time kStartTime = base::Time::Now();
-  const base::Time kFourDaysBeforeStart = kStartTime - base::Days(4);
-  const base::Time kThreeDaysBeforeStart = kStartTime - base::Days(3);
-  const base::Time kTwoDaysBeforeStart = kStartTime - base::Days(2);
-  const base::Time kLastComputeTime = kStartTime + base::Days(1);
-
-  // Configure the last compute time to be 1 day after the start time, that
-  // emulates the situation when the machine time has changed.
-  FlocId floc_id_in_prefs_before_start =
-      FlocIdTester::Create(123, FlocId::Status::kValid, kFourDaysBeforeStart,
-                           kThreeDaysBeforeStart, 1, 999, kLastComputeTime);
-  floc_id_in_prefs_before_start.SaveToPrefs(&prefs_);
-
-  AddHistoryEntriesForDomains({"foo.com"}, kTwoDaysBeforeStart);
-
-  // Start of session.
-  InitializeFlocIdProvider();
-
-  FlocId initial_invalid_floc_id = FlocIdTester::Create(
-      123, FlocId::Status::kInvalidWaitingToStart, kFourDaysBeforeStart,
-      kThreeDaysBeforeStart, 1, 999, kLastComputeTime);
-
-  // Initially the floc is invalidated as the "presumed next computation delay"
-  // >= "2 x the scheduled update interval", implying the machine time has
-  // changed. Other fields should remain unchanged. The invalidation is also
-  // written to the prefs. Expect no immediate computation as the sorting-lsh
-  // file is not ready.
-  EXPECT_EQ(floc_id(), initial_invalid_floc_id);
-  EXPECT_EQ(FlocId::ReadFromPrefs(&prefs_), initial_invalid_floc_id);
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_FALSE(floc_computation_scheduled());
-  EXPECT_EQ(0u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(base::Time::Now(),
-            floc_id_provider_->GetApproximateNextComputeTime());
-
-  // Set up the sorting-lsh service to trigger the 1st floc computation.
-  sorting_lsh_service_->ConfigureSortingLsh(base::Version("99.0"));
-  task_environment_.RunUntilIdle();
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-  EXPECT_EQ(base::Time::Now() + base::Days(1),
-            floc_id_provider_->GetApproximateNextComputeTime());
-
-  // Expect a completed computation and an update to the local prefs.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(floc_id(),
-            FlocId::CreateValid(FlocId::SimHashHistory({"foo.com"}),
-                                kTwoDaysBeforeStart, kTwoDaysBeforeStart, 99));
-  EXPECT_EQ(floc_id(), FlocId::ReadFromPrefs(&prefs_));
-}
-
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       LastFlocVersionMismatch_ImmediateCompute) {
-  // Setups before session start.
-  const base::Time kStartTime = base::Time::Now();
-  const base::Time kFourDaysBeforeStart = kStartTime - base::Days(4);
-  const base::Time kThreeDaysBeforeStart = kStartTime - base::Days(3);
-  const base::Time kTwoDaysBeforeStart = kStartTime - base::Days(2);
-  const base::Time kLastComputeTime = kStartTime - base::Hours(12);
-
-  // Configure a floc with version finch_config_version 0, that is different
-  // from the current version 1.
-  FlocId floc_id_in_prefs_before_start =
-      FlocIdTester::Create(123, FlocId::Status::kValid, kFourDaysBeforeStart,
-                           kThreeDaysBeforeStart, 0, 999, kLastComputeTime);
-  floc_id_in_prefs_before_start.SaveToPrefs(&prefs_);
-
-  AddHistoryEntriesForDomains({"foo.com"}, kTwoDaysBeforeStart);
-
-  // Start of session.
-  InitializeFlocIdProvider();
-
-  FlocId initial_invalid_floc_id = FlocIdTester::Create(
-      123, FlocId::Status::kInvalidWaitingToStart, kFourDaysBeforeStart,
-      kThreeDaysBeforeStart, 0, 999, kLastComputeTime);
-
-  // Initially the floc is invalidated as the version mismatches, but other
-  // fields remains unchanged. The invalidation is also written to the prefs.
-  // Expect no immediate computation as the sorting-lsh file is not ready.
-  EXPECT_EQ(floc_id(), initial_invalid_floc_id);
-  EXPECT_EQ(FlocId::ReadFromPrefs(&prefs_), initial_invalid_floc_id);
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_FALSE(floc_computation_scheduled());
-  EXPECT_EQ(base::Time::Now(),
-            floc_id_provider_->GetApproximateNextComputeTime());
-  EXPECT_EQ(0u, floc_id_provider_->compute_floc_completed_count());
-
-  // Set up the sorting-lsh service to trigger the 1st floc computation.
-  sorting_lsh_service_->ConfigureSortingLsh(base::Version("99.0"));
-  task_environment_.RunUntilIdle();
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-  EXPECT_EQ(base::Time::Now() + base::Days(1),
-            floc_id_provider_->GetApproximateNextComputeTime());
-
-  // Expect a completed computation and an update to the local prefs.
-  EXPECT_EQ(1u, floc_id_provider_->compute_floc_completed_count());
-  EXPECT_EQ(floc_id(),
-            FlocId::CreateValid(FlocId::SimHashHistory({"foo.com"}),
-                                kTwoDaysBeforeStart, kTwoDaysBeforeStart, 99));
-  EXPECT_EQ(floc_id(), FlocId::ReadFromPrefs(&prefs_));
-}
-
-// This setup is possible after the floc status prefs is just introduced, where
-// the previous invalid reason is unknown.
-TEST_F(FlocIdProviderSimpleFeatureParamUnitTest,
-       UnexpiredComputeTimeAndNoStatusPrefs) {
-  const base::Time kStartTime = base::Time::Now();
-  const base::Time kFourDaysBeforeStart = kStartTime - base::Days(4);
-  const base::Time kThreeDaysBeforeStart = kStartTime - base::Days(3);
-  const base::Time kLastComputeTime = kStartTime - base::Hours(12);
-
-  FlocId floc_id_in_prefs_before_start = FlocIdTester::Create(
-      0, FlocId::Status::kInvalidNoStatusPrefs, kFourDaysBeforeStart,
-      kThreeDaysBeforeStart, 1, 999, kLastComputeTime);
-
-  prefs_.SetTime(kFlocIdHistoryBeginTimePrefKey, kFourDaysBeforeStart);
-  prefs_.SetTime(kFlocIdHistoryEndTimePrefKey, kThreeDaysBeforeStart);
-  prefs_.SetUint64(kFlocIdFinchConfigVersionPrefKey, 1);
-  prefs_.SetUint64(kFlocIdSortingLshVersionPrefKey, 999);
-  prefs_.SetTime(kFlocIdComputeTimePrefKey, kLastComputeTime);
-
-  // Initializing the floc provider and sorting-lsh service should not trigger
-  // the 1st floc computation as the floc compute time is unexpired. The floc
-  // status should also stay the same.
-  InitializeFlocIdProviderAndSortingLsh(base::Version("999.0.0"));
-
-  EXPECT_EQ(floc_id(), floc_id_in_prefs_before_start);
-  EXPECT_FALSE(prefs_.HasPrefPath(kFlocIdStatusPrefKey));
-  EXPECT_FALSE(floc_computation_in_progress());
-  EXPECT_TRUE(floc_computation_scheduled());
-  EXPECT_EQ(kLastComputeTime + base::Days(1),
-            floc_id_provider_->GetApproximateNextComputeTime());
-  EXPECT_EQ(0u, floc_id_provider_->compute_floc_completed_count());
-}
-
-}  // namespace federated_learning
diff --git a/chrome/browser/federated_learning/floc_internals_browsertest.cc b/chrome/browser/federated_learning/floc_internals_browsertest.cc
deleted file mode 100644
index 16cb7da..0000000
--- a/chrome/browser/federated_learning/floc_internals_browsertest.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2021 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/strings/strcat.h"
-#include "base/test/bind.h"
-#include "chrome/browser/federated_learning/floc_id_provider.h"
-#include "chrome/browser/federated_learning/floc_id_provider_factory.h"
-#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/webui/federated_learning/floc_internals.mojom.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "components/embedder_support/switches.h"
-#include "components/federated_learning/features/features.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/page_load_metrics/browser/page_load_metrics_test_waiter.h"
-#include "components/subresource_filter/core/common/test_ruleset_utils.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/test_frame_navigation_observer.h"
-#include "content/public/test/test_host_resolver.h"
-#include "content/public/test/test_navigation_observer.h"
-#include "net/dns/mock_host_resolver.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
-
-namespace {
-
-const char kFlocInternalsUrl[] = "chrome://floc-internals/";
-
-class FixedFlocIdProvider : public federated_learning::FlocIdProvider {
- public:
-  FixedFlocIdProvider() = default;
-  ~FixedFlocIdProvider() override = default;
-
-  blink::mojom::InterestCohortPtr GetInterestCohortForJsApi(
-      const GURL& url,
-      const absl::optional<url::Origin>& top_frame_origin) const override {
-    return nullptr;
-  }
-
-  federated_learning::mojom::WebUIFlocStatusPtr GetFlocStatusForWebUi()
-      const override {
-    return status_->Clone();
-  }
-
-  void MaybeRecordFlocToUkm(ukm::SourceId source_id) override {}
-
-  base::Time GetApproximateNextComputeTime() const override {
-    return base::Time();
-  }
-
-  void SetFlocStatus(federated_learning::mojom::WebUIFlocStatusPtr status) {
-    status_ = std::move(status);
-  }
-
- private:
-  federated_learning::mojom::WebUIFlocStatusPtr status_ =
-      federated_learning::mojom::WebUIFlocStatus::New();
-};
-
-}  //  namespace
-
-class FlocInternalsBrowserTest : public InProcessBrowserTest {
- public:
-  // BrowserTestBase::SetUpInProcessBrowserTestFixture
-  void SetUpInProcessBrowserTestFixture() override {
-    subscription_ =
-        BrowserContextDependencyManager::GetInstance()
-            ->RegisterCreateServicesCallbackForTesting(base::BindRepeating(
-                &FlocInternalsBrowserTest::OnWillCreateBrowserContextServices,
-                base::Unretained(this)));
-  }
-
-  content::WebContents* web_contents() {
-    return browser()->tab_strip_model()->GetActiveWebContents();
-  }
-
-  FixedFlocIdProvider* fixed_floc_id_provider() {
-    return static_cast<FixedFlocIdProvider*>(
-        federated_learning::FlocIdProviderFactory::GetForProfile(
-            browser()->profile()));
-  }
-
-  std::vector<std::string> GetPageContents() {
-    // Executing javascript in the WebUI requires using an isolated world in
-    // which to execute the script because WebUI has a default CSP policy
-    // denying "eval()", which is what EvalJs uses under the hood.
-    return base::SplitString(
-        EvalJs(web_contents()->GetMainFrame(), "document.body.innerText",
-               content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
-               /*world_id=*/1)
-            .ExtractString(),
-        "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-  }
-
- private:
-  void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
-    federated_learning::FlocIdProviderFactory::GetInstance()->SetTestingFactory(
-        context, base::BindRepeating(
-                     &FlocInternalsBrowserTest::CreateFixedFlocIdProvider,
-                     base::Unretained(this)));
-  }
-
-  std::unique_ptr<KeyedService> CreateFixedFlocIdProvider(
-      content::BrowserContext* context) {
-    return std::make_unique<FixedFlocIdProvider>();
-  }
-
-  base::CallbackListSubscription subscription_;
-};
-
-IN_PROC_BROWSER_TEST_F(FlocInternalsBrowserTest, EmptyResponse) {
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kFlocInternalsUrl)));
-
-  std::vector<std::string> content_lines = GetPageContents();
-
-  EXPECT_EQ(12u, content_lines.size());
-  EXPECT_EQ("FLoC Status", content_lines[0]);
-  EXPECT_EQ("id: N/A", content_lines[1]);
-  EXPECT_EQ("version: N/A", content_lines[2]);
-  EXPECT_EQ("last compute time: N/A", content_lines[3]);
-  EXPECT_EQ("Features Enabled Status", content_lines[4]);
-  EXPECT_EQ("FlocPagesWithAdResourcesDefaultIncludedInFlocComputation: false",
-            content_lines[5]);
-  EXPECT_EQ("InterestCohortAPIOriginTrial: false", content_lines[6]);
-  EXPECT_EQ("InterestCohortFeaturePolicy: false", content_lines[7]);
-  EXPECT_EQ("Parameters", content_lines[8]);
-  EXPECT_EQ("FlocIdScheduledUpdateInterval: 0d-0h-0m-0s", content_lines[9]);
-  EXPECT_EQ("FlocIdMinimumHistoryDomainSizeRequired: 0", content_lines[10]);
-  EXPECT_EQ("FlocIdFinchConfigVersion: 0", content_lines[11]);
-}
-
-IN_PROC_BROWSER_TEST_F(FlocInternalsBrowserTest, PopulatedResponse) {
-  federated_learning::mojom::WebUIFlocStatusPtr status =
-      federated_learning::mojom::WebUIFlocStatus::New();
-  status->id = "123";
-  status->version = "chrome.2.1";
-  status->compute_time = base::Time::FromDoubleT(1000);
-  status->feature_pages_with_ad_resources_default_included_in_floc_computation =
-      true;
-  status->feature_interest_cohort_api_origin_trial = false;
-  status->feature_interest_cohort_feature_policy = true;
-  status->feature_param_scheduled_update_interval =
-      base::Days(7) + base::Seconds(1);
-  status->feature_param_minimum_history_domain_size_required = 99;
-  status->feature_param_finch_config_version = 2;
-
-  fixed_floc_id_provider()->SetFlocStatus(std::move(status));
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kFlocInternalsUrl)));
-
-  std::vector<std::string> content_lines = GetPageContents();
-
-  EXPECT_EQ(12u, content_lines.size());
-  EXPECT_EQ("FLoC Status", content_lines[0]);
-  EXPECT_EQ("id: 123", content_lines[1]);
-  EXPECT_EQ("version: chrome.2.1", content_lines[2]);
-
-  // It's hard to test the exact time string as it depends on the locale.
-  EXPECT_NE("last compute time: N/A", content_lines[3]);
-  EXPECT_NE("last compute time: Invalid Date", content_lines[3]);
-
-  EXPECT_EQ("Features Enabled Status", content_lines[4]);
-  EXPECT_EQ("FlocPagesWithAdResourcesDefaultIncludedInFlocComputation: true",
-            content_lines[5]);
-  EXPECT_EQ("InterestCohortAPIOriginTrial: false", content_lines[6]);
-  EXPECT_EQ("InterestCohortFeaturePolicy: true", content_lines[7]);
-  EXPECT_EQ("Parameters", content_lines[8]);
-  EXPECT_EQ("FlocIdScheduledUpdateInterval: 7d-0h-0m-1s", content_lines[9]);
-  EXPECT_EQ("FlocIdMinimumHistoryDomainSizeRequired: 99", content_lines[10]);
-  EXPECT_EQ("FlocIdFinchConfigVersion: 2", content_lines[11]);
-}
-
-IN_PROC_BROWSER_TEST_F(FlocInternalsBrowserTest, ResponseWithExtremeValues) {
-  federated_learning::mojom::WebUIFlocStatusPtr status =
-      federated_learning::mojom::WebUIFlocStatus::New();
-  status->compute_time =
-      base::Time::FromDoubleT(std::numeric_limits<double>::max());
-  status->feature_param_scheduled_update_interval = base::TimeDelta::Max();
-  status->feature_param_minimum_history_domain_size_required =
-      std::numeric_limits<int>::max();
-
-  fixed_floc_id_provider()->SetFlocStatus(std::move(status));
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kFlocInternalsUrl)));
-
-  std::vector<std::string> content_lines = GetPageContents();
-
-  EXPECT_EQ(12u, content_lines.size());
-  EXPECT_EQ("last compute time: Invalid Date", content_lines[3]);
-  EXPECT_EQ("FlocIdScheduledUpdateInterval: +inf", content_lines[9]);
-  EXPECT_EQ("FlocIdMinimumHistoryDomainSizeRequired: 2147483647",
-            content_lines[10]);
-}
-
-IN_PROC_BROWSER_TEST_F(FlocInternalsBrowserTest, ResponseWithEmptyId) {
-  federated_learning::mojom::WebUIFlocStatusPtr status =
-      federated_learning::mojom::WebUIFlocStatus::New();
-  status->version = "chrome.2.1";
-  status->compute_time = base::Time::FromDoubleT(1000);
-
-  fixed_floc_id_provider()->SetFlocStatus(std::move(status));
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kFlocInternalsUrl)));
-
-  std::vector<std::string> content_lines = GetPageContents();
-
-  EXPECT_EQ(12u, content_lines.size());
-  EXPECT_EQ("FLoC Status", content_lines[0]);
-  EXPECT_EQ("id: N/A", content_lines[1]);
-  EXPECT_EQ("version: N/A", content_lines[2]);
-
-  // It's hard to test the exact time string as it depends on the locale.
-  EXPECT_NE("last compute time: N/A", content_lines[3]);
-  EXPECT_NE("last compute time: Invalid Date", content_lines[3]);
-}
diff --git a/chrome/browser/federated_learning/floc_origin_trial_browsertest.cc b/chrome/browser/federated_learning/floc_origin_trial_browsertest.cc
deleted file mode 100644
index 3b151027..0000000
--- a/chrome/browser/federated_learning/floc_origin_trial_browsertest.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2020 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/strings/strcat.h"
-#include "base/test/bind.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "components/embedder_support/switches.h"
-#include "content/public/test/browser_test.h"
-#include "content/public/test/url_loader_interceptor.h"
-#include "third_party/blink/public/common/features.h"
-
-namespace federated_learning {
-
-constexpr char kOriginTrialTestPublicKey[] =
-    "dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=";
-
-constexpr char kBaseDataDir[] = "chrome/test/data/federated_learning";
-
-class FlocOriginTrialBrowserTest : public InProcessBrowserTest {
- public:
-  FlocOriginTrialBrowserTest() {
-    scoped_feature_list_.InitAndEnableFeature(
-        blink::features::kInterestCohortAPIOriginTrial);
-  }
-
-  void SetUpOnMainThread() override {
-    InProcessBrowserTest::SetUpOnMainThread();
-
-    // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since
-    // the origin trial token in the response is associated with a fixed
-    // origin, whereas EmbeddedTestServer serves content on a random port.
-    url_loader_interceptor_ = std::make_unique<content::URLLoaderInterceptor>(
-        base::BindLambdaForTesting(
-            [&](content::URLLoaderInterceptor::RequestParams* params) -> bool {
-              if (params->url_request.url.path_piece() !=
-                  "/interest_cohort_api_origin_trial.html") {
-                return false;
-              }
-
-              content::URLLoaderInterceptor::WriteResponse(
-                  base::StrCat(
-                      {kBaseDataDir, params->url_request.url.path_piece()}),
-                  params->client.get());
-              return true;
-            }));
-  }
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitchASCII(embedder_support::kOriginTrialPublicKey,
-                                    kOriginTrialTestPublicKey);
-  }
-
-  void TearDownOnMainThread() override { url_loader_interceptor_.reset(); }
-
-  bool HasInterestCohortApi(const content::ToRenderFrameHost& adapter) {
-    return EvalJs(adapter, R"(
-      document.interestCohort instanceof Function
-    )")
-        .ExtractBool();
-  }
-
-  GURL OriginTrialEnabledURL() const {
-    return GURL("https://example.test/interest_cohort_api_origin_trial.html");
-  }
-
-  GURL OriginTrialDisabledURL() const {
-    return GURL("https://disabled.test/interest_cohort_api_origin_trial.html");
-  }
-
-  content::WebContents* web_contents() {
-    return browser()->tab_strip_model()->GetActiveWebContents();
-  }
-
- protected:
-  base::test::ScopedFeatureList scoped_feature_list_;
-
- private:
-  std::unique_ptr<content::URLLoaderInterceptor> url_loader_interceptor_;
-};
-
-IN_PROC_BROWSER_TEST_F(FlocOriginTrialBrowserTest, OriginTrialEnabled) {
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), OriginTrialEnabledURL()));
-
-  EXPECT_TRUE(HasInterestCohortApi(web_contents()));
-}
-
-IN_PROC_BROWSER_TEST_F(FlocOriginTrialBrowserTest, OriginTrialDisabled) {
-  ASSERT_TRUE(
-      ui_test_utils::NavigateToURL(browser(), OriginTrialDisabledURL()));
-
-  EXPECT_FALSE(HasInterestCohortApi(web_contents()));
-}
-
-class FlocOriginTrialBrowserTestBaseFeatureDisabled
-    : public FlocOriginTrialBrowserTest {
- public:
-  FlocOriginTrialBrowserTestBaseFeatureDisabled() {
-    scoped_feature_list_.Reset();
-    scoped_feature_list_.InitAndDisableFeature(
-        blink::features::kInterestCohortAPIOriginTrial);
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(FlocOriginTrialBrowserTestBaseFeatureDisabled,
-                       OriginTrialEnabled) {
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), OriginTrialEnabledURL()));
-
-  // If the base::Feature is disabled, the OT / API is disabled regardless of
-  // the OT config.
-  EXPECT_FALSE(HasInterestCohortApi(web_contents()));
-}
-
-}  // namespace federated_learning
diff --git a/chrome/browser/federated_learning/floc_remote_permission_service.cc b/chrome/browser/federated_learning/floc_remote_permission_service.cc
deleted file mode 100644
index 29a7817..0000000
--- a/chrome/browser/federated_learning/floc_remote_permission_service.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_remote_permission_service.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/json/json_reader.h"
-#include "base/values.h"
-#include "net/base/isolation_info.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_status_code.h"
-#include "services/network/public/cpp/resource_request.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/network/public/cpp/simple_url_loader.h"
-#include "services/network/public/mojom/url_response_head.mojom.h"
-#include "url/gurl.h"
-
-namespace federated_learning {
-
-namespace {
-
-const char kQueryFlocPermissionUrl[] =
-    "https://adservice.google.com/settings/do_ad_settings_allow_floc_poc";
-
-// The maximum number of retries for the SimpleURLLoader requests.
-const size_t kMaxRetries = 1;
-
-class RequestImpl : public FlocRemotePermissionService::Request {
- public:
-  RequestImpl(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      const GURL& url,
-      FlocRemotePermissionService::CreateRequestCallback callback,
-      const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation)
-      : url_loader_factory_(std::move(url_loader_factory)),
-        url_(url),
-        response_code_(0),
-        callback_(std::move(callback)),
-        partial_traffic_annotation_(partial_traffic_annotation) {
-    DCHECK(url_loader_factory_);
-  }
-
-  ~RequestImpl() override = default;
-
-  // Returns the response code received from the server, which will only be
-  // valid if the request succeeded.
-  int GetResponseCode() override { return response_code_; }
-
-  // Returns the contents of the response body received from the server.
-  const std::string& GetResponseBody() override { return response_body_; }
-
- private:
-  void Start() override {
-    auto resource_request = std::make_unique<network::ResourceRequest>();
-    resource_request->url = url_;
-    resource_request->site_for_cookies = net::SiteForCookies::FromUrl(url_);
-    resource_request->trusted_params =
-        network::ResourceRequest::TrustedParams();
-    resource_request->trusted_params->isolation_info =
-        net::IsolationInfo::CreateForInternalRequest(url::Origin::Create(url_));
-    resource_request->method = "GET";
-
-    DCHECK(resource_request->SendsCookies());
-
-    net::NetworkTrafficAnnotationTag traffic_annotation =
-        net::CompleteNetworkTrafficAnnotation("floc_remote_permission_service",
-                                              partial_traffic_annotation_,
-                                              R"(
-          semantics {
-            sender: "Federated Learning of Cohorts Remote Permission Service"
-            destination: GOOGLE_OWNED_SERVICE
-          }
-          policy {
-            cookies_allowed: YES
-            cookies_store: "user"
-            chrome_policy {
-              SyncDisabled {
-                SyncDisabled: true
-              }
-            }
-          })");
-
-    simple_url_loader_ = network::SimpleURLLoader::Create(
-        std::move(resource_request), traffic_annotation);
-    simple_url_loader_->SetRetryOptions(kMaxRetries,
-                                        network::SimpleURLLoader::RETRY_ON_5XX);
-    simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
-        url_loader_factory_.get(),
-        base::BindOnce(&RequestImpl::OnSimpleLoaderComplete,
-                       base::Unretained(this)));
-  }
-
-  void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body) {
-    response_code_ = -1;
-    if (simple_url_loader_->ResponseInfo() &&
-        simple_url_loader_->ResponseInfo()->headers) {
-      response_code_ =
-          simple_url_loader_->ResponseInfo()->headers->response_code();
-    }
-    simple_url_loader_.reset();
-
-    if (response_body) {
-      response_body_ = std::move(*response_body);
-    } else {
-      response_body_.clear();
-    }
-    std::move(callback_).Run(this);
-    // It is valid for the callback to delete |this|, so do not access any
-    // members below here.
-  }
-
-  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
-
-  // The URL of the API endpoint.
-  const GURL url_;
-
-  // Handles the actual request to |url_| (the API endpoint).
-  std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
-
-  // Holds the response code received from the server.
-  int response_code_;
-
-  // Holds the response body received from the server.
-  std::string response_body_;
-
-  // The callback to execute when the query is complete.
-  FlocRemotePermissionService::CreateRequestCallback callback_;
-
-  // Partial Network traffic annotation used to create SimpleURLLoader for this
-  // request.
-  const net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation_;
-};
-
-std::unique_ptr<base::ListValue> ReadResponseAsList(
-    FlocRemotePermissionService::Request* request) {
-  std::unique_ptr<base::ListValue> result;
-  if (request->GetResponseCode() == net::HTTP_OK) {
-    std::unique_ptr<base::Value> value =
-        base::JSONReader::ReadDeprecated(request->GetResponseBody());
-    if (value && value->is_list())
-      result.reset(static_cast<base::ListValue*>(value.release()));
-    else
-      DLOG(WARNING) << "Non-JSON-Array response received from the server.";
-  }
-  return result;
-}
-
-}  // namespace
-
-FlocRemotePermissionService::Request::Request() = default;
-
-FlocRemotePermissionService::Request::~Request() = default;
-
-FlocRemotePermissionService::FlocRemotePermissionService(
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
-    : url_loader_factory_(std::move(url_loader_factory)) {}
-
-FlocRemotePermissionService::~FlocRemotePermissionService() = default;
-
-std::unique_ptr<FlocRemotePermissionService::Request>
-FlocRemotePermissionService::CreateRequest(
-    const GURL& url,
-    CreateRequestCallback callback,
-    const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation) {
-  return std::make_unique<RequestImpl>(url_loader_factory_, url,
-                                       std::move(callback),
-                                       partial_traffic_annotation);
-}
-
-GURL FlocRemotePermissionService::GetQueryFlocPermissionUrl() const {
-  return GURL(kQueryFlocPermissionUrl);
-}
-
-void FlocRemotePermissionService::QueryFlocPermission(
-    QueryFlocPermissionCallback callback,
-    const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation) {
-  // Wrap the original callback into a generic CreateRequestCallback.
-  CreateRequestCallback create_request_callback = base::BindOnce(
-      &FlocRemotePermissionService::QueryFlocPermissionCompletionCallback,
-      weak_ptr_factory_.GetWeakPtr(), std::move(callback));
-
-  GURL url = GetQueryFlocPermissionUrl();
-  std::unique_ptr<Request> request = CreateRequest(
-      url, std::move(create_request_callback), partial_traffic_annotation);
-  Request* request_raw_ptr = request.get();
-  pending_floc_permission_requests_[request_raw_ptr] = std::move(request);
-  request_raw_ptr->Start();
-}
-
-void FlocRemotePermissionService::QueryFlocPermissionCompletionCallback(
-    FlocRemotePermissionService::QueryFlocPermissionCallback callback,
-    FlocRemotePermissionService::Request* request) {
-  std::unique_ptr<Request> request_ptr =
-      std::move(pending_floc_permission_requests_[request]);
-  pending_floc_permission_requests_.erase(request);
-
-  std::unique_ptr<base::ListValue> response_value;
-  bool swaa = false;
-  bool nac = false;
-  bool account_type = false;
-
-  response_value = ReadResponseAsList(request);
-  if (response_value) {
-    base::Value::ListView l = response_value->GetListDeprecated();
-    if (l.size() == 3) {
-      if (l[0].is_bool())
-        swaa = l[0].GetBool();
-      if (l[1].is_bool())
-        nac = l[1].GetBool();
-      if (l[2].is_bool())
-        account_type = l[2].GetBool();
-    }
-  }
-
-  std::move(callback).Run(swaa && nac && account_type);
-}
-
-}  // namespace federated_learning
diff --git a/chrome/browser/federated_learning/floc_remote_permission_service.h b/chrome/browser/federated_learning/floc_remote_permission_service.h
deleted file mode 100644
index 47ad4c4d..0000000
--- a/chrome/browser/federated_learning/floc_remote_permission_service.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2020 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_FEDERATED_LEARNING_FLOC_REMOTE_PERMISSION_SERVICE_H_
-#define CHROME_BROWSER_FEDERATED_LEARNING_FLOC_REMOTE_PERMISSION_SERVICE_H_
-
-#include <stddef.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "url/gurl.h"
-
-
-namespace network {
-class SharedURLLoaderFactory;
-}
-
-namespace federated_learning {
-
-// Provides an API for querying Google servers for a signed-in user's
-// floc related permission settings (e.g. sWAA, NAC, etc.).
-class FlocRemotePermissionService : public KeyedService {
- public:
-  // Handles all the work of making an API request. This class encapsulates
-  // the entire state of the request. When an instance is destroyed, all
-  // aspects of the request are cancelled.
-  class Request {
-   public:
-    virtual ~Request();
-
-    // Returns the response code received from the server, which will only be
-    // valid if the request succeeded.
-    virtual int GetResponseCode() = 0;
-
-    // Returns the contents of the response body received from the server.
-    virtual const std::string& GetResponseBody() = 0;
-
-    // Tells the request to begin.
-    virtual void Start() = 0;
-
-   protected:
-    Request();
-  };
-
-  using QueryFlocPermissionCallback = base::OnceCallback<void(bool success)>;
-
-  using CreateRequestCallback = base::OnceCallback<void(Request*)>;
-
-  FlocRemotePermissionService(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
-
-  FlocRemotePermissionService(const FlocRemotePermissionService&) = delete;
-  FlocRemotePermissionService& operator=(const FlocRemotePermissionService&) =
-      delete;
-
-  ~FlocRemotePermissionService() override;
-
-  // Queries floc related permission settings - specifically the bit swaa, nac,
-  // and account_type. The |callback| will be called with "true" if all 3 bits
-  // are enabled.
-  virtual void QueryFlocPermission(
-      QueryFlocPermissionCallback callback,
-      const net::PartialNetworkTrafficAnnotationTag&
-          partial_traffic_annotation);
-
- protected:
-  // This function is pulled out for testing purposes.
-  virtual std::unique_ptr<Request> CreateRequest(
-      const GURL& url,
-      CreateRequestCallback callback,
-      const net::PartialNetworkTrafficAnnotationTag&
-          partial_traffic_annotation);
-
-  // Virtual so that in browsertest it can return a URL that the test server can
-  // handle.
-  virtual GURL GetQueryFlocPermissionUrl() const;
-
-  // Called by |request| when a floc permission settings query has completed.
-  // Unpacks the response and calls |callback|, which is the original callback
-  // that was passed to QueryFlocRelatedPermissions().
-  void QueryFlocPermissionCompletionCallback(
-      FlocRemotePermissionService::QueryFlocPermissionCallback callback,
-      FlocRemotePermissionService::Request* request);
-
- private:
-  friend class FlocRemotePermissionServiceTest;
-
-  // Request context getter to use.
-  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
-
-  // Pending floc permission queries to be canceled if not complete by profile
-  // shutdown.
-  std::map<Request*, std::unique_ptr<Request>>
-      pending_floc_permission_requests_;
-
-  base::WeakPtrFactory<FlocRemotePermissionService> weak_ptr_factory_{this};
-};
-
-}  // namespace federated_learning
-
-#endif  // CHROME_BROWSER_FEDERATED_LEARNING_FLOC_REMOTE_PERMISSION_SERVICE_H_
diff --git a/chrome/browser/federated_learning/floc_remote_permission_service_factory.cc b/chrome/browser/federated_learning/floc_remote_permission_service_factory.cc
deleted file mode 100644
index 059217eb..0000000
--- a/chrome/browser/federated_learning/floc_remote_permission_service_factory.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_remote_permission_service_factory.h"
-
-#include "chrome/browser/federated_learning/floc_remote_permission_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/sync/driver/sync_service.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/storage_partition.h"
-
-// static
-FlocRemotePermissionServiceFactory*
-FlocRemotePermissionServiceFactory::GetInstance() {
-  return base::Singleton<FlocRemotePermissionServiceFactory>::get();
-}
-
-// static
-federated_learning::FlocRemotePermissionService*
-FlocRemotePermissionServiceFactory::GetForProfile(Profile* profile) {
-
-  return static_cast<federated_learning::FlocRemotePermissionService*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
-
-KeyedService* FlocRemotePermissionServiceFactory::BuildServiceInstanceFor(
-    content::BrowserContext* context) const {
-  Profile* profile = static_cast<Profile*>(context);
-
-  return new federated_learning::FlocRemotePermissionService(
-      profile->GetDefaultStoragePartition()
-          ->GetURLLoaderFactoryForBrowserProcess());
-}
-
-FlocRemotePermissionServiceFactory::FlocRemotePermissionServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "FlocRemotePermissionServiceFactory",
-          BrowserContextDependencyManager::GetInstance()) {}
-
-FlocRemotePermissionServiceFactory::~FlocRemotePermissionServiceFactory() =
-    default;
diff --git a/chrome/browser/federated_learning/floc_remote_permission_service_factory.h b/chrome/browser/federated_learning/floc_remote_permission_service_factory.h
deleted file mode 100644
index d2962904..0000000
--- a/chrome/browser/federated_learning/floc_remote_permission_service_factory.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2020 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_FEDERATED_LEARNING_FLOC_REMOTE_PERMISSION_SERVICE_FACTORY_H_
-#define CHROME_BROWSER_FEDERATED_LEARNING_FLOC_REMOTE_PERMISSION_SERVICE_FACTORY_H_
-
-#include "base/memory/singleton.h"
-#include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-namespace federated_learning {
-class FlocRemotePermissionService;
-}
-
-// Used for creating and fetching a per-profile instance of the
-// FlocRemotePermissionService.
-class FlocRemotePermissionServiceFactory
-    : public BrowserContextKeyedServiceFactory {
- public:
-  // Get the singleton instance of the factory.
-  static FlocRemotePermissionServiceFactory* GetInstance();
-
-  // Get the FlocRemotePermissionService for |profile|, creating one if needed.
-  static federated_learning::FlocRemotePermissionService* GetForProfile(
-      Profile* profile);
-
-  FlocRemotePermissionServiceFactory(
-      const FlocRemotePermissionServiceFactory&) = delete;
-  FlocRemotePermissionServiceFactory& operator=(
-      const FlocRemotePermissionServiceFactory&) = delete;
-
- protected:
-  // Overridden from BrowserContextKeyedServiceFactory.
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* context) const override;
-
- private:
-  friend struct base::DefaultSingletonTraits<
-      FlocRemotePermissionServiceFactory>;
-
-  FlocRemotePermissionServiceFactory();
-  ~FlocRemotePermissionServiceFactory() override;
-};
-
-#endif  // CHROME_BROWSER_FEDERATED_LEARNING_FLOC_REMOTE_PERMISSION_SERVICE_FACTORY_H_
diff --git a/chrome/browser/federated_learning/floc_remote_permission_service_unittest.cc b/chrome/browser/federated_learning/floc_remote_permission_service_unittest.cc
deleted file mode 100644
index 2a3362f..0000000
--- a/chrome/browser/federated_learning/floc_remote_permission_service_unittest.cc
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_remote_permission_service.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/run_loop.h"
-#include "base/task/single_thread_task_runner.h"
-#include "base/test/task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/values.h"
-#include "net/http/http_status_code.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "services/network/test/test_url_loader_factory.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace federated_learning {
-
-namespace {
-
-// A testing floc remote permission service that does extra checks and creates a
-// TestRequest instead of a normal request.
-class TestingFlocRemotePermissionService : public FlocRemotePermissionService {
- public:
-  explicit TestingFlocRemotePermissionService(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
-      : FlocRemotePermissionService(url_loader_factory),
-        expected_url_(GURL()),
-        expected_floc_permission_(false) {}
-
-  TestingFlocRemotePermissionService(
-      const TestingFlocRemotePermissionService&) = delete;
-  TestingFlocRemotePermissionService& operator=(
-      const TestingFlocRemotePermissionService&) = delete;
-
-  ~TestingFlocRemotePermissionService() override = default;
-
-  std::unique_ptr<FlocRemotePermissionService::Request> CreateRequest(
-      const GURL& url,
-      CreateRequestCallback callback,
-      const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation)
-      override;
-
-  const std::string& GetExpectedPostData(
-      FlocRemotePermissionService::Request* request);
-
-  void QueryFlocPermissionCallback(bool success);
-
-  void SetExpectedURL(const GURL& expected_url) {
-    expected_url_ = expected_url;
-  }
-
-  void SetExpectedFlocPermission(bool expected_value) {
-    expected_floc_permission_ = expected_value;
-  }
-
-  void SetResponseCodeOverride(int response_code_override) {
-    response_code_override_ = response_code_override;
-  }
-
-  void SetResponseBodyOverride(const std::string& response_body_override) {
-    response_body_override_ = response_body_override;
-  }
-
- private:
-  GURL expected_url_;
-  bool expected_floc_permission_;
-  absl::optional<int> response_code_override_;
-  absl::optional<std::string> response_body_override_;
-};
-
-// A testing request class that allows expected values to be filled in.
-class TestRequest : public FlocRemotePermissionService::Request {
- public:
-  TestRequest(const GURL& url,
-              FlocRemotePermissionService::CreateRequestCallback callback,
-              int response_code,
-              const std::string& response_body)
-      : url_(url),
-        callback_(std::move(callback)),
-        response_code_(response_code),
-        response_body_(response_body) {}
-
-  TestRequest(const TestRequest&) = delete;
-  TestRequest& operator=(const TestRequest&) = delete;
-
-  ~TestRequest() override = default;
-
-  // FlocRemotePermissionService::Request overrides
-  int GetResponseCode() override { return response_code_; }
-  const std::string& GetResponseBody() override { return response_body_; }
-
-  void Start() override {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&TestRequest::MimicReturnFromFetch,
-                                  base::Unretained(this)));
-  }
-
-  void MimicReturnFromFetch() {
-    // Mimic a successful fetch and return. We don't actually send out a request
-    // in unittests.
-    std::move(callback_).Run(this);
-  }
-
-  void SetResponseCode(int response_code) { response_code_ = response_code; }
-
-  void SetResponseBody(const std::string& response_body) {
-    response_body_ = response_body;
-  }
-
- private:
-  GURL url_;
-  FlocRemotePermissionService::CreateRequestCallback callback_;
-  int response_code_;
-  std::string response_body_;
-};
-
-std::unique_ptr<FlocRemotePermissionService::Request>
-TestingFlocRemotePermissionService::CreateRequest(
-    const GURL& url,
-    CreateRequestCallback callback,
-    const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation) {
-  EXPECT_EQ(expected_url_, url);
-  auto request =
-      std::make_unique<TestRequest>(url, std::move(callback), net::HTTP_OK, "");
-
-  if (response_code_override_) {
-    request->SetResponseCode(response_code_override_.value());
-  }
-
-  if (response_body_override_) {
-    request->SetResponseBody(response_body_override_.value());
-  }
-
-  return std::move(request);
-}
-
-void TestingFlocRemotePermissionService::QueryFlocPermissionCallback(
-    bool success) {
-  EXPECT_EQ(expected_floc_permission_, success);
-}
-
-}  // namespace
-
-// A test class used for testing the FlocRemotePermissionService class.
-class FlocRemotePermissionServiceTest : public testing::Test {
- public:
-  FlocRemotePermissionServiceTest()
-      : test_shared_loader_factory_(
-            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-                &test_url_loader_factory_)),
-        floc_remote_permission_service_(test_shared_loader_factory_) {}
-
-  FlocRemotePermissionServiceTest(const FlocRemotePermissionServiceTest&) =
-      delete;
-  FlocRemotePermissionServiceTest& operator=(
-      const FlocRemotePermissionServiceTest&) = delete;
-
-  ~FlocRemotePermissionServiceTest() override = default;
-
-  void TearDown() override {
-    base::RunLoop run_loop;
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  run_loop.QuitClosure());
-    run_loop.Run();
-  }
-
-  TestingFlocRemotePermissionService* floc_remote_permission_service() {
-    return &floc_remote_permission_service_;
-  }
-
- private:
-  base::test::SingleThreadTaskEnvironment task_environment_;
-  network::TestURLLoaderFactory test_url_loader_factory_;
-  scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
-  TestingFlocRemotePermissionService floc_remote_permission_service_;
-};
-
-TEST_F(FlocRemotePermissionServiceTest, QueryFlocPermission) {
-  floc_remote_permission_service()->SetExpectedURL(GURL(
-      "https://adservice.google.com/settings/do_ad_settings_allow_floc_poc"));
-
-  /* Success cases */
-  floc_remote_permission_service()->SetExpectedFlocPermission(true);
-
-  floc_remote_permission_service()->SetResponseCodeOverride(net::HTTP_OK);
-  floc_remote_permission_service()->SetResponseBodyOverride(
-      "[true, true, true]");
-
-  floc_remote_permission_service()->QueryFlocPermission(
-      base::BindOnce(
-          &TestingFlocRemotePermissionService::QueryFlocPermissionCallback,
-          base::Unretained(floc_remote_permission_service())),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
-
-  base::RunLoop().RunUntilIdle();
-
-  /* Failure cases */
-  floc_remote_permission_service()->SetExpectedFlocPermission(false);
-
-  // Failure: disabled permission setting
-  floc_remote_permission_service()->SetResponseBodyOverride(
-      "[true, false, true]");
-  floc_remote_permission_service()->QueryFlocPermission(
-      base::BindOnce(
-          &TestingFlocRemotePermissionService::QueryFlocPermissionCallback,
-          base::Unretained(floc_remote_permission_service())),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
-
-  base::RunLoop().RunUntilIdle();
-
-  // Failure: unexpected response format
-  floc_remote_permission_service()->SetResponseBodyOverride("[1, 1, 1]");
-
-  floc_remote_permission_service()->QueryFlocPermission(
-      base::BindOnce(
-          &TestingFlocRemotePermissionService::QueryFlocPermissionCallback,
-          base::Unretained(floc_remote_permission_service())),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
-
-  base::RunLoop().RunUntilIdle();
-
-  // Failure: 404 Not Found
-  floc_remote_permission_service()->SetResponseBodyOverride(
-      "[true, true, true]");
-  floc_remote_permission_service()->SetResponseCodeOverride(
-      net::HTTP_NOT_FOUND);
-
-  floc_remote_permission_service()->QueryFlocPermission(
-      base::BindOnce(
-          &TestingFlocRemotePermissionService::QueryFlocPermissionCallback,
-          base::Unretained(floc_remote_permission_service())),
-      PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
-
-  base::RunLoop().RunUntilIdle();
-}
-
-}  // namespace federated_learning
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 0b5659d8..469999f 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -2050,7 +2050,7 @@
   {
     "name": "enable-force-dark",
     "owners": [ "pdr", "khorimoto@chromium.org", "jessejames@chromium.org" ],
-    "expiry_milestone": 99
+    "expiry_milestone": 105
   },
   {
     "name": "enable-fre-default-browser-screen-testing",
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/floc_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/floc_page_load_metrics_observer.cc
deleted file mode 100644
index 7ea10235..0000000
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/floc_page_load_metrics_observer.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2021 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/page_load_metrics/observers/ad_metrics/floc_page_load_metrics_observer.h"
-
-#include "base/ranges/algorithm.h"
-#include "chrome/browser/federated_learning/floc_eligibility_observer.h"
-#include "chrome/browser/federated_learning/floc_id_provider.h"
-#include "chrome/browser/federated_learning/floc_id_provider_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/web_contents.h"
-
-FlocPageLoadMetricsObserver::FlocPageLoadMetricsObserver() = default;
-
-FlocPageLoadMetricsObserver::~FlocPageLoadMetricsObserver() = default;
-
-page_load_metrics::PageLoadMetricsObserver::ObservePolicy
-FlocPageLoadMetricsObserver::OnCommit(
-    content::NavigationHandle* navigation_handle,
-    ukm::SourceId source_id) {
-  federated_learning::FlocIdProvider* floc_id_provider =
-      federated_learning::FlocIdProviderFactory::GetForProfile(
-          Profile::FromBrowserContext(
-              GetDelegate().GetWebContents()->GetBrowserContext()));
-
-  if (floc_id_provider)
-    floc_id_provider->MaybeRecordFlocToUkm(source_id);
-
-  return federated_learning::FlocEligibilityObserver::
-      GetOrCreateForCurrentDocument(navigation_handle->GetRenderFrameHost())
-          ->OnCommit(navigation_handle);
-}
-
-void FlocPageLoadMetricsObserver::OnResourceDataUseObserved(
-    content::RenderFrameHost* rfh,
-    const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>&
-        resources) {
-  bool any_ads_resource = base::ranges::any_of(
-      resources,
-      [](const page_load_metrics::mojom::ResourceDataUpdatePtr& resource) {
-        return resource->reported_as_ad_resource &&
-               resource->received_data_length > 0;
-      });
-
-  if (any_ads_resource) {
-    content::WebContents* web_contents = GetDelegate().GetWebContents();
-    federated_learning::FlocEligibilityObserver::GetOrCreateForCurrentDocument(
-        web_contents->GetMainFrame())
-        ->OnAdResource();
-  }
-}
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/floc_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/ad_metrics/floc_page_load_metrics_observer.h
deleted file mode 100644
index 565c1dbd..0000000
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/floc_page_load_metrics_observer.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2021 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_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_FLOC_PAGE_LOAD_METRICS_OBSERVER_H_
-#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_FLOC_PAGE_LOAD_METRICS_OBSERVER_H_
-
-#include "components/page_load_metrics/browser/page_load_metrics_observer.h"
-
-// This observer monitors navigation commit and resource usages, which may
-// affect whether the navigation's associated history entry is eligible for floc
-// computation.
-//
-// The final eligibility decision may be based on other signals. See the
-// FlocEligibilityObserver class for the full criteria.
-class FlocPageLoadMetricsObserver
-    : public page_load_metrics::PageLoadMetricsObserver {
- public:
-  FlocPageLoadMetricsObserver();
-  ~FlocPageLoadMetricsObserver() override;
-
-  FlocPageLoadMetricsObserver(const FlocPageLoadMetricsObserver&) = delete;
-  FlocPageLoadMetricsObserver& operator=(const FlocPageLoadMetricsObserver&) =
-      delete;
-
-  // page_load_metrics::PageLoadMetricsObserver
-  ObservePolicy OnCommit(content::NavigationHandle* navigation_handle,
-                         ukm::SourceId source_id) override;
-  void OnResourceDataUseObserved(
-      content::RenderFrameHost* rfh,
-      const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>&
-          resources) override;
-};
-
-#endif  // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_FLOC_PAGE_LOAD_METRICS_OBSERVER_H_
diff --git a/chrome/browser/page_load_metrics/observers/formfill_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/formfill_page_load_metrics_observer.cc
index b9cd754..c4e5f5a 100644
--- a/chrome/browser/page_load_metrics/observers/formfill_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/formfill_page_load_metrics_observer.cc
@@ -6,9 +6,6 @@
 
 #include "base/ranges/algorithm.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/federated_learning/floc_eligibility_observer.h"
-#include "chrome/browser/federated_learning/floc_id_provider.h"
-#include "chrome/browser/federated_learning/floc_id_provider_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/page_load_metrics/browser/metrics_web_contents_observer.h"
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
index 6cedf91..230a2f08 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/heavy_ad_intervention/heavy_ad_service_factory.h"
 #include "chrome/browser/page_load_metrics/observers/aborts_page_load_metrics_observer.h"
-#include "chrome/browser/page_load_metrics/observers/ad_metrics/floc_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/core/amp_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h"
@@ -141,7 +140,6 @@
     if (ads_observer)
       tracker->AddObserver(std::move(ads_observer));
 
-    tracker->AddObserver(std::make_unique<FlocPageLoadMetricsObserver>());
     tracker->AddObserver(std::make_unique<ThirdPartyMetricsObserver>());
     tracker->AddObserver(std::make_unique<FormfillPageLoadMetricsObserver>());
 
diff --git a/chrome/browser/policy/webhid_device_policy_handler.cc b/chrome/browser/policy/webhid_device_policy_handler.cc
index 60c880c..8cdea01 100644
--- a/chrome/browser/policy/webhid_device_policy_handler.cc
+++ b/chrome/browser/policy/webhid_device_policy_handler.cc
@@ -49,13 +49,13 @@
     return false;
 
   int item_index = 0;
-  for (const auto& item : value->GetList()) {
+  for (const auto& item : value->GetListDeprecated()) {
     int url_index = 0;
     auto* urls_list = item.FindKeyOfType(kUrlsKey, base::Value::Type::LIST);
     if (!urls_list)
       continue;
 
-    for (const auto& url_value : urls_list->GetList()) {
+    for (const auto& url_value : urls_list->GetListDeprecated()) {
       DCHECK(url_value.is_string());
       GURL url(url_value.GetString());
       // If `url` is invalid, emit an error but do not prevent the policy from
diff --git a/chrome/browser/policy/webhid_device_policy_handler_unittest.cc b/chrome/browser/policy/webhid_device_policy_handler_unittest.cc
index 5d48882..f43b781 100644
--- a/chrome/browser/policy/webhid_device_policy_handler_unittest.cc
+++ b/chrome/browser/policy/webhid_device_policy_handler_unittest.cc
@@ -201,14 +201,14 @@
   ASSERT_TRUE(pref_value->is_list());
 
   // Ensure that the kManagedWebHidAllowDevicesForUrls pref is set correctly.
-  const auto& list = pref_value->GetList();
+  const auto& list = pref_value->GetListDeprecated();
   ASSERT_EQ(2ul, list.size());
 
   // Check the first item's devices list.
   const base::Value* devices = list[0].FindKey(kDevicesKey);
   ASSERT_TRUE(devices);
 
-  const auto& first_devices_list = devices->GetList();
+  const auto& first_devices_list = devices->GetListDeprecated();
   ASSERT_EQ(2ul, first_devices_list.size());
 
   const base::Value* vendor_id = first_devices_list[0].FindKey(kVendorIdKey);
@@ -229,15 +229,15 @@
   // Check the first item's urls list.
   const base::Value* urls = list[0].FindKey(kUrlsKey);
   ASSERT_TRUE(urls);
-  ASSERT_EQ(2ul, urls->GetList().size());
-  EXPECT_EQ(base::Value("https://origin1"), urls->GetList()[0]);
-  EXPECT_EQ(base::Value("https://origin2"), urls->GetList()[1]);
+  ASSERT_EQ(2ul, urls->GetListDeprecated().size());
+  EXPECT_EQ(base::Value("https://origin1"), urls->GetListDeprecated()[0]);
+  EXPECT_EQ(base::Value("https://origin2"), urls->GetListDeprecated()[1]);
 
   // Check the second item's devices list.
   devices = list[1].FindKey(kDevicesKey);
   ASSERT_TRUE(devices);
 
-  const auto& second_devices_list = devices->GetList();
+  const auto& second_devices_list = devices->GetListDeprecated();
   ASSERT_EQ(1ul, second_devices_list.size());
 
   vendor_id = second_devices_list[0].FindKey(kVendorIdKey);
@@ -250,8 +250,8 @@
   // Check the second item's urls list.
   urls = list[1].FindKey(kUrlsKey);
   ASSERT_TRUE(urls);
-  ASSERT_EQ(1ul, urls->GetList().size());
-  EXPECT_EQ(base::Value("https://origin3"), urls->GetList()[0]);
+  ASSERT_EQ(1ul, urls->GetListDeprecated().size());
+  EXPECT_EQ(base::Value("https://origin3"), urls->GetListDeprecated()[0]);
 }
 
 TEST_F(WebHidDevicePolicyHandlerTest, ApplyPolicySettingsWithUsagePolicy) {
@@ -276,14 +276,14 @@
 
   // Ensure that the kManagedWebHidAllowDevicesWithHidUsagesForUrls pref is set
   // correctly.
-  const auto& list = pref_value->GetList();
+  const auto& list = pref_value->GetListDeprecated();
   ASSERT_EQ(2ul, list.size());
 
   // Check the first item's usages list.
   const base::Value* usages = list[0].FindKey(kUsagesKey);
   ASSERT_TRUE(usages);
 
-  const auto& first_usages_list = usages->GetList();
+  const auto& first_usages_list = usages->GetListDeprecated();
   ASSERT_EQ(2ul, first_usages_list.size());
 
   const base::Value* usage_page = first_usages_list[0].FindKey(kUsagePageKey);
@@ -304,15 +304,15 @@
   // Check the first item's urls list.
   const base::Value* urls = list[0].FindKey(kUrlsKey);
   ASSERT_TRUE(urls);
-  ASSERT_EQ(2ul, urls->GetList().size());
-  EXPECT_EQ(base::Value("https://origin1"), urls->GetList()[0]);
-  EXPECT_EQ(base::Value("https://origin2"), urls->GetList()[1]);
+  ASSERT_EQ(2ul, urls->GetListDeprecated().size());
+  EXPECT_EQ(base::Value("https://origin1"), urls->GetListDeprecated()[0]);
+  EXPECT_EQ(base::Value("https://origin2"), urls->GetListDeprecated()[1]);
 
   // Check the second item's usages list.
   usages = list[1].FindKey(kUsagesKey);
   ASSERT_TRUE(usages);
 
-  const auto& second_usages_list = usages->GetList();
+  const auto& second_usages_list = usages->GetListDeprecated();
   ASSERT_EQ(1ul, second_usages_list.size());
 
   usage_page = second_usages_list[0].FindKey(kUsagePageKey);
@@ -325,8 +325,8 @@
   // Check the second item's urls list.
   urls = list[1].FindKey(kUrlsKey);
   ASSERT_TRUE(urls);
-  ASSERT_EQ(1ul, urls->GetList().size());
-  EXPECT_EQ(base::Value("https://origin3"), urls->GetList()[0]);
+  ASSERT_EQ(1ul, urls->GetListDeprecated().size());
+  EXPECT_EQ(base::Value("https://origin3"), urls->GetListDeprecated()[0]);
 }
 
 struct WebHidInvalidPolicyTestData {
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 49ce6e9..37e32f1a 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -99,7 +99,6 @@
 #include "components/dom_distiller/core/dom_distiller_features.h"
 #include "components/dom_distiller/core/pref_names.h"
 #include "components/embedder_support/origin_trials/origin_trial_prefs.h"
-#include "components/federated_learning/floc_id.h"
 #include "components/flags_ui/pref_service_flags_storage.h"
 #include "components/history_clusters/core/history_clusters_prefs.h"
 #include "components/image_fetcher/core/cache/image_cache.h"
@@ -456,6 +455,21 @@
 #endif  // BUILDFLAG(ENABLE_SIDE_SEARCH)
 
 namespace {
+
+// Deprecated 02/2022
+const char kFlocIdValuePrefKey[] = "federated_learning.floc_id.value";
+const char kFlocIdStatusPrefKey[] = "federated_learning.floc_id.status";
+const char kFlocIdHistoryBeginTimePrefKey[] =
+    "federated_learning.floc_id.history_begin_time";
+const char kFlocIdHistoryEndTimePrefKey[] =
+    "federated_learning.floc_id.history_end_time";
+const char kFlocIdFinchConfigVersionPrefKey[] =
+    "federated_learning.floc_id.finch_config_version";
+const char kFlocIdSortingLshVersionPrefKey[] =
+    "federated_learning.floc_id.sorting_lsh_version";
+const char kFlocIdComputeTimePrefKey[] =
+    "federated_learning.floc_id.compute_time";
+
 // Deprecated 10/2021
 const char kTabStripStackedLayout[] = "tab-strip-stacked-layout";
 
@@ -955,6 +969,14 @@
   registry->RegisterBooleanPref(kDataSaverEnabled, false);
   registry->RegisterBooleanPref(kDataReductionProxyWasEnabledBefore, false);
   registry->RegisterInt64Pref(kDataReductionProxyLastEnabledTime, 0L);
+
+  registry->RegisterUint64Pref(kFlocIdValuePrefKey, 0);
+  registry->RegisterIntegerPref(kFlocIdStatusPrefKey, 0);
+  registry->RegisterTimePref(kFlocIdHistoryBeginTimePrefKey, base::Time());
+  registry->RegisterTimePref(kFlocIdHistoryEndTimePrefKey, base::Time());
+  registry->RegisterUint64Pref(kFlocIdFinchConfigVersionPrefKey, 0);
+  registry->RegisterUint64Pref(kFlocIdSortingLshVersionPrefKey, 0);
+  registry->RegisterTimePref(kFlocIdComputeTimePrefKey, base::Time());
 }
 
 }  // namespace
@@ -1215,7 +1237,6 @@
   dom_distiller::DistilledPagePrefs::RegisterProfilePrefs(registry);
   dom_distiller::RegisterProfilePrefs(registry);
   DownloadPrefs::RegisterProfilePrefs(registry);
-  federated_learning::FlocId::RegisterPrefs(registry);
   history_clusters::prefs::RegisterProfilePrefs(registry);
   HostContentSettingsMap::RegisterProfilePrefs(registry);
   image_fetcher::ImageCache::RegisterProfilePrefs(registry);
@@ -1863,6 +1884,15 @@
   web_app::WebAppProvider::MigrateProfilePrefs(profile);
 #endif
 
+  // Added 02/2022
+  profile_prefs->ClearPref(kFlocIdValuePrefKey);
+  profile_prefs->ClearPref(kFlocIdStatusPrefKey);
+  profile_prefs->ClearPref(kFlocIdHistoryBeginTimePrefKey);
+  profile_prefs->ClearPref(kFlocIdHistoryEndTimePrefKey);
+  profile_prefs->ClearPref(kFlocIdFinchConfigVersionPrefKey);
+  profile_prefs->ClearPref(kFlocIdSortingLshVersionPrefKey);
+  profile_prefs->ClearPref(kFlocIdComputeTimePrefKey);
+
   // Please don't delete the following line. It is used by PRESUBMIT.py.
   // END_MIGRATE_OBSOLETE_PROFILE_PREFS
 }
diff --git a/chrome/browser/prefs/chrome_command_line_pref_store.cc b/chrome/browser/prefs/chrome_command_line_pref_store.cc
index 983c79e5..223c767 100644
--- a/chrome/browser/prefs/chrome_command_line_pref_store.cc
+++ b/chrome/browser/prefs/chrome_command_line_pref_store.cc
@@ -45,6 +45,7 @@
 const CommandLinePrefStore::SwitchToPreferenceMapEntry
     ChromeCommandLinePrefStore::string_switch_map_[] = {
         {switches::kLang, language::prefs::kApplicationLocale},
+        {switches::kAcceptLang, language::prefs::kSelectedLanguages},
         {switches::kAuthServerAllowlist, prefs::kAuthServerAllowlist},
         {switches::kSSLVersionMin, prefs::kSSLVersionMin},
         {switches::kSSLVersionMax, prefs::kSSLVersionMax},
diff --git a/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc b/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc
index b2803fc..420444d 100644
--- a/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc
+++ b/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc
@@ -246,3 +246,15 @@
     ++i;
   }
 }
+
+TEST(ChromeCommandLinePrefStoreTest, AcceptLanguage) {
+  base::CommandLine cl(base::CommandLine::NO_PROGRAM);
+  cl.AppendSwitchASCII(switches::kAcceptLang, "de,en,fr,jp");
+  auto store = base::MakeRefCounted<ChromeCommandLinePrefStore>(&cl);
+
+  const base::Value* actual = nullptr;
+  EXPECT_TRUE(store->GetValue(language::prefs::kSelectedLanguages, &actual));
+  std::string result;
+  EXPECT_TRUE(actual->GetAsString(&result));
+  EXPECT_EQ("de,en,fr,jp", result);
+}
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
index 1e829bf..225372c 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
@@ -13,10 +13,8 @@
 #include "base/metrics/user_metrics.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
-#include "chrome/browser/federated_learning/floc_id_provider.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/content_settings/core/common/pref_names.h"
-#include "components/federated_learning/features/features.h"
 #include "components/prefs/pref_service.h"
 #include "components/privacy_sandbox/privacy_sandbox_features.h"
 #include "components/privacy_sandbox/privacy_sandbox_prefs.h"
@@ -115,7 +113,6 @@
     policy::PolicyService* policy_service,
     syncer::SyncService* sync_service,
     signin::IdentityManager* identity_manager,
-    federated_learning::FlocIdProvider* floc_id_provider,
     content::InterestGroupManager* interest_group_manager,
     profile_metrics::BrowserProfileType profile_type)
     : privacy_sandbox_settings_(privacy_sandbox_settings),
@@ -124,7 +121,6 @@
       policy_service_(policy_service),
       sync_service_(sync_service),
       identity_manager_(identity_manager),
-      floc_id_provider_(floc_id_provider),
       interest_group_manager_(interest_group_manager),
       profile_type_(profile_type) {
   DCHECK(privacy_sandbox_settings_);
@@ -180,52 +176,24 @@
 std::u16string PrivacySandboxService::GetFlocDescriptionForDisplay() const {
   return l10n_util::GetPluralStringFUTF16(
       IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION,
-      GetNumberOfDaysRoundedAboveOne(
-          federated_learning::kFlocIdScheduledUpdateInterval.Get()));
+      GetNumberOfDaysRoundedAboveOne(base::Days(7)));
 }
 
 std::u16string PrivacySandboxService::GetFlocIdForDisplay() const {
-  const bool floc_feature_enabled = base::FeatureList::IsEnabled(
-      blink::features::kInterestCohortAPIOriginTrial);
-  auto floc_id = federated_learning::FlocId::ReadFromPrefs(pref_service_);
-
-  if (!privacy_sandbox_settings_->IsFlocAllowed() || !floc_feature_enabled ||
-      !floc_id.IsValid())
-    return l10n_util::GetStringUTF16(IDS_PRIVACY_SANDBOX_FLOC_INVALID);
-
-  return base::NumberToString16(floc_id.ToUint64());
+  return l10n_util::GetStringUTF16(IDS_PRIVACY_SANDBOX_FLOC_INVALID);
 }
 
 std::u16string PrivacySandboxService::GetFlocIdNextUpdateForDisplay(
     const base::Time& current_time) {
-  const bool floc_feature_enabled = base::FeatureList::IsEnabled(
-      blink::features::kInterestCohortAPIOriginTrial);
-
-  if (!floc_id_provider_ || !floc_feature_enabled ||
-      !privacy_sandbox_settings_->IsFlocAllowed()) {
-    return l10n_util::GetStringUTF16(
-        IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE_INVALID);
-  }
-
-  auto next_compute_time = floc_id_provider_->GetApproximateNextComputeTime();
-
-  // There are no guarantee that the next compute time is in the future. This
-  // should only occur when a compute is soon to occur, so assuming the current
-  // time is suitable.
-  if (next_compute_time < current_time)
-    next_compute_time = current_time;
-
-  return l10n_util::GetPluralStringFUTF16(
-      IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE,
-      GetNumberOfDaysRoundedAboveOne(next_compute_time - current_time));
+  return l10n_util::GetStringUTF16(
+      IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE_INVALID);
 }
 
 std::u16string PrivacySandboxService::GetFlocResetExplanationForDisplay()
     const {
   return l10n_util::GetPluralStringFUTF16(
       IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION,
-      GetNumberOfDaysRoundedAboveOne(
-          federated_learning::kFlocIdScheduledUpdateInterval.Get()));
+      GetNumberOfDaysRoundedAboveOne(base::Days(7)));
 }
 
 std::u16string PrivacySandboxService::GetFlocStatusForDisplay() const {
@@ -235,9 +203,7 @@
 }
 
 bool PrivacySandboxService::IsFlocIdResettable() const {
-  const bool floc_feature_enabled = base::FeatureList::IsEnabled(
-      blink::features::kInterestCohortAPIOriginTrial);
-  return floc_feature_enabled && privacy_sandbox_settings_->IsFlocAllowed();
+  return false;
 }
 
 void PrivacySandboxService::ResetFlocId(bool user_initiated) const {
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service.h b/chrome/browser/privacy_sandbox/privacy_sandbox_service.h
index a7b0b57..4a36023 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service.h
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service.h
@@ -9,7 +9,6 @@
 #include "base/memory/raw_ptr.h"
 #include "base/scoped_observation.h"
 #include "base/time/time.h"
-#include "chrome/browser/federated_learning/floc_id_provider.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/policy/core/common/policy_service.h"
@@ -85,7 +84,6 @@
                         policy::PolicyService* policy_service,
                         syncer::SyncService* sync_service,
                         signin::IdentityManager* identity_manager,
-                        federated_learning::FlocIdProvider* floc_id_provider,
                         content::InterestGroupManager* interest_group_manager,
                         profile_metrics::BrowserProfileType profile_type);
   ~PrivacySandboxService() override;
@@ -277,7 +275,6 @@
   raw_ptr<policy::PolicyService> policy_service_;
   raw_ptr<syncer::SyncService> sync_service_;
   raw_ptr<signin::IdentityManager> identity_manager_;
-  raw_ptr<federated_learning::FlocIdProvider> floc_id_provider_;
   raw_ptr<content::InterestGroupManager> interest_group_manager_;
   profile_metrics::BrowserProfileType profile_type_;
 
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
index 9ec2a179..0bb160a 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
@@ -6,7 +6,6 @@
 
 #include "base/memory/singleton.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
-#include "chrome/browser/federated_learning/floc_id_provider_factory.h"
 #include "chrome/browser/policy/profile_policy_connector.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
@@ -38,7 +37,6 @@
   DependsOn(CookieSettingsFactory::GetInstance());
   DependsOn(SyncServiceFactory::GetInstance());
   DependsOn(IdentityManagerFactory::GetInstance());
-  DependsOn(federated_learning::FlocIdProviderFactory::GetInstance());
 }
 
 KeyedService* PrivacySandboxServiceFactory::BuildServiceInstanceFor(
@@ -50,7 +48,6 @@
       profile->GetProfilePolicyConnector()->policy_service(),
       SyncServiceFactory::GetForProfile(profile),
       IdentityManagerFactory::GetForProfile(profile),
-      federated_learning::FlocIdProviderFactory::GetForProfile(profile),
       profile->GetDefaultStoragePartition()->GetInterestGroupManager(),
       profile_metrics::GetBrowserProfileType(profile));
 }
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc
index a10516c..15ca5d7 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc
@@ -12,18 +12,14 @@
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/federated_learning/floc_id_provider.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "chrome/browser/ui/webui/federated_learning/floc_internals.mojom.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/pref_names.h"
-#include "components/federated_learning/features/features.h"
-#include "components/federated_learning/floc_id.h"
 #include "components/policy/core/common/mock_policy_service.h"
 #include "components/privacy_sandbox/privacy_sandbox_features.h"
 #include "components/privacy_sandbox/privacy_sandbox_prefs.h"
@@ -41,27 +37,11 @@
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/origin.h"
 
 namespace {
 
-class MockFlocIdProvider : public federated_learning::FlocIdProvider {
- public:
-  blink::mojom::InterestCohortPtr GetInterestCohortForJsApi(
-      const GURL& url,
-      const absl::optional<url::Origin>& top_frame_origin) const override {
-    return blink::mojom::InterestCohort::New();
-  }
-  MOCK_METHOD(federated_learning::mojom::WebUIFlocStatusPtr,
-              GetFlocStatusForWebUi,
-              (),
-              (const, override));
-  MOCK_METHOD(void, MaybeRecordFlocToUkm, (ukm::SourceId), (override));
-  MOCK_METHOD(base::Time, GetApproximateNextComputeTime, (), (const, override));
-};
-
 class TestInterestGroupManager : public content::InterestGroupManager {
  public:
   void SetInterestGroupJoiningOrigins(const std::vector<url::Origin>& origins) {
@@ -93,8 +73,8 @@
         PrivacySandboxSettingsFactory::GetForProfile(profile()),
         CookieSettingsFactory::GetForProfile(profile()).get(),
         profile()->GetPrefs(), policy_service(), sync_service(),
-        identity_test_env()->identity_manager(), mock_floc_id_provider(),
-        test_interest_group_manager(), GetProfileType());
+        identity_test_env()->identity_manager(), test_interest_group_manager(),
+        GetProfileType());
   }
 
   virtual void InitializePrefsBeforeStart() {}
@@ -122,9 +102,6 @@
   signin::IdentityTestEnvironment* identity_test_env() {
     return &identity_test_env_;
   }
-  MockFlocIdProvider* mock_floc_id_provider() {
-    return &mock_floc_id_provider_;
-  }
   TestInterestGroupManager* test_interest_group_manager() {
     return &test_interest_group_manager_;
   }
@@ -137,257 +114,43 @@
   TestingProfile profile_;
   base::test::ScopedFeatureList feature_list_;
   syncer::TestSyncService sync_service_;
-  MockFlocIdProvider mock_floc_id_provider_;
   TestInterestGroupManager test_interest_group_manager_;
 
   std::unique_ptr<PrivacySandboxService> privacy_sandbox_service_;
 };
 
 TEST_F(PrivacySandboxServiceTest, GetFlocDescriptionForDisplay) {
-  // Check that the returned FLoC description correctly takes into account the
-  // time between FLoC recomputes.
-  std::map<std::string, std::u16string> param_to_expected_string = {
-      {"1h", l10n_util::GetPluralStringFUTF16(
-                 IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION, 0)},
-      {"23h", l10n_util::GetPluralStringFUTF16(
-                  IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION, 0)},
-      {"24h", l10n_util::GetPluralStringFUTF16(
-                  IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION, 1)},
-      {"25h", l10n_util::GetPluralStringFUTF16(
-                  IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION, 1)},
-      {"60h", l10n_util::GetPluralStringFUTF16(
-                  IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION, 3)},
-      {"167h", l10n_util::GetPluralStringFUTF16(
-                   IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION, 7)},
-      {"168h", l10n_util::GetPluralStringFUTF16(
-                   IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION, 7)}};
-
-  for (const auto& param_expected : param_to_expected_string) {
-    feature_list()->InitAndEnableFeatureWithParameters(
-        federated_learning::kFederatedLearningOfCohorts,
-        {{"update_interval", param_expected.first}});
-    EXPECT_EQ(param_expected.second,
-              privacy_sandbox_service()->GetFlocDescriptionForDisplay());
-    feature_list()->Reset();
-  }
+  EXPECT_EQ(
+      l10n_util::GetPluralStringFUTF16(IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION, 7),
+      privacy_sandbox_service()->GetFlocDescriptionForDisplay());
 }
 
 TEST_F(PrivacySandboxServiceTest, GetFlocIdForDisplay) {
-  // Check that the cohort identifier is correctly converted to a string when
-  // available.
-  feature_list()->InitWithFeatures(
-      {blink::features::kInterestCohortAPIOriginTrial},
-      {privacy_sandbox::kPrivacySandboxSettings3});
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, true);
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxApisEnabled, true);
-  federated_learning::FlocId floc_id = federated_learning::FlocId::CreateValid(
-      123456, base::Time(), base::Time::Now(),
-      /*sorting_lsh_version=*/0);
-  floc_id.SaveToPrefs(profile()->GetTestingPrefService());
-
-  EXPECT_EQ(std::u16string(u"123456"),
-            privacy_sandbox_service()->GetFlocIdForDisplay());
-
-  // If the FLoC preference, the Sandbox Preference, or the feature is disabled,
-  // or the FLoC ID is invalid, the invalid string should be returned.
-  feature_list()->Reset();
-  feature_list()->InitWithFeatures(
-      {}, {blink::features::kInterestCohortAPIOriginTrial,
-           privacy_sandbox::kPrivacySandboxSettings3});
-  EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PRIVACY_SANDBOX_FLOC_INVALID),
-            privacy_sandbox_service()->GetFlocIdForDisplay());
-
-  feature_list()->Reset();
-  feature_list()->InitWithFeatures(
-      {blink::features::kInterestCohortAPIOriginTrial},
-      {privacy_sandbox::kPrivacySandboxSettings3});
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxApisEnabled, false);
-  EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PRIVACY_SANDBOX_FLOC_INVALID),
-            privacy_sandbox_service()->GetFlocIdForDisplay());
-
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxApisEnabled, true);
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, false);
-  EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PRIVACY_SANDBOX_FLOC_INVALID),
-            privacy_sandbox_service()->GetFlocIdForDisplay());
-
-  floc_id.UpdateStatusAndSaveToPrefs(
-      profile()->GetTestingPrefService(),
-      federated_learning::FlocId::Status::kInvalidReset);
   EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PRIVACY_SANDBOX_FLOC_INVALID),
             privacy_sandbox_service()->GetFlocIdForDisplay());
 }
 
 TEST_F(PrivacySandboxServiceTest, GetFlocIdNextUpdateForDisplay) {
-  // Check that date FLoC will be next updated is returned when available.
-  feature_list()->InitWithFeatures(
-      {blink::features::kInterestCohortAPIOriginTrial},
-      {privacy_sandbox::kPrivacySandboxSettings3});
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxApisEnabled, true);
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, true);
-
-  std::map<base::TimeDelta, std::u16string> offsets_to_expected_string = {
-      {base::Hours(23), l10n_util::GetPluralStringFUTF16(
-                            IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE, 0)},
-      {base::Hours(25), l10n_util::GetPluralStringFUTF16(
-                            IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE, 1)},
-      {base::Days(2), l10n_util::GetPluralStringFUTF16(
-                          IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE, 2)},
-      {base::Hours(60), l10n_util::GetPluralStringFUTF16(
-                            IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE, 3)},
-      {base::Hours(167),  // 1 hour less than 7 days.
-       l10n_util::GetPluralStringFUTF16(
-           IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE, 7)}};
-
-  for (const auto& offset_expected : offsets_to_expected_string) {
-    EXPECT_CALL(*mock_floc_id_provider(), GetApproximateNextComputeTime)
-        .WillOnce(testing::Return(base::Time::Now() + offset_expected.first));
-    EXPECT_EQ(offset_expected.second,
-              privacy_sandbox_service()->GetFlocIdNextUpdateForDisplay(
-                  base::Time::Now()));
-    testing::Mock::VerifyAndClearExpectations(mock_floc_id_provider());
-  }
-
-  // Check that disabling FLoC is also reflected in the returned string.
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, false);
-  EXPECT_CALL(*mock_floc_id_provider(), GetApproximateNextComputeTime).Times(0);
   EXPECT_EQ(l10n_util::GetStringUTF16(
                 IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE_INVALID),
             privacy_sandbox_service()->GetFlocIdNextUpdateForDisplay(
                 base::Time::Now()));
-  testing::Mock::VerifyAndClearExpectations(mock_floc_id_provider());
-
-  // Disabling the FLoC feature should also invalidate the next compute time.
-  feature_list()->Reset();
-  feature_list()->InitWithFeatures(
-      {}, {blink::features::kInterestCohortAPIOriginTrial,
-           privacy_sandbox::kPrivacySandboxSettings3});
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, true);
-  testing::Mock::VerifyAndClearExpectations(mock_floc_id_provider());
 }
 
 TEST_F(PrivacySandboxServiceTest, GetFlocResetExplanationForDisplay) {
-  // Check that the string description indicating what happens when the user
-  // resets the FLoC ID updates appropriately based on the feature parameter.
-  std::map<std::string, std::u16string> param_to_expected_string = {
-      {"1h", l10n_util::GetPluralStringFUTF16(
-                 IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION, 0)},
-      {"23h", l10n_util::GetPluralStringFUTF16(
-                  IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION, 0)},
-      {"24h", l10n_util::GetPluralStringFUTF16(
-                  IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION, 1)},
-      {"25h", l10n_util::GetPluralStringFUTF16(
-                  IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION, 1)},
-      {"60h", l10n_util::GetPluralStringFUTF16(
-                  IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION, 3)},
-      {"167h", l10n_util::GetPluralStringFUTF16(
-                   IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION, 7)},
-      {"168h", l10n_util::GetPluralStringFUTF16(
-                   IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION, 7)}};
-
-  for (const auto& param_expected : param_to_expected_string) {
-    feature_list()->InitAndEnableFeatureWithParameters(
-        federated_learning::kFederatedLearningOfCohorts,
-        {{"update_interval", param_expected.first}});
-    EXPECT_EQ(param_expected.second,
-              privacy_sandbox_service()->GetFlocResetExplanationForDisplay());
-    feature_list()->Reset();
-  }
+  EXPECT_EQ(l10n_util::GetPluralStringFUTF16(
+                IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION, 7),
+            privacy_sandbox_service()->GetFlocResetExplanationForDisplay());
 }
 
 TEST_F(PrivacySandboxServiceTest, GetFlocStatusForDisplay) {
-  // Check the status of the user's FLoC is correctly returned. This depends
-  // on whether the FLoC origin trial feature is enabled, and whether the user
-  // has FLoC enabled.
-  // TODO(crbug.com/1287951): FLoC is always disabled if OT is not active.
-  feature_list()->InitWithFeatures(
-      {blink::features::kInterestCohortAPIOriginTrial},
-      {privacy_sandbox::kPrivacySandboxSettings3});
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, true);
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxApisEnabled, true);
-  EXPECT_EQ(
-      l10n_util::GetStringUTF16(IDS_PRIVACY_SANDBOX_FLOC_STATUS_NOT_ACTIVE),
-      privacy_sandbox_service()->GetFlocStatusForDisplay());
-
-  // The Privacy Sandbox APIs pref & FLoC pref should disable the trial when
-  // either is disabled.
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxApisEnabled, false);
-  EXPECT_EQ(
-      l10n_util::GetStringUTF16(IDS_PRIVACY_SANDBOX_FLOC_STATUS_NOT_ACTIVE),
-      privacy_sandbox_service()->GetFlocStatusForDisplay());
-
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxApisEnabled, true);
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, false);
-  EXPECT_EQ(
-      l10n_util::GetStringUTF16(IDS_PRIVACY_SANDBOX_FLOC_STATUS_NOT_ACTIVE),
-      privacy_sandbox_service()->GetFlocStatusForDisplay());
-
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, true);
-  feature_list()->Reset();
-  feature_list()->InitWithFeatures(
-      {}, {blink::features::kInterestCohortAPIOriginTrial,
-           privacy_sandbox::kPrivacySandboxSettings3});
   EXPECT_EQ(
       l10n_util::GetStringUTF16(IDS_PRIVACY_SANDBOX_FLOC_STATUS_NOT_ACTIVE),
       privacy_sandbox_service()->GetFlocStatusForDisplay());
 }
 
 TEST_F(PrivacySandboxServiceTest, IsFlocIdResettable) {
-  // Check that if FLoC is functional the FLoC ID is resettable, regardless of
-  // whether the FLoC ID is currently valid.
-  feature_list()->InitWithFeatures(
-      {blink::features::kInterestCohortAPIOriginTrial},
-      {privacy_sandbox::kPrivacySandboxSettings3});
-  federated_learning::FlocId floc_id = federated_learning::FlocId::CreateValid(
-      123456, base::Time(), base::Time::Now(),
-      /*sorting_lsh_version=*/0);
-  floc_id.SaveToPrefs(profile()->GetTestingPrefService());
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, true);
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxApisEnabled, true);
-  EXPECT_TRUE(privacy_sandbox_service()->IsFlocIdResettable());
-
-  feature_list()->Reset();
-  feature_list()->InitWithFeatures(
-      {}, {blink::features::kInterestCohortAPIOriginTrial,
-           privacy_sandbox::kPrivacySandboxSettings3});
   EXPECT_FALSE(privacy_sandbox_service()->IsFlocIdResettable());
-
-  feature_list()->Reset();
-  feature_list()->InitWithFeatures(
-      {blink::features::kInterestCohortAPIOriginTrial},
-      {privacy_sandbox::kPrivacySandboxSettings3});
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, false);
-  EXPECT_FALSE(privacy_sandbox_service()->IsFlocIdResettable());
-
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, true);
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, false);
-  EXPECT_FALSE(privacy_sandbox_service()->IsFlocIdResettable());
-
-  floc_id.UpdateStatusAndSaveToPrefs(
-      profile()->GetTestingPrefService(),
-      federated_learning::FlocId::Status::kInvalidReset);
-  profile()->GetTestingPrefService()->SetBoolean(
-      prefs::kPrivacySandboxFlocEnabled, true);
-  EXPECT_TRUE(privacy_sandbox_service()->IsFlocIdResettable());
 }
 
 TEST_F(PrivacySandboxServiceTest, UserResetFlocID) {
diff --git a/chrome/browser/profile_resetter/profile_resetter_unittest.cc b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
index 4f0281c..e05afec7 100644
--- a/chrome/browser/profile_resetter/profile_resetter_unittest.cc
+++ b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
@@ -793,9 +793,8 @@
   EXPECT_TRUE(startup_list);
   std::vector<std::string> startup_pages;
   for (const auto& entry : startup_list->GetListDeprecated()) {
-    std::string url_str;
-    EXPECT_TRUE(entry.GetAsString(&url_str));
-    startup_pages.push_back(url_str);
+    ASSERT_TRUE(entry.is_string());
+    startup_pages.push_back(entry.GetString());
   }
   ASSERT_EQ(2u, startup_pages.size());
   EXPECT_EQ("http://goo.gl", startup_pages[0]);
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index a106ae0..bd0c693 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -64,8 +64,6 @@
 #include "chrome/browser/download/download_core_service.h"
 #include "chrome/browser/download/download_core_service_factory.h"
 #include "chrome/browser/download/download_manager_utils.h"
-#include "chrome/browser/federated_learning/floc_id_provider.h"
-#include "chrome/browser/federated_learning/floc_id_provider_factory.h"
 #include "chrome/browser/file_system_access/chrome_file_system_access_permission_context.h"
 #include "chrome/browser/file_system_access/file_system_access_permission_context_factory.h"
 #include "chrome/browser/heavy_ad_intervention/heavy_ad_service_factory.h"
@@ -824,10 +822,6 @@
 
   HttpsFirstModeServiceFactory::GetForProfile(this);
 
-  // The creation of FlocIdProvider should align with the start of a browser
-  // profile session, so initialize it here.
-  federated_learning::FlocIdProviderFactory::GetForProfile(this);
-
   // The Privacy Metrics service should start alongside each profile session.
   PrivacyMetricsServiceFactory::GetForProfile(this);
 
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index 1560fedc..6ca9ce2 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -31,7 +31,6 @@
       "commander:resources",
       "download_shelf:resources",
       "downloads:resources",
-      "federated_learning:resources",
       "feedback_webui:resources",
       "gaia_auth_host:resources",
       "history:resources",
@@ -133,7 +132,6 @@
       deps += [
         "bluetooth_internals:closure_compile",
         "discards:closure_compile",
-        "federated_learning:closure_compile",
         "feedback_webui/js:closure_compile",
         "gaia_auth_host:closure_compile",
         "inline_login:closure_compile",
@@ -309,7 +307,6 @@
   sources = [
     "$root_gen_dir/chrome/bluetooth_internals_resources.pak",
     "$root_gen_dir/chrome/dev_ui_browser_resources.pak",
-    "$root_gen_dir/chrome/floc_internals_resources.pak",
     "$root_gen_dir/chrome/internals_resources.pak",
     "$root_gen_dir/chrome/invalidations_resources.pak",
     "$root_gen_dir/chrome/net_internals_resources.pak",
@@ -326,7 +323,6 @@
   deps = [
     "//chrome/browser:dev_ui_browser_resources",
     "//chrome/browser/resources/bluetooth_internals:resources",
-    "//chrome/browser/resources/federated_learning:resources",
     "//chrome/browser/resources/internals:resources",
     "//chrome/browser/resources/invalidations:resources",
     "//chrome/browser/resources/media:webrtc_logs_resources",
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/list_commands_macro.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/list_commands_macro.js
index ac32846..510d07e 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/list_commands_macro.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/list_commands_macro.js
@@ -22,11 +22,11 @@
 
   /** @override */
   runMacro() {
-    // Note that this will open a new tab, probably ending the current
-    // Dictation by changing the input focus.
-    // TODO(crbug.com/1247299): This support page does not exist. Make
-    // sure to get the correct URL before launch.
-    window.open('https://support.google.com/chromebook?p=dictation', '_blank');
+    // Note that this will open a new tab, ending the current Dictation session
+    // by changing the input focus.
+    window.open(
+        'https://support.google.com/chromebook?p=text_dictation_m100',
+        '_blank');
     return this.createRunMacroResult_(/*isSuccess=*/ true);
   }
 }
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
index 9123bd06..9dafd59 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
@@ -187,13 +187,14 @@
    * @param {!cursors.Range} range The new range.
    * @param {boolean=} opt_focus Focus the range; defaults to true.
    * @param {Object=} opt_speechProps Speech properties.
-   * @param {boolean=} opt_shouldSetSelection If true, does set
-   *     the selection.
+   * @param {boolean=} opt_skipSettingSelection If true, does not set
+   *     the selection, otherwise it does by default.
    * @override
    */
-  navigateToRange(range, opt_focus, opt_speechProps, opt_shouldSetSelection) {
+  navigateToRange(range, opt_focus, opt_speechProps, opt_skipSettingSelection) {
     opt_focus = opt_focus === undefined ? true : opt_focus;
     opt_speechProps = opt_speechProps || {};
+    opt_skipSettingSelection = opt_skipSettingSelection || false;
     const prevRange = this.currentRange_;
 
     // Specialization for math output.
@@ -213,7 +214,8 @@
     let selectedRange;
     let msg;
 
-    if (this.pageSel_ && this.pageSel_.isValid() && range.isValid()) {
+    if (this.pageSel_ && this.pageSel_.isValid() && range.isValid() &&
+        !opt_skipSettingSelection) {
       // Suppress hints.
       o.withoutHints();
 
@@ -256,7 +258,7 @@
           this.pageSel_.select();
         }
       }
-    } else if (opt_shouldSetSelection) {
+    } else if (!opt_skipSettingSelection) {
       // Ensure we don't select the editable when we first encounter it.
       let lca = null;
       if (range.start.node && prevRange.start.node) {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_state.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_state.js
index d20bbed..bdc5fd0 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_state.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_state.js
@@ -104,8 +104,8 @@
    * @param {!cursors.Range} range The new range.
    * @param {boolean=} opt_focus Focus the range; defaults to true.
    * @param {Object=} opt_speechProps Speech properties.
-   * @param {boolean=} opt_shouldSetSelection If true, does set
-   *     the selection.
+   * @param {boolean=} opt_skipSettingSelection If true, does not set
+   *     the selection, otherwise it does by default.
    */
   navigateToRange: goog.abstractMethod,
 
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
index 1f11b0e..589217a 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
@@ -401,18 +401,16 @@
   let skipSync = false;
   let didNavigate = false;
   let tryScrolling = true;
-  let shouldSetSelection = false;
+  let skipSettingSelection = false;
   let skipInitialAncestry = true;
   switch (command) {
     case 'nextCharacter':
-      shouldSetSelection = true;
       didNavigate = true;
       speechProps['phoneticCharacters'] = true;
       unit = cursors.Unit.CHARACTER;
       current = current.move(cursors.Unit.CHARACTER, Dir.FORWARD);
       break;
     case 'previousCharacter':
-      shouldSetSelection = true;
       dir = Dir.BACKWARD;
       didNavigate = true;
       speechProps['phoneticCharacters'] = true;
@@ -430,13 +428,11 @@
       }
       return true;
     case 'nextWord':
-      shouldSetSelection = true;
       didNavigate = true;
       unit = cursors.Unit.WORD;
       current = current.move(cursors.Unit.WORD, Dir.FORWARD);
       break;
     case 'previousWord':
-      shouldSetSelection = true;
       dir = Dir.BACKWARD;
       didNavigate = true;
       unit = cursors.Unit.WORD;
@@ -496,33 +492,39 @@
       predErrorMsg = 'no_previous_combo_box';
       break;
     case 'nextEditText':
+      skipSettingSelection = true;
       pred = AutomationPredicate.editText;
       predErrorMsg = 'no_next_edit_text';
       CommandHandler.smartStickyMode_.startIgnoringRangeChanges();
       break;
     case 'previousEditText':
+      skipSettingSelection = true;
       dir = Dir.BACKWARD;
       pred = AutomationPredicate.editText;
       predErrorMsg = 'no_previous_edit_text';
       CommandHandler.smartStickyMode_.startIgnoringRangeChanges();
       break;
     case 'nextFormField':
+      skipSettingSelection = true;
       pred = AutomationPredicate.formField;
       predErrorMsg = 'no_next_form_field';
       CommandHandler.smartStickyMode_.startIgnoringRangeChanges();
       break;
     case 'previousFormField':
+      skipSettingSelection = true;
       dir = Dir.BACKWARD;
       pred = AutomationPredicate.formField;
       predErrorMsg = 'no_previous_form_field';
       CommandHandler.smartStickyMode_.startIgnoringRangeChanges();
       break;
     case 'previousGraphic':
+      skipSettingSelection = true;
       dir = Dir.BACKWARD;
       pred = AutomationPredicate.image;
       predErrorMsg = 'no_previous_graphic';
       break;
     case 'nextGraphic':
+      skipSettingSelection = true;
       pred = AutomationPredicate.image;
       predErrorMsg = 'no_next_graphic';
       break;
@@ -627,10 +629,12 @@
       break;
     case 'left':
     case 'previousObject':
+      skipSettingSelection = true;
       dir = Dir.BACKWARD;
       // Falls through.
     case 'right':
     case 'nextObject':
+      skipSettingSelection = true;
       didNavigate = true;
       unit = cursors.Unit.NODE;
       current = current.move(cursors.Unit.NODE, dir);
@@ -886,7 +890,6 @@
       output.withString(target.docUrl || '').go();
       return false;
     case 'toggleSelection':
-      shouldSetSelection = true;
       if (!ChromeVoxState.instance.pageSel_) {
         ChromeVoxState.instance.pageSel_ = ChromeVoxState.instance.currentRange;
         DesktopAutomationHandler.instance.ignoreDocumentSelectionFromAction(
@@ -923,7 +926,6 @@
     // Table commands.
     case 'previousRow': {
       skipSync = true;
-      shouldSetSelection = true;
       dir = Dir.BACKWARD;
       const tableOpts = {row: true, dir};
       pred = AutomationPredicate.makeTableCellPredicate(
@@ -934,7 +936,6 @@
     } break;
     case 'previousCol': {
       skipSync = true;
-      shouldSetSelection = true;
       dir = Dir.BACKWARD;
       const tableOpts = {col: true, dir};
       pred = AutomationPredicate.makeTableCellPredicate(
@@ -945,7 +946,6 @@
     } break;
     case 'nextRow': {
       skipSync = true;
-      shouldSetSelection = true;
       const tableOpts = {row: true, dir};
       pred = AutomationPredicate.makeTableCellPredicate(
           current.start.node, tableOpts);
@@ -955,7 +955,6 @@
     } break;
     case 'nextCol': {
       skipSync = true;
-      shouldSetSelection = true;
       const tableOpts = {col: true, dir};
       pred = AutomationPredicate.makeTableCellPredicate(
           current.start.node, tableOpts);
@@ -966,7 +965,6 @@
     case 'goToRowFirstCell':
     case 'goToRowLastCell': {
       skipSync = true;
-      shouldSetSelection = true;
       while (node && node.role !== RoleType.ROW) {
         node = node.parent;
       }
@@ -982,7 +980,6 @@
     } break;
     case 'goToColFirstCell': {
       skipSync = true;
-      shouldSetSelection = true;
       while (node && node.role !== RoleType.TABLE) {
         node = node.parent;
       }
@@ -1000,7 +997,6 @@
     } break;
     case 'goToColLastCell': {
       skipSync = true;
-      shouldSetSelection = true;
       dir = Dir.BACKWARD;
       while (node && node.role !== RoleType.TABLE) {
         node = node.parent;
@@ -1030,7 +1026,6 @@
     case 'goToFirstCell':
     case 'goToLastCell': {
       skipSync = true;
-      shouldSetSelection = true;
       while (node && node.role !== RoleType.TABLE) {
         node = node.parent;
       }
@@ -1277,7 +1272,7 @@
     }
 
     ChromeVoxState.instance.navigateToRange(
-        current, undefined, speechProps, shouldSetSelection);
+        current, undefined, speechProps, skipSettingSelection);
   }
 
   CommandHandler.onFinishCommand();
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js
index 1669a2f..47fcf54 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js
@@ -149,8 +149,7 @@
                       this.node_, Dir.FORWARD, AutomationPredicate.object,
                       {skipInitialSubtree: true}) ||
         this.node_;
-    ChromeVoxState.instance.navigateToRange(
-        cursors.Range.fromNode(after), true, {}, true);
+    ChromeVoxState.instance.navigateToRange(cursors.Range.fromNode(after));
   }
 
   /**
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js
index dc23d8e..3bee6c75 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js
@@ -2352,3 +2352,39 @@
         .replay();
   });
 });
+
+TEST_F('ChromeVoxEditingTest', 'JumpCommandsSyncSelection', function() {
+  const mockFeedback = this.createMockFeedback();
+  const site = `
+    <div contenteditable="true" role="textbox">
+      <p>first</p>
+      <h1>second</h1>
+      <p>third <a href="#">fourth</a></p>
+      <table border=1><r><td>fifth</td></tr></table>
+    </div>
+  `;
+  this.runWithLoadedTree(site, async function(root) {
+    await this.focusFirstTextField(root);
+
+    const textField = root.find({role: RoleType.TEXT_FIELD});
+    mockFeedback.expectSpeech('Text area')
+        .call(doCmd('nextTable'))
+        .expectSpeech('fifth', 'row 1 column 1', 'Table , 1 by 1')
+
+        // Verifies selection is where we expect.
+        .call(this.press(KeyCode.RIGHT, {shift: true, ctrl: true}))
+        .expectSpeech('fifth', 'row 1 column 1', 'Table , 1 by 1', 'selected')
+
+        .call(doCmd('previousHeading'))
+        .expectSpeech('second', 'Heading 1')
+        .call(this.press(KeyCode.RIGHT, {shift: true, ctrl: true}))
+        .expectSpeech('second', 'Heading 1', 'selected')
+
+        .call(doCmd('nextLink'))
+        .expectSpeech('fourth', 'Internal link')
+        .call(this.press(KeyCode.RIGHT, {shift: true, ctrl: true}))
+        .expectSpeech('fourth', 'Link', 'selected')
+
+        .replay();
+  });
+});
diff --git a/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js b/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js
index 8857cbc..2f0ea449 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js
@@ -210,37 +210,8 @@
    * @return {AutomationNode}
    */
   get selectionNode() {
-    let adjustedNode = this.node;
-    if (!adjustedNode) {
-      return null;
-    }
-
-    // Make no adjustments if we're within non-rich editable content.
-    if (adjustedNode.state[StateType.EDITABLE] &&
-        !adjustedNode.state[StateType.RICHLY_EDITABLE]) {
-      return adjustedNode;
-    }
-
-    // Selections over line break nodes are broken.
-    const parent = adjustedNode.parent;
-    const grandparent = parent && parent.parent;
-    if (parent && parent.role === RoleType.LINE_BREAK) {
-      adjustedNode = grandparent;
-    } else if (grandparent && grandparent.role === RoleType.LINE_BREAK) {
-      adjustedNode = grandparent.parent;
-    } else if (
-        this.index_ === cursors.NODE_INDEX ||
-        adjustedNode.role === RoleType.INLINE_TEXT_BOX ||
-        adjustedNode.nameFrom !== chrome.automation.NameFromType.CONTENTS) {
-      // A node offset or unselectable character offset.
-      adjustedNode = parent;
-    } else {
-      // A character offset into content.
-      adjustedNode =
-          adjustedNode.find({role: RoleType.STATIC_TEXT}) || adjustedNode;
-    }
-
-    return adjustedNode || null;
+    // TODO(accessibility): figure out if we still need the above property.
+    return this.node;
   }
 
   /**
@@ -250,48 +221,7 @@
    * @return {number}
    */
   get selectionIndex() {
-    let adjustedIndex = this.index_;
-
-    if (!this.node) {
-      return -1;
-    }
-
-    if (this.node.state[StateType.EDITABLE]) {
-      if (!this.node.state[StateType.RICHLY_EDITABLE]) {
-        return this.index_;
-      }
-      return this.index_ === cursors.NODE_INDEX ?
-          (this.node.indexInParent || 0) :
-          this.index_;
-    } else if (
-        this.node.role === RoleType.INLINE_TEXT_BOX &&
-        // Selections under a line break are broken.
-        this.node.parent && this.node.parent.role !== RoleType.LINE_BREAK) {
-      if (adjustedIndex === cursors.NODE_INDEX) {
-        adjustedIndex = 0;
-      }
-
-      let sibling = this.node.previousSibling;
-      while (sibling) {
-        adjustedIndex += sibling.name.length;
-        sibling = sibling.previousSibling;
-      }
-    } else if (
-        this.index_ === cursors.NODE_INDEX ||
-        this.node.nameFrom !== chrome.automation.NameFromType.CONTENTS) {
-      // A node offset or unselectable character offset.
-
-      // The selected node could have been adjusted upwards in the tree.
-      let childOfSelection = this.node;
-      do {
-        adjustedIndex = childOfSelection.indexInParent || 0;
-        childOfSelection = childOfSelection.parent;
-      } while (childOfSelection && childOfSelection !== this.selectionNode);
-    }
-    // A character offset into content is the remaining case. It requires no
-    // adjustment.
-
-    return adjustedIndex;
+    return this.index_ === cursors.NODE_INDEX ? 0 : this.index_;
   }
 
   /**
@@ -516,7 +446,11 @@
     let isTextIndex = false;
 
     while (newNode.firstChild) {
-      if (newNode.role === RoleType.STATIC_TEXT) {
+      if (AutomationPredicate.editText(newNode) &&
+          !newNode.state[StateType.MULTILINE]) {
+        // Do not reinterpret nodes and indices on this node.
+        break;
+      } else if (newNode.role === RoleType.STATIC_TEXT) {
         // Text offset.
         // Re-interpret the index as an offset into an inlineTextBox.
         isTextIndex = true;
diff --git a/chrome/browser/resources/chromeos/accessibility/common/cursors/cursors_test.js b/chrome/browser/resources/chromeos/accessibility/common/cursors/cursors_test.js
index cbed788..4946c2d 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/cursors/cursors_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/cursors/cursors_test.js
@@ -458,37 +458,6 @@
           });
     });
 
-TEST_F(
-    'AccessibilityExtensionCursorsTest', 'MultiLineOffsetSelection',
-    function() {
-      this.runWithLoadedTree(this.multiInlineDoc, function(root) {
-        const secondLine = root.firstChild.firstChild.firstChild.nextSibling;
-        assertEquals('inlineTextBox', secondLine.role);
-        assertEquals('diff ', secondLine.name);
-
-        let secondLineCursor = new cursors.Cursor(secondLine, -1);
-        // The selected node moves to the static text node.
-        assertEquals(
-            secondLineCursor.node.parent, secondLineCursor.selectionNode);
-
-        // This selects the entire node via a character offset.
-        assertEquals(6, secondLineCursor.selectionIndex);
-
-        // Index into the characters.
-        secondLineCursor = new cursors.Cursor(secondLine, 1);
-        assertEquals(7, secondLineCursor.selectionIndex);
-
-        // Now, try selecting via node offsets.
-        let cursor = new cursors.Cursor(root.firstChild, -1);
-        assertEquals(root, cursor.selectionNode);
-        assertEquals(0, cursor.selectionIndex);
-
-        cursor = new cursors.Cursor(root.firstChild.nextSibling, -1);
-        assertEquals(root, cursor.selectionNode);
-        assertEquals(1, cursor.selectionIndex);
-      });
-    });
-
 TEST_F('AccessibilityExtensionCursorsTest', 'InlineElementOffset', function() {
   this.runWithLoadedTree(
       `
@@ -638,94 +607,6 @@
     });
 
 TEST_F(
-    'AccessibilityExtensionCursorsTest', 'SelectionAdjustmentsRichText',
-    function() {
-      this.runWithLoadedTree(
-          `
-    <div contenteditable><p>test</p><p>123</p></div>
-  `,
-          function(root) {
-            const textField = root.firstChild;
-            const paragraph = textField.firstChild;
-            const otherParagraph = textField.lastChild;
-            const staticText = paragraph.firstChild;
-            const otherStaticText = otherParagraph.firstChild;
-
-            // Ranges by default surround a node. Ensure it results in a
-            // collapsed selection.
-            let range = cursors.Range.fromNode(staticText);
-            assertEquals(0, range.start.selectionIndex);
-            assertEquals(0, range.end.selectionIndex);
-            assertEquals(paragraph, range.start.selectionNode);
-            assertEquals(paragraph, range.end.selectionNode);
-
-            // Text selection.
-            range = new cursors.Range(
-                new cursors.Cursor(staticText, 2),
-                new cursors.Cursor(staticText, 4));
-            assertEquals(2, range.start.selectionIndex);
-            assertEquals(4, range.end.selectionIndex);
-            assertEquals(staticText, range.start.selectionNode);
-            assertEquals(staticText, range.end.selectionNode);
-
-            // Tree selection.
-            range = cursors.Range.fromNode(paragraph);
-            assertEquals(0, range.start.selectionIndex);
-            assertEquals(0, range.end.selectionIndex);
-            assertEquals(textField, range.start.selectionNode);
-            assertEquals(textField, range.end.selectionNode);
-
-            range = cursors.Range.fromNode(otherStaticText);
-            assertEquals(0, range.start.selectionIndex);
-            assertEquals(0, range.end.selectionIndex);
-            assertEquals(otherParagraph, range.start.selectionNode);
-            assertEquals(otherParagraph, range.end.selectionNode);
-
-            range = cursors.Range.fromNode(otherParagraph);
-            assertEquals(1, range.start.selectionIndex);
-            assertEquals(1, range.end.selectionIndex);
-            assertEquals(textField, range.start.selectionNode);
-            assertEquals(textField, range.end.selectionNode);
-          });
-    });
-
-TEST_F(
-    'AccessibilityExtensionCursorsTest', 'SelectionAdjustmentsNonRichText',
-    function() {
-      this.runWithLoadedTree(
-          `
-    <input type="text"></input>
-    <textarea></textarea>
-  `,
-          function(root) {
-            const testEditable = function(edit) {
-              // Occurs as part of ordinary (non-text) navigation.
-              let range = cursors.Range.fromNode(edit);
-              assertEquals(-1, range.start.selectionIndex);
-              assertEquals(-1, range.end.selectionIndex);
-              assertEquals(edit, range.start.selectionNode);
-              assertEquals(edit, range.end.selectionNode);
-
-              // Occurs as a result of explicit text nav e.g. nextCharacter
-              // command.
-              range = new cursors.Range(
-                  new cursors.Cursor(edit, 2), new cursors.Cursor(edit, 3));
-              assertEquals(2, range.start.selectionIndex);
-              assertEquals(3, range.end.selectionIndex);
-              assertEquals(edit, range.start.selectionNode);
-              assertEquals(edit, range.end.selectionNode);
-            };
-
-            const textField = root.firstChild.firstChild;
-            const textArea = root.lastChild.lastChild;
-
-            // Both of these should behave in the same way.
-            testEditable(textField);
-            testEditable(textArea);
-          });
-    });
-
-TEST_F(
     'AccessibilityExtensionCursorsTest', 'MovementByWordThroughNonInlineText',
     function() {
       this.runCursorMovesOnDocument(this.buttonAndInlineTextDoc, [
diff --git a/chrome/browser/resources/federated_learning/BUILD.gn b/chrome/browser/resources/federated_learning/BUILD.gn
deleted file mode 100644
index 46d2bf4a..0000000
--- a/chrome/browser/resources/federated_learning/BUILD.gn
+++ /dev/null
@@ -1,86 +0,0 @@
-# Copyright 2021 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/common/features.gni")
-import("//third_party/closure_compiler/compile_js.gni")
-import("//tools/grit/grit_rule.gni")
-import("//tools/grit/preprocess_if_expr.gni")
-import("//ui/webui/resources/tools/generate_grd.gni")
-import("//ui/webui/webui_features.gni")
-
-preprocess_folder = "preprocessed"
-preprocess_manifest = "preprocessed_manifest.json"
-preprocess_mojo_manifest = "preprocessed_mojo_manifest.json"
-
-generate_grd("build_grd") {
-  grd_prefix = "floc_internals"
-  out_grd = "$target_gen_dir/resources.grd"
-  input_files = [
-    "floc_internals.html",
-    "floc_internals.css",
-  ]
-  input_files_base_dir = rebase_path(".", "//")
-
-  deps = [
-    ":preprocess",
-    ":preprocess_mojo",
-  ]
-  manifest_files = [
-    "$target_gen_dir/$preprocess_manifest",
-    "$target_gen_dir/$preprocess_mojo_manifest",
-  ]
-}
-
-preprocess_if_expr("preprocess") {
-  in_folder = "./"
-  out_folder = "$target_gen_dir/$preprocess_folder"
-  out_manifest = "$target_gen_dir/$preprocess_manifest"
-  in_files = [ "floc_internals.js" ]
-}
-
-preprocess_if_expr("preprocess_mojo") {
-  deps =
-      [ "//chrome/browser/ui/webui/federated_learning:mojo_bindings_webui_js" ]
-  in_folder =
-      "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/federated_learning/"
-  out_folder = "$target_gen_dir/$preprocess_folder"
-  out_manifest = "$target_gen_dir/$preprocess_mojo_manifest"
-  in_files = [ "floc_internals.mojom-webui.js" ]
-}
-
-grit("resources") {
-  defines = chrome_grit_defines
-
-  # These arguments are needed since the grd is generated at build time.
-  enable_input_discovery_for_gn_analyze = false
-  source = "$target_gen_dir/resources.grd"
-  deps = [ ":build_grd" ]
-
-  outputs = [
-    "grit/floc_internals_resources.h",
-    "grit/floc_internals_resources_map.cc",
-    "grit/floc_internals_resources_map.h",
-    "floc_internals_resources.pak",
-  ]
-  output_dir = "$root_gen_dir/chrome"
-}
-
-js_type_check("closure_compile") {
-  closure_flags = default_closure_args + mojom_js_args + [
-                    "js_module_root=" + rebase_path(".", root_build_dir),
-                    "js_module_root=" + rebase_path(
-                            "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/federated_learning",
-                            root_build_dir),
-                  ]
-
-  deps = [ ":floc_internals" ]
-}
-
-js_library("floc_internals") {
-  deps = [
-    "//chrome/browser/ui/webui/federated_learning:mojo_bindings_webui_js",
-    "//ui/webui/resources/js:assert.m",
-    "//ui/webui/resources/js:util.m",
-  ]
-}
diff --git a/chrome/browser/resources/federated_learning/OWNERS b/chrome/browser/resources/federated_learning/OWNERS
deleted file mode 100644
index 7d2ce91..0000000
--- a/chrome/browser/resources/federated_learning/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://chrome/browser/ui/webui/federated_learning/OWNERS
diff --git a/chrome/browser/resources/federated_learning/floc_internals.css b/chrome/browser/resources/federated_learning/floc_internals.css
deleted file mode 100644
index e710cb4..0000000
--- a/chrome/browser/resources/federated_learning/floc_internals.css
+++ /dev/null
@@ -1,14 +0,0 @@
-/* Copyright 2021 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. */
-
-.large-bold-div {
-  font-size: 2em;
-  font-weight: bold;
-  line-height: 1.5em;
-}
-
-span {
-  font-size: 1.5em;
-  line-height: 1.5em;
-}
diff --git a/chrome/browser/resources/federated_learning/floc_internals.html b/chrome/browser/resources/federated_learning/floc_internals.html
deleted file mode 100644
index fe08bbfd..0000000
--- a/chrome/browser/resources/federated_learning/floc_internals.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!-- Copyright 2021 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.-->
-<!doctype html>
-<html dir="ltr" lang="en">
-<head>
-  <meta charset="utf-8">
-  <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
-  <link rel="stylesheet" href="chrome://resources/css/roboto.css">
-
-  <link rel="stylesheet" href="floc_internals.css">
-  <script type="module" src="floc_internals.js"></script>
-  <title>Floc Internals</title>
-</head>
-<body>
-
-<div class="large-bold-div">FLoC Status</div>
-<div id="floc-status-div"></div>
-
-<div class="large-bold-div">Features Enabled Status</div>
-<div id="floc-features-div"></div>
-
-<div class="large-bold-div">Parameters</div>
-<div id="floc-params-div"></div>
-
-<template id="result-template">
-<div>
-  <span></span>
-  <span></span>
-</div>
-</template>
-
-</body>
-</html>
diff --git a/chrome/browser/resources/federated_learning/floc_internals.js b/chrome/browser/resources/federated_learning/floc_internals.js
deleted file mode 100644
index e091bf8..0000000
--- a/chrome/browser/resources/federated_learning/floc_internals.js
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2021 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 {$} from 'chrome://resources/js/util.m.js';
-
-import {PageHandler} from './floc_internals.mojom-webui.js';
-
-/**
- * Creates a single row of the status entries.
- * @param {string} name The status identifier name.
- * @param {string} value The text content that describes the status.
- * @return {!Node}
- */
-function createRow(name, value) {
-  const row = $('result-template').content.cloneNode(true);
-  row.querySelectorAll('span')[0].textContent = name + ': ';
-  row.querySelectorAll('span')[1].textContent = value;
-  return row;
-}
-
-/**
- * Converts a time period in seconds into a user-readable string.
- * @param {number} totalMicroseconds The total microseconds in time.
- * @return {string}
- */
-function formatTimeDuration(totalMicroseconds) {
-  if (totalMicroseconds > Number.MAX_SAFE_INTEGER) {
-    return '+inf';
-  }
-
-  let totalSeconds = Math.round(totalMicroseconds / 1000000);
-
-  const days = Math.round(totalSeconds / 3600 / 24);
-  totalSeconds %= 3600 * 24;
-  const hours = Math.round(totalSeconds / 3600);
-  totalSeconds %= 3600;
-  const minutes = Math.round(totalSeconds / 60);
-  const seconds = Math.round(totalSeconds % 60);
-  return days + 'd-' + hours + 'h-' + minutes + 'm-' + seconds + 's';
-}
-
-/**
- * Converts a point of time into a user-readable string.
- * @param {number} microsecondsSinceWindowsEpoch The total microseconds since
- *     Windows FILETIME epoch.
- * @return {string}
- */
-function formatTime(microsecondsSinceWindowsEpoch) {
-  if (microsecondsSinceWindowsEpoch === 0) {
-    return 'N/A';
-  }
-
-  const unixWindowsOffsetMicroseconds = 11644473600000000;
-  const msSinceUnixEpoch =
-      (microsecondsSinceWindowsEpoch - unixWindowsOffsetMicroseconds) / 1000;
-
-  return new Date(msSinceUnixEpoch).toLocaleString();
-}
-
-document.addEventListener('DOMContentLoaded', function() {
-  PageHandler.getRemote().getFlocStatus().then((response) => {
-    const status = response.status;
-
-    const statusDiv = $('floc-status-div');
-    if (status.id) {
-      statusDiv.appendChild(createRow('id', status.id));
-      statusDiv.appendChild(createRow('version', status.version));
-    } else {
-      statusDiv.appendChild(createRow('id', 'N/A'));
-      statusDiv.appendChild(createRow('version', 'N/A'));
-    }
-    statusDiv.appendChild(createRow(
-        'last compute time',
-        formatTime(Number(status.computeTime.internalValue))));
-
-    const featuresDiv = $('floc-features-div');
-    featuresDiv.appendChild(createRow(
-        'FlocPagesWithAdResourcesDefaultIncludedInFlocComputation',
-        status.featurePagesWithAdResourcesDefaultIncludedInFlocComputation
-            .toString()));
-    featuresDiv.appendChild(createRow(
-        'InterestCohortAPIOriginTrial',
-        status.featureInterestCohortApiOriginTrial.toString()));
-    featuresDiv.appendChild(createRow(
-        'InterestCohortFeaturePolicy',
-        status.featureInterestCohortFeaturePolicy.toString()));
-
-    const paramsDiv = $('floc-params-div');
-    paramsDiv.appendChild(createRow(
-        'FlocIdScheduledUpdateInterval',
-        formatTimeDuration(
-            Number(status.featureParamScheduledUpdateInterval.microseconds))));
-    paramsDiv.appendChild(createRow(
-        'FlocIdMinimumHistoryDomainSizeRequired',
-        status.featureParamMinimumHistoryDomainSizeRequired.toString()));
-    paramsDiv.appendChild(createRow(
-        'FlocIdFinchConfigVersion',
-        status.featureParamFinchConfigVersion.toString()));
-  });
-});
diff --git a/chrome/browser/resources/new_tab_page/realbox/icons/BUILD.gn b/chrome/browser/resources/new_tab_page/realbox/icons/BUILD.gn
index fa28a85..dad0dc45 100644
--- a/chrome/browser/resources/new_tab_page/realbox/icons/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/realbox/icons/BUILD.gn
@@ -24,6 +24,7 @@
     "drive_video.svg",
     "extension_app.svg",
     "finance.svg",
+    "google_g.svg",
     "note.svg",
     "page.svg",
     "sites.svg",
diff --git a/chrome/browser/resources/new_tab_page/realbox/icons/google_g.svg b/chrome/browser/resources/new_tab_page/realbox/icons/google_g.svg
new file mode 100644
index 0000000..996bf77
--- /dev/null
+++ b/chrome/browser/resources/new_tab_page/realbox/icons/google_g.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 48 48" width="24px"><path d="M0-1h48v48H0z" fill="none"/><circle cx="24" cy="23" fill="#FFF" r="22"/><path d="M24 1.23c12.11 0 21.94 9.79 22 21.89v-.11c0-12.15-9.85-22-22-22C11.85 1 2 10.85 2 23v.11c.06-12.09 9.89-21.88 22-21.88z" fill="#FFF" fill-opacity=".2"/><path d="M24 44.77c12.11 0 21.94-9.79 22-21.89v.11c0 12.15-9.85 22-22 22C11.85 45 2 35.15 2 23v-.11c.06 12.09 9.89 21.88 22 21.88z" fill="#263238" fill-opacity=".15"/><path d="M33.76 34.26c2.75-2.56 4.49-6.37 4.49-11.26 0-.89-.08-1.84-.29-3H24.01v5.99h8.03c-.4 2.02-1.5 3.56-3.07 4.56v.75l3.91 2.97h.88z" fill="#4285F4"/><path d="M15.58 25.77A8.845 8.845 0 0 0 24 31.86c1.92 0 3.62-.46 4.97-1.31l4.79 3.71C31.14 36.7 27.65 38 24 38c-5.93 0-11.01-3.4-13.45-8.36l.17-1.01 4.06-2.85h.8z" fill="#34A853"/><path d="M15.59 20.21a8.864 8.864 0 0 0 0 5.58l-5.03 3.86c-.98-2-1.53-4.25-1.53-6.64 0-2.39.55-4.64 1.53-6.64l1-.22 3.81 2.98.22 1.08z" fill="#FBBC05"/><path d="M24 14.14c2.11 0 4.02.75 5.52 1.98l4.36-4.36C31.22 9.43 27.81 8 24 8c-5.93 0-11.01 3.4-13.45 8.36l5.03 3.85A8.86 8.86 0 0 1 24 14.14z" fill="#EA4335"/><radialGradient cx="298.159" cy="-106.681" gradientTransform="translate(-264.667 105.437) scale(.917)" gradientUnits="userSpaceOnUse" id="aa" r="47.683"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><circle cx="24" cy="23" fill="url(#aa)" fill-opacity=".1" r="22"/></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/new_tab_page/realbox/realbox.html b/chrome/browser/resources/new_tab_page/realbox/realbox.html
index 3cce331..fcfc8d56 100644
--- a/chrome/browser/resources/new_tab_page/realbox/realbox.html
+++ b/chrome/browser/resources/new_tab_page/realbox/realbox.html
@@ -1,8 +1,9 @@
 <style>
   :host {
+    --ntp-realbox-shadow: 0 1px 6px 0 rgba(32, 33, 36, .28);
     --ntp-realbox-height: 44px;
     border-radius: calc(0.5 * var(--ntp-realbox-height));
-    box-shadow: 0 1px 6px 0 rgba(32, 33, 36, .28);
+    box-shadow: var(--ntp-realbox-shadow);
     font-size: 16px;
     height: var(--ntp-realbox-height);
   }
@@ -17,6 +18,21 @@
     box-shadow: none;
   }
 
+  :host([match-searchbox]) {
+    box-shadow: none;
+    --ntp-realbox-height: 46px;
+    box-sizing: border-box;
+  }
+
+  :host([match-searchbox]:not([matches-are-visible])) {
+    border: 1px solid var(--ntp-border-color);
+  }
+
+  :host([match-searchbox]:not([matches-are-visible]):hover)  {
+    border: 1px solid var(--search-box-bg-hovered, white);
+    box-shadow: var(--ntp-realbox-shadow);
+  }
+
   #inputWrapper {
     height: 100%;
     position: relative;
diff --git a/chrome/browser/resources/new_tab_page/realbox/realbox.ts b/chrome/browser/resources/new_tab_page/realbox/realbox.ts
index bcffdd61..b525074 100644
--- a/chrome/browser/resources/new_tab_page/realbox/realbox.ts
+++ b/chrome/browser/resources/new_tab_page/realbox/realbox.ts
@@ -63,6 +63,13 @@
         observer: 'onThemeChange_',
       },
 
+      /** Whether the realbox should match the searchbox. */
+      matchSearchbox: {
+        type: Boolean,
+        value: () => loadTimeData.getBoolean('realboxMatchSearchboxTheme'),
+        reflectToAttribute: true,
+      },
+
       //========================================================================
       // Private properties
       //========================================================================
@@ -161,6 +168,7 @@
   }
 
   matchesAreVisible: boolean;
+  matchSearchbox: boolean;
   theme: SearchBoxTheme;
   private charTypedTime_: number;
   private isDeletingInput_: boolean;
diff --git a/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.html b/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.html
index 3b92e99..b8b7c95 100644
--- a/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.html
+++ b/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.html
@@ -13,6 +13,10 @@
     padding-top: var(--ntp-realbox-height);
   }
 
+  :host([round-corners]) #selector {
+    border-radius: calc(0.5 * var(--ntp-realbox-height));
+  }
+
   @media (forced-colors: active) {
     #selector {
       border: 1px solid ActiveBorder;
diff --git a/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.ts b/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.ts
index fc4294d..5afa587 100644
--- a/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.ts
+++ b/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.ts
@@ -42,6 +42,13 @@
         type: Object,
       },
 
+      /** Whether the realbox should have rounded corners. */
+      roundCorners: {
+        type: Boolean,
+        value: () => loadTimeData.getBoolean('roundCorners'),
+        reflectToAttribute: true,
+      },
+
       /** Index of the selected match. */
       selectedMatchIndex: {
         type: Number,
@@ -79,6 +86,7 @@
   }
 
   result: AutocompleteResult;
+  roundCorners: boolean;
   selectedMatchIndex: number;
   theme: SearchBoxTheme;
   private groupIds_: number[];
diff --git a/chrome/browser/resources/new_tab_page/realbox/realbox_icon.html b/chrome/browser/resources/new_tab_page/realbox/realbox_icon.html
index cf247d3..4be2f47 100644
--- a/chrome/browser/resources/new_tab_page/realbox/realbox_icon.html
+++ b/chrome/browser/resources/new_tab_page/realbox/realbox_icon.html
@@ -60,8 +60,8 @@
     background-color: white;
   }
 
-  :host([in-searchbox][background-image='google_g.png']) #icon {
-    background-size: 12px;
+  :host([in-searchbox][background-image='realbox/icons/google_g.svg']) #icon {
+    background-size: 24px;
   }
 
   :host([in-searchbox][mask-image='search.svg']) #icon {
diff --git a/chrome/browser/resources/new_tab_page/realbox/realbox_icon.ts b/chrome/browser/resources/new_tab_page/realbox/realbox_icon.ts
index b5325774..240dc2e 100644
--- a/chrome/browser/resources/new_tab_page/realbox/realbox_icon.ts
+++ b/chrome/browser/resources/new_tab_page/realbox/realbox_icon.ts
@@ -105,7 +105,7 @@
       } else {
         return '';
       }
-    } else if (this.defaultIcon === 'google_g.png') {
+    } else if (this.defaultIcon === 'realbox/icons/google_g.svg') {
       return this.defaultIcon;
     } else {
       return '';
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html
index eb3f0b8..937f269 100644
--- a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html
+++ b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html
@@ -13,10 +13,18 @@
         color: var(--cr-secondary-text-color);
         margin-inline-start: 16px;
       }
+
+      #virtualCardLabel {
+        margin-inline-start: 8px;
+      }
     </style>
     <div class="list-item">
       <div class="type-column">
         <span id="creditCardLabel">[[creditCard.metadata.summaryLabel]]</span>
+        <span id="virtualCardLabel"
+            hidden$="[[!isVirtualCardEnrolled_(creditCard.metadata)]]">
+          $i18n{virtualCardEnabled}
+        </span>
         <span class="payments-label"
             hidden$="[[creditCard.metadata.isLocal]]">
           <span hidden$="[[creditCard.metadata.isCached]]">
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts
index 3bc9841..22947f3 100644
--- a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts
+++ b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts
@@ -15,6 +15,7 @@
 
 import {I18nMixin} from '//resources/js/i18n_mixin.js';
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {loadTimeData} from '../i18n_setup.js';
 
 const SettingsCreditCardListEntryElementBase = I18nMixin(PolymerElement);
 
@@ -32,10 +33,22 @@
     return {
       /** A saved credit card. */
       creditCard: Object,
+
+      /**
+       * Whether virtual card enrollment management on settings page is enabled.
+       */
+      virtualCardEnrollmentEnabled_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean('virtualCardEnrollmentEnabled');
+        },
+        readOnly: true,
+      },
     };
   }
 
   creditCard: chrome.autofillPrivate.CreditCardEntry;
+  private virtualCardEnrollmentEnabled_: boolean;
 
   /**
    * Opens the credit card action menu.
@@ -86,12 +99,24 @@
   }
 
   /**
-   * The 3-dot menu should not be shown if the card is entirely remote.
+   * The 3-dot menu should be shown if the card is not a masked server card or
+   * if the card is eligble for virtual card enrollment.
    */
   private showDots_(): boolean {
     return !!(
         this.creditCard.metadata!.isLocal ||
-        this.creditCard.metadata!.isCached);
+        this.creditCard.metadata!.isCached ||
+        this.isVirtualCardEnrollmentEligible_());
+  }
+
+  private isVirtualCardEnrollmentEligible_(): boolean {
+    return this.virtualCardEnrollmentEnabled_ &&
+        this.creditCard.metadata!.isVirtualCardEnrollmentEligible!;
+  }
+
+  private isVirtualCardEnrolled_(): boolean {
+    return this.virtualCardEnrollmentEnabled_ &&
+        this.creditCard.metadata!.isVirtualCardEnrolled!;
   }
 }
 
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.html b/chrome/browser/resources/settings/autofill_page/payments_section.html
index d469fe8..75a4b954 100644
--- a/chrome/browser/resources/settings/autofill_page/payments_section.html
+++ b/chrome/browser/resources/settings/autofill_page/payments_section.html
@@ -78,7 +78,10 @@
 
     <cr-action-menu id="creditCardSharedMenu" role-description="$i18n{menu}">
       <button id="menuEditCreditCard" class="dropdown-item"
-          on-click="onMenuEditCreditCardTap_">$i18n{edit}</button>
+          on-click="onMenuEditCreditCardTap_">
+        [[getMenuEditCardText_(activeCreditCard_.metadata.isLocal)]]
+      </button>
+
       <button id="menuRemoveCreditCard" class="dropdown-item"
           hidden$="[[!activeCreditCard_.metadata.isLocal]]"
           on-click="onMenuRemoveCreditCardTap_">$i18n{removeCreditCard}</button>
@@ -87,6 +90,15 @@
           hidden$="[[!activeCreditCard_.metadata.isCached]]">
         $i18n{clearCreditCard}
       </button>
+
+      <button id="menuAddVirtualCard" class="dropdown-item"
+          hidden$="[[!shouldShowAddVirtualCardButton_(activeCreditCard_)]]">
+        $i18n{addVirtualCard}
+      </button>
+      <button id="menuRemoveVirtualCard" class="dropdown-item"
+          hidden$="[[!shouldShowRemoveVirtualCardButton_(activeCreditCard_)]]">
+        $i18n{removeVirtualCard}
+      </button>
     </cr-action-menu>
     <template is="dom-if" if="[[showCreditCardDialog_]]" restamp>
       <settings-credit-card-edit-dialog credit-card="[[activeCreditCard_]]"
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.ts b/chrome/browser/resources/settings/autofill_page/payments_section.ts
index fcc334a..c26e7d38 100644
--- a/chrome/browser/resources/settings/autofill_page/payments_section.ts
+++ b/chrome/browser/resources/settings/autofill_page/payments_section.ts
@@ -55,6 +55,8 @@
     menuClearCreditCard: HTMLElement,
     menuEditCreditCard: HTMLElement,
     menuRemoveCreditCard: HTMLElement,
+    menuAddVirtualCard: HTMLElement,
+    menuRemoveVirtualCard: HTMLElement,
     migrateCreditCards: HTMLElement,
     paymentsList: HTMLElement,
   };
@@ -121,6 +123,17 @@
         },
         readOnly: true,
       },
+
+      /**
+       * Whether virtual card enroll management on settings page is enabled.
+       */
+      virtualCardEnrollmentEnabled_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean('virtualCardEnrollmentEnabled');
+        },
+        readOnly: true,
+      },
     };
   }
 
@@ -132,6 +145,7 @@
   private showCreditCardDialog_: boolean;
   private migratableCreditCardsInfo_: string;
   private migrationEnabled_: boolean;
+  private virtualCardEnrollmentEnabled_: boolean;
   private activeDialogAnchor_: HTMLElement|null;
   private paymentsManager_: PaymentsManagerProxy =
       PaymentsManagerImpl.getInstance();
@@ -352,6 +366,32 @@
 
     return true;
   }
+
+  private getMenuEditCardText_(isLocalCard: boolean): string {
+    return this.i18n(isLocalCard ? 'edit' : 'editServerCard');
+  }
+
+  private shouldShowAddVirtualCardButton_(): boolean {
+    if (!this.virtualCardEnrollmentEnabled_ ||
+        this.activeCreditCard_ === null ||
+        this.activeCreditCard_.metadata === null) {
+      return false;
+    }
+    return !!this.activeCreditCard_!.metadata!
+                 .isVirtualCardEnrollmentEligible &&
+        !this.activeCreditCard_!.metadata!.isVirtualCardEnrolled;
+  }
+
+  private shouldShowRemoveVirtualCardButton_(): boolean {
+    if (!this.virtualCardEnrollmentEnabled_ ||
+        this.activeCreditCard_ === null ||
+        this.activeCreditCard_.metadata === null) {
+      return false;
+    }
+    return !!this.activeCreditCard_!.metadata!
+                 .isVirtualCardEnrollmentEligible &&
+        !!this.activeCreditCard_!.metadata!.isVirtualCardEnrolled;
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html
index 1b13f69..c55a175 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html
@@ -31,7 +31,8 @@
       </cr-expand-button>
       <template is="dom-if" if="[[addConnectionExpanded_]]">
         <div class="list-frame vertical-list">
-          <template is="dom-if" if="[[wifiIsEnabled_(deviceStates)]]">
+          <template is="dom-if" if="[[shouldShowAddWiFiRow_(globalPolicy_,
+              managedNetworkAvailable, deviceStates)]]">
             <div actionable class="list-item" on-click="onAddWiFiTap_">
               <div class="start settings-box-text"
                   id="add-wifi-label" aria-hidden="true">
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js
index d75fd8ff..b911428 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js
@@ -813,9 +813,22 @@
   /**
    * @param {!mojom.GlobalPolicy} globalPolicy
    * @param {boolean} managedNetworkAvailable
+   * @param {!Array<!OncMojo.DeviceStateProperties>} deviceStates
+   * @return {boolean}
+   * @private
+   */
+  shouldShowAddWiFiRow_(globalPolicy, managedNetworkAvailable, deviceStates) {
+    return this.allowAddWiFiConnection_(
+               globalPolicy, managedNetworkAvailable) &&
+        this.wifiIsEnabled_(deviceStates);
+  },
+
+  /**
+   * @param {!mojom.GlobalPolicy} globalPolicy
+   * @param {boolean} managedNetworkAvailable
    * @return {boolean}
    */
-  allowAddConnection_(globalPolicy, managedNetworkAvailable) {
+  allowAddWiFiConnection_(globalPolicy, managedNetworkAvailable) {
     if (!globalPolicy) {
       return true;
     }
@@ -826,6 +839,18 @@
   },
 
   /**
+   * @param {!mojom.GlobalPolicy} globalPolicy
+   * @param {boolean} managedNetworkAvailable
+   * @return {boolean}
+   */
+  allowAddConnection_(globalPolicy, managedNetworkAvailable) {
+    if (!this.vpnIsProhibited_) {
+      return true;
+    }
+    return this.allowAddWiFiConnection_(globalPolicy, managedNetworkAvailable);
+  },
+
+  /**
    * @param {!mojom.VpnProvider} provider
    * @return {string}
    */
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js
index 6bbb493..6475dbef 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js
@@ -307,14 +307,10 @@
       }
     },
 
-    /**
-     * TODO(crbug.com/1247299): This support page does not exist. Make sure to
-     * get the correct URL before launch.
-     * @private
-     */
+    /** @private */
     dictationLearnMoreUrl_: {
       type: String,
-      value: 'https://support.google.com/chromebook?p=dictation',
+      value: 'https://support.google.com/chromebook?p=text_dictation_m100',
     },
 
     /**
diff --git a/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate.cc b/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate.cc
index e00ea3e2..bcda2d7 100644
--- a/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate.cc
@@ -71,9 +71,12 @@
     std::unique_ptr<TPIncident> incident(
         new ClientIncidentReport_IncidentData_TrackedPreferenceIncident());
     incident->set_path(pref_path);
-    if (!value || (!value->GetAsString(incident->mutable_atomic_value()) &&
-                   !base::JSONWriter::Write(
-                       std::move(*value), incident->mutable_atomic_value()))) {
+    if (!value) {
+      incident->clear_atomic_value();
+    } else if (value->is_string()) {
+      *incident->mutable_atomic_value() = value->GetString();
+    } else if (!base::JSONWriter::Write(std::move(*value),
+                                        incident->mutable_atomic_value())) {
       incident->clear_atomic_value();
     }
     incident->set_value_state(proto_value_state);
diff --git a/chrome/browser/search/most_visited_iframe_source_unittest.cc b/chrome/browser/search/most_visited_iframe_source_unittest.cc
index 0ed57c5..03e6710e 100644
--- a/chrome/browser/search/most_visited_iframe_source_unittest.cc
+++ b/chrome/browser/search/most_visited_iframe_source_unittest.cc
@@ -114,7 +114,6 @@
 
   content::BrowserTaskEnvironment task_environment_;
 
-  net::TestURLRequestContext test_url_request_context_;
   TestingProfile profile_;
   std::unique_ptr<TestMostVisitedIframeSource> source_;
   scoped_refptr<base::RefCountedMemory> response_;
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index d88422dab..51fe452d 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -46,7 +46,6 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "components/bookmarks/test/bookmark_test_helpers.h"
-#include "components/federated_learning/features/features.h"
 #include "components/gcm_driver/gcm_profile_service.h"
 #include "components/invalidation/impl/fake_invalidation_service.h"
 #include "components/invalidation/impl/fcm_invalidation_service.h"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index e7bcbe3..42bb2ae 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -246,10 +246,6 @@
     "webui/download_internals/download_internals_ui_message_handler.h",
     "webui/engagement/site_engagement_ui.cc",
     "webui/engagement/site_engagement_ui.h",
-    "webui/federated_learning/floc_internals_page_handler.cc",
-    "webui/federated_learning/floc_internals_page_handler.h",
-    "webui/federated_learning/floc_internals_ui.cc",
-    "webui/federated_learning/floc_internals_ui.h",
     "webui/fileicon_source.cc",
     "webui/fileicon_source.h",
     "webui/flags/flags_ui.cc",
@@ -407,7 +403,6 @@
     "//chrome/browser/profiles",
     "//chrome/browser/profiles:profile",
     "//chrome/browser/profiling_host",
-    "//chrome/browser/resources/federated_learning:resources",
     "//chrome/browser/resources/internals:resources",
     "//chrome/browser/resources/invalidations:resources",
     "//chrome/browser/resources/media:webrtc_logs_resources",
@@ -418,7 +413,6 @@
     "//chrome/browser/ui/webui/bluetooth_internals",
     "//chrome/browser/ui/webui/download_shelf:mojo_bindings",
     "//chrome/browser/ui/webui/downloads:mojo_bindings",
-    "//chrome/browser/ui/webui/federated_learning:mojo_bindings",
     "//chrome/browser/ui/webui/history_clusters:mojo_bindings",
     "//chrome/browser/ui/webui/new_tab_page:mojo_bindings",
     "//chrome/browser/ui/webui/new_tab_page_third_party:mojo_bindings",
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java
index aaba3fe9..5f3c146 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java
@@ -329,8 +329,8 @@
         DataSharingConsentProperties.Properties properties =
                 new DataSharingConsentProperties.Properties();
         properties.mFormattedIdpUrl = idpUrl;
-        properties.mTermsOfServiceUrl = "https://idp.com/tos";
-        properties.mPrivacyPolicyUrl = "https://idp.com/privacy";
+        properties.mTermsOfServiceUrl = "https://rp.com/tos";
+        properties.mPrivacyPolicyUrl = "https://rp.com/privacy";
 
         return new MVCListAdapter.ListItem(AccountSelectionProperties.ItemType.DATA_SHARING_CONSENT,
                 new PropertyModel.Builder(DataSharingConsentProperties.ALL_KEYS)
diff --git a/chrome/browser/ui/app_list/app_list_sort_browsertest.cc b/chrome/browser/ui/app_list/app_list_sort_browsertest.cc
index ccb8b4d..1b5fc052 100644
--- a/chrome/browser/ui/app_list/app_list_sort_browsertest.cc
+++ b/chrome/browser/ui/app_list/app_list_sort_browsertest.cc
@@ -166,6 +166,12 @@
   void ReorderByMouseClickAtContextMenu(ash::AppListSortOrder order,
                                         MenuType menu_type,
                                         AnimationTargetStatus target_status) {
+    // Ensure that the apps grid layout is refreshed before showing the
+    // context menu.
+    app_list_test_api_.GetTopLevelAppsGridView()
+        ->GetWidget()
+        ->LayoutRootViewIfNecessary();
+
     // Custom order is not a menu option.
     ASSERT_NE(order, ash::AppListSortOrder::kCustom);
 
@@ -361,7 +367,7 @@
   ash::ShellTestApi().SetTabletModeEnabledForTest(false);
   ash::AcceleratorController::Get()->PerformActionIfEnabled(
       ash::TOGGLE_APP_LIST_FULLSCREEN, {});
-  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/false);
+  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/true);
 
   ReorderByMouseClickAtContextMenu(ash::AppListSortOrder::kNameAlphabetical,
                                    MenuType::kAppListPageMenu,
@@ -384,7 +390,7 @@
   ash::ShellTestApi().SetTabletModeEnabledForTest(false);
   ash::AcceleratorController::Get()->PerformActionIfEnabled(
       ash::TOGGLE_APP_LIST_FULLSCREEN, {});
-  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/false);
+  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/true);
 
   // Move apps to one folder.
   const std::string folder_id =
@@ -413,7 +419,7 @@
   ash::ShellTestApi().SetTabletModeEnabledForTest(false);
   ash::AcceleratorController::Get()->PerformActionIfEnabled(
       ash::TOGGLE_APP_LIST_FULLSCREEN, {});
-  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/false);
+  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/true);
 
   ReorderByMouseClickAtContextMenu(ash::AppListSortOrder::kNameAlphabetical,
                                    MenuType::kAppListNonFolderItemMenu,
@@ -438,7 +444,7 @@
   ash::ShellTestApi().SetTabletModeEnabledForTest(false);
   ash::AcceleratorController::Get()->PerformActionIfEnabled(
       ash::TOGGLE_APP_LIST_FULLSCREEN, {});
-  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/false);
+  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/true);
 
   // Move apps to one folder.
   app_list_test_api_.CreateFolderWithApps({app1_id_, app2_id_, app3_id_});
@@ -468,7 +474,7 @@
   ash::ShellTestApi().SetTabletModeEnabledForTest(false);
   ash::AcceleratorController::Get()->PerformActionIfEnabled(
       ash::TOGGLE_APP_LIST_FULLSCREEN, {});
-  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/false);
+  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/true);
 
   // Move apps to one folder.
   app_list_test_api_.CreateFolderWithApps({app1_id_, app2_id_, app3_id_});
@@ -495,7 +501,7 @@
   ash::ShellTestApi().SetTabletModeEnabledForTest(false);
   ash::AcceleratorController::Get()->PerformActionIfEnabled(
       ash::TOGGLE_APP_LIST_FULLSCREEN, {});
-  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/false);
+  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/true);
 
   // Verify the default app order.
   EXPECT_EQ(GetAppIdsInOrdinalOrder(),
@@ -527,7 +533,7 @@
   ash::ShellTestApi().SetTabletModeEnabledForTest(false);
   ash::AcceleratorController::Get()->PerformActionIfEnabled(
       ash::TOGGLE_APP_LIST_FULLSCREEN, {});
-  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/false);
+  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/true);
 
   // Verify the default app order.
   EXPECT_EQ(GetAppIdsInOrdinalOrder(),
@@ -798,27 +804,14 @@
             std::vector<std::string>({app1_id_, app2_id_, app3_id_}));
 }
 
-#if BUILDFLAG(IS_CHROMEOS)
-// These two transition tests are both flaky on CrOS ASAN: crbug.com/1290890
-#define MAYBE_TransitionToTabletModeDuringReorderAnimation \
-  DISABLED_TransitionToTabletModeDuringReorderAnimation
-#define MAYBE_TransitionToClamshellModeDuringReorderAnimation \
-  DISABLED_TransitionToClamshellModeDuringReorderAnimation
-#else
-#define MAYBE_TransitionToTabletModeDuringReorderAnimation \
-  TransitionToTabletModeDuringReorderAnimation
-#define MAYBE_TransitionToClamshellModeDuringReorderAnimation \
-  TransitionToClamshellModeDuringReorderAnimation
-#endif
-
 // Verify that switching to tablet mode when the app list reorder animation in
 // clamshell mode is running works as expected.
 IN_PROC_BROWSER_TEST_F(AppListSortBrowserTest,
-                       MAYBE_TransitionToTabletModeDuringReorderAnimation) {
+                       TransitionToTabletModeDuringReorderAnimation) {
   ash::ShellTestApi().SetTabletModeEnabledForTest(false);
   ash::AcceleratorController::Get()->PerformActionIfEnabled(
       ash::TOGGLE_APP_LIST_FULLSCREEN, {});
-  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/false);
+  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/true);
 
   // Verify the default app order.
   EXPECT_EQ(GetAppIdsInOrdinalOrder(),
@@ -857,7 +850,7 @@
 // Verify that switching to clamshell mode when the app list reorder animation
 // in tablet mode is running works as expected.
 IN_PROC_BROWSER_TEST_F(AppListSortBrowserTest,
-                       MAYBE_TransitionToClamshellModeDuringReorderAnimation) {
+                       TransitionToClamshellModeDuringReorderAnimation) {
   ash::ShellTestApi().SetTabletModeEnabledForTest(true);
 
   ash::AcceleratorController::Get()->PerformActionIfEnabled(
@@ -882,7 +875,7 @@
   ash::ShellTestApi().SetTabletModeEnabledForTest(false);
   ash::AcceleratorController::Get()->PerformActionIfEnabled(
       ash::TOGGLE_APP_LIST_FULLSCREEN, {});
-  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/false);
+  app_list_test_api_.WaitForBubbleWindow(/*wait_for_opening_animation=*/true);
 
   // Before switching to the tablet mode, the app list is closed so the
   // temporary sorting order is committed.
diff --git a/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc b/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc
index a269810..c0b4728f 100644
--- a/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc
+++ b/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc
@@ -248,7 +248,7 @@
     // Lacros and Ash windows, so we can assign the icons to the instances that
     // have already been created.
     std::string app_id = shelf_id().app_id;
-    if (app_id == extension_misc::kLacrosAppId) {
+    if (app_id == app_constants::kLacrosAppId) {
       for (auto* instance : registry_.GetLacrosBrowserWindowInstances()) {
         views::NativeWidgetAura::AssignIconToAuraWindow(
             instance->window, bitty_icon_, medium_icon_);
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 6c0de272..ffa6d1b 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -36,7 +36,6 @@
 #include "chrome/browser/ui/webui/domain_reliability_internals_ui.h"
 #include "chrome/browser/ui/webui/download_internals/download_internals_ui.h"
 #include "chrome/browser/ui/webui/engagement/site_engagement_ui.h"
-#include "chrome/browser/ui/webui/federated_learning/floc_internals_ui.h"
 #include "chrome/browser/ui/webui/flags/flags_ui.h"
 #include "chrome/browser/ui/webui/gcm_internals_ui.h"
 #include "chrome/browser/ui/webui/internals/internals_ui.h"
@@ -691,8 +690,6 @@
     return &NewWebUI<FlagsDeprecatedUI>;
   if (url.host_piece() == chrome::kChromeUIFlagsHost)
     return &NewWebUI<FlagsUI>;
-  if (url.host_piece() == chrome::kChromeUIFlocInternalsHost)
-    return &NewWebUI<FlocInternalsUI>;
   if (url.host_piece() == chrome::kChromeUIGCMInternalsHost)
     return &NewWebUI<GCMInternalsUI>;
   if (url.host_piece() == chrome::kChromeUIInternalsHost)
diff --git a/chrome/browser/ui/webui/federated_learning/BUILD.gn b/chrome/browser/ui/webui/federated_learning/BUILD.gn
deleted file mode 100644
index dc271b8..0000000
--- a/chrome/browser/ui/webui/federated_learning/BUILD.gn
+++ /dev/null
@@ -1,12 +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("//build/config/android/channel.gni")
-import("//mojo/public/tools/bindings/mojom.gni")
-
-mojom("mojo_bindings") {
-  sources = [ "floc_internals.mojom" ]
-  public_deps = [ "//mojo/public/mojom/base" ]
-  webui_module_path = "/"
-}
diff --git a/chrome/browser/ui/webui/federated_learning/DIR_METADATA b/chrome/browser/ui/webui/federated_learning/DIR_METADATA
deleted file mode 100644
index 94c4325..0000000
--- a/chrome/browser/ui/webui/federated_learning/DIR_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-mixins: "//chrome/browser/federated_learning/COMMON_METADATA"
diff --git a/chrome/browser/ui/webui/federated_learning/OWNERS b/chrome/browser/ui/webui/federated_learning/OWNERS
deleted file mode 100644
index 8efe058..0000000
--- a/chrome/browser/ui/webui/federated_learning/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-file://chrome/browser/federated_learning/OWNERS
-
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/ui/webui/federated_learning/floc_internals.mojom b/chrome/browser/ui/webui/federated_learning/floc_internals.mojom
deleted file mode 100644
index 9bcf222..0000000
--- a/chrome/browser/ui/webui/federated_learning/floc_internals.mojom
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module federated_learning.mojom;
-
-import "mojo/public/mojom/base/time.mojom";
-
-// Struct representing the floc related status that will be displayed by WebUI.
-struct WebUIFlocStatus {
-  // The string representation of the cohort id.
-  string id;
-
-  // The string representation of the cohort version.
-  string version;
-
-  // The last time when floc is computed.
-  mojo_base.mojom.Time compute_time;
-
-  // The feature enabled state of whether pages with ad resources is default
-  // included in the cohort computation.
-  bool feature_pages_with_ad_resources_default_included_in_floc_computation;
-
-  // The feature enabled state of whether the FLoC origin trial should be
-  // enabled.
-  bool feature_interest_cohort_api_origin_trial;
-
-  // The feature enabled state of whether the interest-cohort feature policy is
-  // available.
-  bool feature_interest_cohort_feature_policy;
-
-  // The feature parameter that controls the scheduled cohort update interval.
-  mojo_base.mojom.TimeDelta feature_param_scheduled_update_interval;
-
-  // The feature parameter that controls the minimum number of history domains
-  // required to compute the floc.
-  int32 feature_param_minimum_history_domain_size_required;
-
-  // The feature parameter that controls the primary part of the floc version.
-  int32 feature_param_finch_config_version;
-};
-
-// Browser interface for the page. Consists of calls for data and hooks for
-// interactivity.
-interface PageHandler {
-  // Get the floc related status.
-  GetFlocStatus() => (WebUIFlocStatus status);
-};
diff --git a/chrome/browser/ui/webui/federated_learning/floc_internals_page_handler.cc b/chrome/browser/ui/webui/federated_learning/floc_internals_page_handler.cc
deleted file mode 100644
index a78f424..0000000
--- a/chrome/browser/ui/webui/federated_learning/floc_internals_page_handler.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2021 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/webui/federated_learning/floc_internals_page_handler.h"
-
-#include "chrome/browser/federated_learning/floc_id_provider.h"
-#include "chrome/browser/federated_learning/floc_id_provider_factory.h"
-#include "chrome/browser/profiles/profile.h"
-
-FlocInternalsPageHandler::FlocInternalsPageHandler(
-    Profile* profile,
-    mojo::PendingReceiver<federated_learning::mojom::PageHandler> receiver)
-    : profile_(profile), receiver_(this, std::move(receiver)) {}
-
-FlocInternalsPageHandler::~FlocInternalsPageHandler() = default;
-
-void FlocInternalsPageHandler::GetFlocStatus(
-    federated_learning::mojom::PageHandler::GetFlocStatusCallback callback) {
-  federated_learning::FlocIdProvider* floc_id_provider =
-      federated_learning::FlocIdProviderFactory::GetForProfile(profile_);
-
-  if (!floc_id_provider) {
-    std::move(callback).Run(federated_learning::mojom::WebUIFlocStatus::New());
-    return;
-  }
-
-  std::move(callback).Run(floc_id_provider->GetFlocStatusForWebUi());
-}
diff --git a/chrome/browser/ui/webui/federated_learning/floc_internals_page_handler.h b/chrome/browser/ui/webui/federated_learning/floc_internals_page_handler.h
deleted file mode 100644
index f3e5577..0000000
--- a/chrome/browser/ui/webui/federated_learning/floc_internals_page_handler.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2021 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_WEBUI_FEDERATED_LEARNING_FLOC_INTERNALS_PAGE_HANDLER_H_
-#define CHROME_BROWSER_UI_WEBUI_FEDERATED_LEARNING_FLOC_INTERNALS_PAGE_HANDLER_H_
-
-#include "base/memory/raw_ptr.h"
-#include "chrome/browser/ui/webui/federated_learning/floc_internals.mojom.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "ui/webui/mojo_web_ui_controller.h"
-
-class Profile;
-
-// Implements the mojo endpoint for the FLoC WebUI which proxies calls to the
-// FlocIdProvider to get information about relevant floc status. Owned by
-// FlocInternalsUI.
-class FlocInternalsPageHandler : public federated_learning::mojom::PageHandler {
- public:
-  FlocInternalsPageHandler(
-      Profile* profile,
-      mojo::PendingReceiver<federated_learning::mojom::PageHandler> receiver);
-  FlocInternalsPageHandler(const FlocInternalsPageHandler&) = delete;
-  FlocInternalsPageHandler& operator=(const FlocInternalsPageHandler&) = delete;
-  ~FlocInternalsPageHandler() override;
-
-  // federated_learning::mojom::PageHandler overrides:
-  void GetFlocStatus(
-      federated_learning::mojom::PageHandler::GetFlocStatusCallback callback)
-      override;
-
- private:
-  raw_ptr<Profile> profile_;
-
-  mojo::Receiver<federated_learning::mojom::PageHandler> receiver_;
-};
-
-#endif  // CHROME_BROWSER_UI_WEBUI_FEDERATED_LEARNING_FLOC_INTERNALS_PAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/federated_learning/floc_internals_ui.cc b/chrome/browser/ui/webui/federated_learning/floc_internals_ui.cc
deleted file mode 100644
index a432276e..0000000
--- a/chrome/browser/ui/webui/federated_learning/floc_internals_ui.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2021 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/webui/federated_learning/floc_internals_ui.h"
-
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/federated_learning/floc_internals.mojom.h"
-#include "chrome/browser/ui/webui/federated_learning/floc_internals_page_handler.h"
-#include "chrome/browser/ui/webui/webui_util.h"
-#include "chrome/common/webui_url_constants.h"
-#include "chrome/grit/floc_internals_resources.h"
-#include "chrome/grit/floc_internals_resources_map.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-
-FlocInternalsUI::FlocInternalsUI(content::WebUI* web_ui)
-    : ui::MojoWebUIController(web_ui, true) {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(chrome::kChromeUIFlocInternalsHost);
-
-  webui::SetupWebUIDataSource(
-      source,
-      base::make_span(kFlocInternalsResources, kFlocInternalsResourcesSize),
-      IDR_FLOC_INTERNALS_FLOC_INTERNALS_HTML);
-
-  content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
-                                source);
-}
-
-FlocInternalsUI::~FlocInternalsUI() = default;
-
-WEB_UI_CONTROLLER_TYPE_IMPL(FlocInternalsUI)
-
-void FlocInternalsUI::BindInterface(
-    mojo::PendingReceiver<federated_learning::mojom::PageHandler> receiver) {
-  page_handler_ = std::make_unique<FlocInternalsPageHandler>(
-      Profile::FromBrowserContext(
-          web_ui()->GetWebContents()->GetBrowserContext()),
-      std::move(receiver));
-}
diff --git a/chrome/browser/ui/webui/federated_learning/floc_internals_ui.h b/chrome/browser/ui/webui/federated_learning/floc_internals_ui.h
deleted file mode 100644
index 3bcdc667..0000000
--- a/chrome/browser/ui/webui/federated_learning/floc_internals_ui.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2021 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_WEBUI_FEDERATED_LEARNING_FLOC_INTERNALS_UI_H_
-#define CHROME_BROWSER_UI_WEBUI_FEDERATED_LEARNING_FLOC_INTERNALS_UI_H_
-
-#include <memory>
-
-#include "chrome/browser/ui/webui/federated_learning/floc_internals.mojom-forward.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "ui/webui/mojo_web_ui_controller.h"
-
-class FlocInternalsPageHandler;
-
-// WebUI which handles serving the chrome://floc-internals page.
-class FlocInternalsUI : public ui::MojoWebUIController {
- public:
-  explicit FlocInternalsUI(content::WebUI* web_ui);
-  FlocInternalsUI(const FlocInternalsUI&) = delete;
-  FlocInternalsUI& operator=(const FlocInternalsUI&) = delete;
-  ~FlocInternalsUI() override;
-
-  // Instantiates the implementor of the mojom::PageHandler mojo interface
-  // passing the pending receiver that will be internally bound.
-  void BindInterface(
-      mojo::PendingReceiver<federated_learning::mojom::PageHandler> receiver);
-
- private:
-  std::unique_ptr<FlocInternalsPageHandler> page_handler_;
-
-  WEB_UI_CONTROLLER_TYPE_DECL();
-};
-
-#endif  // CHROME_BROWSER_UI_WEBUI_FEDERATED_LEARNING_FLOC_INTERNALS_UI_H_
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index 684821a..4bb509a 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -1196,7 +1196,7 @@
 
 void PrintPreviewHandler::OnPrintRequestCancelled() {
   base::Value empty(base::Value::Type::LIST);
-  HandleCancelPendingPrintRequest(empty.GetList());
+  HandleCancelPendingPrintRequest(empty.GetListDeprecated());
 }
 
 void PrintPreviewHandler::ClearInitiatorDetails() {
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
index 1536158..895deb5 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
@@ -469,7 +469,7 @@
       browser_process->SetApplicationLocale(locale);
       base::test::ScopedRestoreICUDefaultLocale scoped_locale(locale);
       base::ResetFormattersForTesting();
-      handler()->HandleGetInitialSettings(args.GetList());
+      handler()->HandleGetInitialSettings(args.GetListDeprecated());
     }
     // Reset again now that |scoped_locale| has been destroyed.
     browser_process->SetApplicationLocale(original_locale);
@@ -629,7 +629,7 @@
     base::Value args(base::Value::Type::LIST);
     args.Append(callback_id_in);
     args.Append(static_cast<int>(type));
-    handler()->HandleGetPrinters(args.GetList());
+    handler()->HandleGetPrinters(args.GetListDeprecated());
   }
 
   // Validates that the printers-added Web UI event has been fired for
@@ -661,7 +661,7 @@
     args.Append(callback_id_in);
     args.Append(printer_name);
     args.Append(static_cast<int>(type));
-    handler()->HandleGetPrinterCapabilities(args.GetList());
+    handler()->HandleGetPrinterCapabilities(args.GetListDeprecated());
   }
 
   // Validates that a printer capabilities promise was resolved/rejected.
@@ -1239,7 +1239,7 @@
         "test-callback-id-" + base::NumberToString(2 * i + 1);
     base::Value preview_list_args =
         ConstructPreviewArgs(preview_callback_id, preview_ticket);
-    handler()->HandleGetPreview(preview_list_args.GetList());
+    handler()->HandleGetPreview(preview_list_args.GetListDeprecated());
 
     // Send printing request.
     mojom::PrinterType type = kAllTypes[i];
@@ -1251,7 +1251,7 @@
     std::string json;
     base::JSONWriter::Write(print_ticket, &json);
     print_args.Append(json);
-    handler()->HandlePrint(print_args.GetList());
+    handler()->HandlePrint(print_args.GetListDeprecated());
 
     CheckHistograms(histograms, type);
 
@@ -1288,7 +1288,7 @@
   base::Value print_ticket = GetPrintPreviewTicket();
   base::Value list_args =
       ConstructPreviewArgs("test-callback-id-1", print_ticket);
-  handler()->HandleGetPreview(list_args.GetList());
+  handler()->HandleGetPreview(list_args.GetListDeprecated());
   run_loop.Run();
 
   // Verify that the preview was requested from the renderer with the
@@ -1318,7 +1318,7 @@
   const char callback_id_in[] = "test-callback-id-1";
   base::Value print_ticket = GetPrintPreviewTicket();
   base::Value list_args = ConstructPreviewArgs(callback_id_in, print_ticket);
-  handler()->HandleGetPreview(list_args.GetList());
+  handler()->HandleGetPreview(list_args.GetListDeprecated());
   run_loop.Run();
   const base::Value& preview_params = print_render_frame.GetSettings();
 
@@ -1436,7 +1436,7 @@
     args.Append(callback_id_in);
     args.Append(kDummyPrinterName);
     args.Append(static_cast<int>(type));
-    handler()->HandleGetPrinterCapabilities(args.GetList());
+    handler()->HandleGetPrinterCapabilities(args.GetListDeprecated());
     EXPECT_TRUE(handler()->CalledOnlyForType(type));
 
     // Start with 1 call from initial settings, then add 1 more for each loop
diff --git a/chrome/browser/ui/webui/realbox/realbox_handler.cc b/chrome/browser/ui/webui/realbox/realbox_handler.cc
index c33894d..bed45eb 100644
--- a/chrome/browser/ui/webui/realbox/realbox_handler.cc
+++ b/chrome/browser/ui/webui/realbox/realbox_handler.cc
@@ -64,7 +64,6 @@
 
 namespace {
 
-constexpr char kGoogleGIconResourceName[] = "google_g.png";
 constexpr char kSearchIconResourceName[] = "search.svg";
 
 constexpr char kAnswerCurrencyIconResourceName[] = "realbox/icons/currency.svg";
@@ -95,6 +94,7 @@
 constexpr char kDriveVideoIconResourceName[] = "realbox/icons/drive_video.svg";
 constexpr char kExtensionAppIconResourceName[] =
     "realbox/icons/extension_app.svg";
+constexpr char kGoogleGIconResourceName[] = "realbox/icons/google_g.svg";
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
 constexpr char kGoogleCalendarIconResourceName[] = "realbox/icons/calendar.svg";
 constexpr char kGoogleKeepNoteIconResourceName[] = "realbox/icons/note.svg";
@@ -276,7 +276,6 @@
 // static
 void RealboxHandler::SetupWebUIDataSource(content::WebUIDataSource* source) {
   static constexpr webui::ResourcePath kImages[] = {
-      {kGoogleGIconResourceName, IDR_WEBUI_IMAGES_200_LOGO_GOOGLEG_PNG},
       {kSearchIconResourceName, IDR_WEBUI_IMAGES_ICON_SEARCH_SVG}};
   source->AddResourcePaths(kImages);
 
@@ -296,6 +295,14 @@
   source->AddBoolean(
       "realboxMatchOmniboxTheme",
       base::FeatureList::IsEnabled(ntp_features::kRealboxMatchOmniboxTheme));
+  source->AddBoolean(
+      "roundCorners",
+      base::GetFieldTrialParamByFeatureAsInt(
+          ntp_features::kRealboxMatchSearchboxTheme,
+          ntp_features::kRealboxMatchSearchboxThemeParam, 0) == 1);
+  source->AddBoolean(
+      "realboxMatchSearchboxTheme",
+      base::FeatureList::IsEnabled(ntp_features::kRealboxMatchSearchboxTheme));
   source->AddString(
       "realboxDefaultIcon",
       base::FeatureList::IsEnabled(ntp_features::kRealboxUseGoogleGIcon)
diff --git a/chrome/browser/ui/webui/sanitized_image_source.cc b/chrome/browser/ui/webui/sanitized_image_source.cc
index aa5dec1..e03b31e4 100644
--- a/chrome/browser/ui/webui/sanitized_image_source.cc
+++ b/chrome/browser/ui/webui/sanitized_image_source.cc
@@ -4,8 +4,12 @@
 
 #include "chrome/browser/ui/webui/sanitized_image_source.h"
 
+#include <map>
+#include <string>
+
 #include "base/memory/ref_counted_memory.h"
 #include "base/strings/strcat.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
 #include "chrome/browser/image_fetcher/image_decoder_impl.h"
@@ -24,6 +28,30 @@
 #include "ui/gfx/image/image.h"
 #include "url/url_util.h"
 
+namespace {
+
+std::map<std::string, std::string> ParseParams(
+    const std::string& param_string) {
+  url::Component query(0, param_string.size());
+  url::Component key;
+  url::Component value;
+  constexpr int kMaxUriDecodeLen = 2048;
+  std::map<std::string, std::string> params;
+  while (
+      url::ExtractQueryKeyValue(param_string.c_str(), &query, &key, &value)) {
+    url::RawCanonOutputW<kMaxUriDecodeLen> output;
+    url::DecodeURLEscapeSequences(param_string.c_str() + value.begin, value.len,
+                                  url::DecodeURLMode::kUTF8OrIsomorphic,
+                                  &output);
+    params.insert({param_string.substr(key.begin, key.len),
+                   base::UTF16ToUTF8(
+                       base::StringPiece16(output.data(), output.length()))});
+  }
+  return params;
+}
+
+}  // namespace
+
 SanitizedImageSource::SanitizedImageSource(Profile* profile)
     : SanitizedImageSource(profile,
                            profile->GetDefaultStoragePartition()
@@ -49,14 +77,31 @@
     content::URLDataSource::GotDataCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  GURL url_param = GURL(url.query());
-  if (!url_param.is_valid() ||
-      url != GURL(base::StrCat(
-                 {chrome::kChromeUIImageURL, "?", url_param.spec()}))) {
+  std::string image_url_or_params = url.query();
+  if (url != GURL(base::StrCat(
+                 {chrome::kChromeUIImageURL, "?", image_url_or_params}))) {
     std::move(callback).Run(base::MakeRefCounted<base::RefCountedString>());
     return;
   }
 
+  GURL image_url = GURL(image_url_or_params);
+  bool send_cookies = false;
+  if (!image_url.is_valid()) {
+    // Attempt to parse URL and additional options from params.
+    auto params = ParseParams(image_url_or_params);
+
+    auto url_it = params.find("url");
+    if (url_it == params.end()) {
+      std::move(callback).Run(base::MakeRefCounted<base::RefCountedString>());
+      return;
+    }
+    image_url = GURL(url_it->second);
+
+    auto cookies_it = params.find("withCookies");
+    if (cookies_it != params.end() && cookies_it->second == "true")
+      send_cookies = true;
+  }
+
   // Download the image body.
   net::NetworkTrafficAnnotationTag traffic_annotation =
       net::DefineNetworkTrafficAnnotation("sanitized_image_source", R"(
@@ -66,21 +111,25 @@
             "This data source fetches an arbitrary image to be displayed in a "
             "WebUI."
           trigger:
-            "When a WebUI triggers the download of chrome://image?<URL> by "
-            "e.g. setting that URL as a src on an img tag."
+            "When a WebUI triggers the download of chrome://image?<URL> or "
+            "chrome://image?url=<URL>&withCookies=<bool> by e.g. setting that "
+            "URL as a src on an img tag."
           data: "NONE"
           destination: WEBSITE
         }
         policy {
-          cookies_allowed: NO
+          cookies_allowed: YES
+          cookies_store: "User, only when withCookies is true."
           setting: "This feature cannot be disabled by settings."
           policy_exception_justification:
             "This is a helper data source. It can be indirectly disabled by "
             "disabling the requester WebUI."
         })");
   auto request = std::make_unique<network::ResourceRequest>();
-  request->url = url_param;
-  request->credentials_mode = network::mojom::CredentialsMode::kOmit;
+  request->url = image_url;
+  request->credentials_mode = send_cookies
+                                  ? network::mojom::CredentialsMode::kInclude
+                                  : network::mojom::CredentialsMode::kOmit;
   loaders_.push_back(
       network::SimpleURLLoader::Create(std::move(request), traffic_annotation));
   loaders_.back()->DownloadToString(
diff --git a/chrome/browser/ui/webui/sanitized_image_source.h b/chrome/browser/ui/webui/sanitized_image_source.h
index 0011c85f..3476b5ec 100644
--- a/chrome/browser/ui/webui/sanitized_image_source.h
+++ b/chrome/browser/ui/webui/sanitized_image_source.h
@@ -38,6 +38,9 @@
 //
 //   chrome://image?<external image URL>
 //
+// If the image source needs to be requested with cookies, you can instead reach
+// it via:
+//   chrome://image?url=<external image URL>&withCookies=true
 class SanitizedImageSource : public content::URLDataSource {
  public:
   explicit SanitizedImageSource(Profile* profile);
diff --git a/chrome/browser/ui/webui/sanitized_image_source_unittest.cc b/chrome/browser/ui/webui/sanitized_image_source_unittest.cc
index 2ef3fa2..10b1b134 100644
--- a/chrome/browser/ui/webui/sanitized_image_source_unittest.cc
+++ b/chrome/browser/ui/webui/sanitized_image_source_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/webui/sanitized_image_source.h"
 
+#include "base/cxx17_backports.h"
 #include "base/memory/raw_ptr.h"
 #include "base/strings/strcat.h"
 #include "base/test/mock_callback.h"
@@ -19,6 +20,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image.h"
+#include "url/url_util.h"
 
 namespace {
 
@@ -165,3 +167,50 @@
 
   EXPECT_EQ(0, test_url_loader_factory_.NumPending());
 }
+
+// Verifies that the image source sends cookies with its data request if and
+// only if asked to by URL specification.
+TEST_F(SanitizedImageSourceTest, CookiesInclusion) {
+  constexpr char kImageUrl[] = "https://foo.com/img.png";
+  base::MockCallback<content::URLDataSource::GotDataCallback> callback;
+
+  // Verify that by default, requests are sent without cookies.
+  sanitized_image_source_->StartDataRequest(
+      GURL(base::StrCat({chrome::kChromeUIImageURL, "?", kImageUrl})),
+      content::WebContents::Getter(), callback.Get());
+  ASSERT_EQ(1, test_url_loader_factory_.NumPending());
+  EXPECT_FALSE(
+      test_url_loader_factory_.GetPendingRequest(0)->request.SendsCookies());
+
+  // Encode a URL so that it can be used as a param value.
+  url::RawCanonOutputT<char> encoded_url;
+  url::EncodeURIComponent(kImageUrl, base::size(kImageUrl), &encoded_url);
+  EXPECT_GT(encoded_url.length(), 0);
+  auto encoded_url_str =
+      base::StringPiece(encoded_url.data(), encoded_url.length());
+
+  // Verify that param-formatted requests can be sent with cookies.
+  sanitized_image_source_->StartDataRequest(
+      GURL(base::StrCat({chrome::kChromeUIImageURL, "?url=", encoded_url_str,
+                         "&withCookies=true"})),
+      content::WebContents::Getter(), callback.Get());
+  ASSERT_EQ(2, test_url_loader_factory_.NumPending());
+  EXPECT_TRUE(
+      test_url_loader_factory_.GetPendingRequest(1)->request.SendsCookies());
+
+  // Verify that param-formatted requests can be sent without cookies.
+  sanitized_image_source_->StartDataRequest(
+      GURL(base::StrCat({chrome::kChromeUIImageURL, "?url=", encoded_url_str,
+                         "&withCookies=false"})),
+      content::WebContents::Getter(), callback.Get());
+  ASSERT_EQ(3, test_url_loader_factory_.NumPending());
+  EXPECT_FALSE(
+      test_url_loader_factory_.GetPendingRequest(2)->request.SendsCookies());
+
+  sanitized_image_source_->StartDataRequest(
+      GURL(base::StrCat({chrome::kChromeUIImageURL, "?url=", encoded_url_str})),
+      content::WebContents::Getter(), callback.Get());
+  ASSERT_EQ(4, test_url_loader_factory_.NumPending());
+  EXPECT_FALSE(
+      test_url_loader_factory_.GetPendingRequest(3)->request.SendsCookies());
+}
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc
index c7b4f215..498acb9 100644
--- a/chrome/browser/ui/webui/settings/about_handler.cc
+++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -268,77 +268,77 @@
 }
 
 void AboutHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "aboutPageReady", base::BindRepeating(&AboutHandler::HandlePageReady,
                                             base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "refreshUpdateStatus",
       base::BindRepeating(&AboutHandler::HandleRefreshUpdateStatus,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "openFeedbackDialog",
       base::BindRepeating(&AboutHandler::HandleOpenFeedbackDialog,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "openHelpPage", base::BindRepeating(&AboutHandler::HandleOpenHelpPage,
                                           base::Unretained(this)));
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "openDiagnostics",
       base::BindRepeating(&AboutHandler::HandleOpenDiagnostics,
                           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "openFirmwareUpdatesPage",
       base::BindRepeating(&AboutHandler::HandleOpenFirmwareUpdates,
                           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "openOsHelpPage", base::BindRepeating(&AboutHandler::HandleOpenOsHelpPage,
                                             base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setChannel", base::BindRepeating(&AboutHandler::HandleSetChannel,
                                         base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "requestUpdate", base::BindRepeating(&AboutHandler::HandleRequestUpdate,
                                            base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "requestUpdateOverCellular",
       base::BindRepeating(&AboutHandler::HandleRequestUpdateOverCellular,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getVersionInfo", base::BindRepeating(&AboutHandler::HandleGetVersionInfo,
                                             base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getRegulatoryInfo",
       base::BindRepeating(&AboutHandler::HandleGetRegulatoryInfo,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getChannelInfo", base::BindRepeating(&AboutHandler::HandleGetChannelInfo,
                                             base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "canChangeChannel",
       base::BindRepeating(&AboutHandler::HandleCanChangeChannel,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "refreshTPMFirmwareUpdateStatus",
       base::BindRepeating(&AboutHandler::HandleRefreshTPMFirmwareUpdateStatus,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getEndOfLifeInfo",
       base::BindRepeating(&AboutHandler::HandleGetEndOfLifeInfo,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "launchReleaseNotes",
       base::BindRepeating(&AboutHandler::HandleLaunchReleaseNotes,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "checkInternetConnection",
       base::BindRepeating(&AboutHandler::HandleCheckInternetConnection,
                           base::Unretained(this)));
 #endif
 #if BUILDFLAG(IS_MAC)
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "promoteUpdater", base::BindRepeating(&AboutHandler::PromoteUpdater,
                                             base::Unretained(this)));
 #endif
@@ -399,11 +399,11 @@
   }
 }
 
-void AboutHandler::HandlePageReady(const base::ListValue* args) {
+void AboutHandler::HandlePageReady(base::Value::ConstListView args) {
   AllowJavascript();
 }
 
-void AboutHandler::HandleRefreshUpdateStatus(const base::ListValue* args) {
+void AboutHandler::HandleRefreshUpdateStatus(base::Value::ConstListView args) {
   RefreshUpdateStatus();
 }
 
@@ -419,40 +419,41 @@
 }
 
 #if BUILDFLAG(IS_MAC)
-void AboutHandler::PromoteUpdater(const base::ListValue* args) {
+void AboutHandler::PromoteUpdater(base::Value::ConstListView args) {
   version_updater_->PromoteUpdater();
 }
 #endif
 
-void AboutHandler::HandleOpenFeedbackDialog(const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+void AboutHandler::HandleOpenFeedbackDialog(base::Value::ConstListView args) {
+  DCHECK(args.empty());
   Browser* browser =
       chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
   chrome::OpenFeedbackDialog(browser,
                              chrome::kFeedbackSourceMdSettingsAboutPage);
 }
 
-void AboutHandler::HandleOpenHelpPage(const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+void AboutHandler::HandleOpenHelpPage(base::Value::ConstListView args) {
+  DCHECK(args.empty());
   Browser* browser =
       chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
   chrome::ShowHelp(browser, chrome::HELP_SOURCE_WEBUI);
 }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-void AboutHandler::HandleOpenDiagnostics(const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+void AboutHandler::HandleOpenDiagnostics(base::Value::ConstListView args) {
+  DCHECK(args.empty());
   chrome::ShowDiagnosticsApp(profile_);
 }
 
-void AboutHandler::HandleOpenFirmwareUpdates(const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+void AboutHandler::HandleOpenFirmwareUpdates(base::Value::ConstListView args) {
+  DCHECK(args.empty());
   chrome::ShowFirmwareUpdatesApp(profile_);
 }
 
-void AboutHandler::HandleCheckInternetConnection(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+void AboutHandler::HandleCheckInternetConnection(
+    base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   chromeos::NetworkStateHandler* network_state_handler =
       chromeos::NetworkHandler::Get()->network_state_handler();
@@ -462,8 +463,8 @@
                             base::Value(network && network->IsOnline()));
 }
 
-void AboutHandler::HandleLaunchReleaseNotes(const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+void AboutHandler::HandleLaunchReleaseNotes(base::Value::ConstListView args) {
+  DCHECK(args.empty());
   // We can always show the release notes since the Help app caches it, or can
   // show an appropriate error state (e.g. No internet connection).
   base::RecordAction(base::UserMetricsAction("ReleaseNotes.LaunchedAboutPage"));
@@ -471,28 +472,27 @@
                              apps::mojom::LaunchSource::kFromOtherApp);
 }
 
-void AboutHandler::HandleOpenOsHelpPage(const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+void AboutHandler::HandleOpenOsHelpPage(base::Value::ConstListView args) {
+  DCHECK(args.empty());
   Browser* browser =
       chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
   chrome::ShowHelp(browser, chrome::HELP_SOURCE_WEBUI_CHROME_OS);
 }
 
-void AboutHandler::HandleSetChannel(const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().size() == 2);
+void AboutHandler::HandleSetChannel(base::Value::ConstListView args) {
+  DCHECK(args.size() == 2);
 
   if (!CanChangeChannel(profile_)) {
     LOG(WARNING) << "Non-owner tried to change release track.";
     return;
   }
 
-  if (!args->GetListDeprecated()[0].is_string() ||
-      !args->GetListDeprecated()[1].is_bool()) {
+  if (!args[0].is_string() || !args[1].is_bool()) {
     LOG(ERROR) << "Can't parse SetChannel() args";
     return;
   }
-  const std::string& channel = args->GetListDeprecated()[0].GetString();
-  const bool& is_powerwash_allowed = args->GetListDeprecated()[1].GetBool();
+  const std::string& channel = args[0].GetString();
+  const bool& is_powerwash_allowed = args[1].GetBool();
 
   version_updater_->SetChannel(channel, is_powerwash_allowed);
   if (user_manager::UserManager::Get()->IsCurrentUserOwner()) {
@@ -504,9 +504,9 @@
   }
 }
 
-void AboutHandler::HandleGetVersionInfo(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+void AboutHandler::HandleGetVersionInfo(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&GetVersionInfo),
@@ -520,9 +520,9 @@
   ResolveJavascriptCallback(base::Value(callback_id), *version_info);
 }
 
-void AboutHandler::HandleGetRegulatoryInfo(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+void AboutHandler::HandleGetRegulatoryInfo(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
@@ -531,18 +531,18 @@
                      weak_factory_.GetWeakPtr(), callback_id));
 }
 
-void AboutHandler::HandleGetChannelInfo(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+void AboutHandler::HandleGetChannelInfo(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
   version_updater_->GetChannel(
       true /* get current channel */,
       base::BindOnce(&AboutHandler::OnGetCurrentChannel,
                      weak_factory_.GetWeakPtr(), callback_id));
 }
 
-void AboutHandler::HandleCanChangeChannel(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+void AboutHandler::HandleCanChangeChannel(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
   ResolveJavascriptCallback(base::Value(callback_id),
                             base::Value(CanChangeChannel(profile_)));
 }
@@ -573,17 +573,16 @@
   ResolveJavascriptCallback(base::Value(callback_id), *channel_info);
 }
 
-void AboutHandler::HandleRequestUpdate(const base::ListValue* args) {
+void AboutHandler::HandleRequestUpdate(base::Value::ConstListView args) {
   RequestUpdate();
 }
 
 void AboutHandler::HandleRequestUpdateOverCellular(
-    const base::ListValue* args) {
-  CHECK_EQ(2U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  CHECK_EQ(2U, args.size());
 
-  const std::string& update_version = args->GetListDeprecated()[0].GetString();
-  const std::string& update_size_string =
-      args->GetListDeprecated()[1].GetString();
+  const std::string& update_version = args[0].GetString();
+  const std::string& update_size_string = args[1].GetString();
   int64_t update_size;
   CHECK(base::StringToInt64(update_size_string, &update_size));
 
@@ -599,7 +598,7 @@
 }
 
 void AboutHandler::HandleRefreshTPMFirmwareUpdateStatus(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   ash::tpm_firmware_update::GetAvailableUpdateModes(
       base::BindOnce(&AboutHandler::RefreshTPMFirmwareUpdateStatus,
                      weak_factory_.GetWeakPtr()),
@@ -613,9 +612,9 @@
   FireWebUIListener("tpm-firmware-update-status-changed", *event);
 }
 
-void AboutHandler::HandleGetEndOfLifeInfo(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+void AboutHandler::HandleGetEndOfLifeInfo(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
   version_updater_->GetEolInfo(base::BindOnce(&AboutHandler::OnGetEndOfLifeInfo,
                                               weak_factory_.GetWeakPtr(),
                                               callback_id));
diff --git a/chrome/browser/ui/webui/settings/about_handler.h b/chrome/browser/ui/webui/settings/about_handler.h
index 3e9c51d..31c900c 100644
--- a/chrome/browser/ui/webui/settings/about_handler.h
+++ b/chrome/browser/ui/webui/settings/about_handler.h
@@ -26,7 +26,6 @@
 namespace base {
 class DictionaryValue;
 class FilePath;
-class ListValue;
 class Clock;
 }  // namespace base
 
@@ -66,52 +65,52 @@
 
   // Called once the JS page is ready to be called, serves as a signal to the
   // handler to register C++ observers.
-  void HandlePageReady(const base::ListValue* args);
+  void HandlePageReady(base::Value::ConstListView args);
 
   // Called once when the page has loaded. On ChromeOS, this gets the current
   // update status. On other platforms, it will request and perform an update
   // (if one is available).
-  void HandleRefreshUpdateStatus(const base::ListValue* args);
+  void HandleRefreshUpdateStatus(base::Value::ConstListView args);
   void RefreshUpdateStatus();
 
 #if BUILDFLAG(IS_MAC)
   // Promotes the updater for all users.
-  void PromoteUpdater(const base::ListValue* args);
+  void PromoteUpdater(base::Value::ConstListView args);
 #endif
 
   // Opens the feedback dialog. |args| must be empty.
-  void HandleOpenFeedbackDialog(const base::ListValue* args);
+  void HandleOpenFeedbackDialog(base::Value::ConstListView args);
 
   // Opens the help page. |args| must be empty.
-  void HandleOpenHelpPage(const base::ListValue* args);
+  void HandleOpenHelpPage(base::Value::ConstListView args);
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Checks if ReleaseNotes is enabled.
-  void HandleGetEnabledReleaseNotes(const base::ListValue* args);
+  void HandleGetEnabledReleaseNotes(base::Value::ConstListView args);
 
   // Checks if system is connected to internet.
-  void HandleCheckInternetConnection(const base::ListValue* args);
+  void HandleCheckInternetConnection(base::Value::ConstListView args);
 
   // Opens the release notes app. |args| must be empty.
-  void HandleLaunchReleaseNotes(const base::ListValue* args);
+  void HandleLaunchReleaseNotes(base::Value::ConstListView args);
 
   // Opens the help page. |args| must be empty.
-  void HandleOpenOsHelpPage(const base::ListValue* args);
+  void HandleOpenOsHelpPage(base::Value::ConstListView args);
 
   // Sets the release track version.
-  void HandleSetChannel(const base::ListValue* args);
+  void HandleSetChannel(base::Value::ConstListView args);
 
   // Retrieves OS, ARC and firmware versions.
-  void HandleGetVersionInfo(const base::ListValue* args);
+  void HandleGetVersionInfo(base::Value::ConstListView args);
   void OnGetVersionInfoReady(
       std::string callback_id,
       std::unique_ptr<base::DictionaryValue> version_info);
 
   // Retrieves channel info.
-  void HandleGetChannelInfo(const base::ListValue* args);
+  void HandleGetChannelInfo(base::Value::ConstListView args);
 
   // Checks whether we can change the current channel.
-  void HandleCanChangeChannel(const base::ListValue* args);
+  void HandleCanChangeChannel(base::Value::ConstListView args);
 
   // Callbacks for version_updater_->GetChannel calls.
   void OnGetCurrentChannel(std::string callback_id,
@@ -121,11 +120,11 @@
                           const std::string& target_channel);
 
   // Checks for and applies update, triggered by JS.
-  void HandleRequestUpdate(const base::ListValue* args);
+  void HandleRequestUpdate(base::Value::ConstListView args);
 
   // Checks for and applies update over cellular connection, triggered by JS.
   // Update version and size should be included in the list of arguments.
-  void HandleRequestUpdateOverCellular(const base::ListValue* args);
+  void HandleRequestUpdateOverCellular(base::Value::ConstListView args);
 
   // Checks for and applies update over cellular connection.
   void RequestUpdateOverCellular(const std::string& update_version,
@@ -133,7 +132,7 @@
 
   // Called once when the page has loaded to retrieve the TPM firmware update
   // status.
-  void HandleRefreshTPMFirmwareUpdateStatus(const base::ListValue* args);
+  void HandleRefreshTPMFirmwareUpdateStatus(base::Value::ConstListView args);
   void RefreshTPMFirmwareUpdateStatus(
       const std::set<ash::tpm_firmware_update::Mode>& modes);
 #endif
@@ -156,11 +155,11 @@
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  void HandleOpenDiagnostics(const base::ListValue* args);
+  void HandleOpenDiagnostics(base::Value::ConstListView args);
 
-  void HandleOpenFirmwareUpdates(const base::ListValue* args);
+  void HandleOpenFirmwareUpdates(base::Value::ConstListView args);
 
-  void HandleGetRegulatoryInfo(const base::ListValue* args);
+  void HandleGetRegulatoryInfo(base::Value::ConstListView args);
 
   // Callback for when the directory with the regulatory label image and alt
   // text has been found.
@@ -176,7 +175,7 @@
   // date. Will asynchronously resolve the provided callback with an object
   // containing a boolean indicating whether the device has reached/passed End
   // of Life, and an End Of Life description formatted with the month and year.
-  void HandleGetEndOfLifeInfo(const base::ListValue* args);
+  void HandleGetEndOfLifeInfo(base::Value::ConstListView args);
 
   // Callbacks for version_updater_->GetEolInfo calls.
   void OnGetEndOfLifeInfo(std::string callback_id,
diff --git a/chrome/browser/ui/webui/settings/accessibility_main_handler.cc b/chrome/browser/ui/webui/settings/accessibility_main_handler.cc
index a938ae0..c48e3f38 100644
--- a/chrome/browser/ui/webui/settings/accessibility_main_handler.cc
+++ b/chrome/browser/ui/webui/settings/accessibility_main_handler.cc
@@ -26,11 +26,11 @@
 AccessibilityMainHandler::~AccessibilityMainHandler() = default;
 
 void AccessibilityMainHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "a11yPageReady",
       base::BindRepeating(&AccessibilityMainHandler::HandleA11yPageReady,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "confirmA11yImageLabels",
       base::BindRepeating(
           &AccessibilityMainHandler::HandleCheckAccessibilityImageLabels,
@@ -53,13 +53,13 @@
 }
 
 void AccessibilityMainHandler::HandleA11yPageReady(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   SendScreenReaderStateChanged();
 }
 
 void AccessibilityMainHandler::HandleCheckAccessibilityImageLabels(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   // When the user tries to enable the feature, show the modal dialog. The
   // dialog will disable the feature again if it is not accepted.
   content::WebContents* web_contents = web_ui()->GetWebContents();
diff --git a/chrome/browser/ui/webui/settings/accessibility_main_handler.h b/chrome/browser/ui/webui/settings/accessibility_main_handler.h
index 35913756..0796a2a3 100644
--- a/chrome/browser/ui/webui/settings/accessibility_main_handler.h
+++ b/chrome/browser/ui/webui/settings/accessibility_main_handler.h
@@ -12,10 +12,6 @@
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-namespace base {
-class ListValue;
-}
-
 namespace settings {
 
 // Settings handler for the main accessibility settings page,
@@ -32,8 +28,8 @@
   void OnJavascriptAllowed() override;
   void OnJavascriptDisallowed() override;
 
-  void HandleA11yPageReady(const base::ListValue* args);
-  void HandleCheckAccessibilityImageLabels(const base::ListValue* args);
+  void HandleA11yPageReady(base::Value::ConstListView args);
+  void HandleCheckAccessibilityImageLabels(base::Value::ConstListView args);
 
  private:
   void SendScreenReaderStateChanged();
diff --git a/chrome/browser/ui/webui/settings/appearance_handler.cc b/chrome/browser/ui/webui/settings/appearance_handler.cc
index 86021bb..392c06664 100644
--- a/chrome/browser/ui/webui/settings/appearance_handler.cc
+++ b/chrome/browser/ui/webui/settings/appearance_handler.cc
@@ -25,28 +25,28 @@
 void AppearanceHandler::OnJavascriptDisallowed() {}
 
 void AppearanceHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "useDefaultTheme",
       base::BindRepeating(&AppearanceHandler::HandleUseDefaultTheme,
                           base::Unretained(this)));
 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
 // of lacros-chrome is complete.
 #if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_LACROS)
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "useSystemTheme",
       base::BindRepeating(&AppearanceHandler::HandleUseSystemTheme,
                           base::Unretained(this)));
 #endif
 }
 
-void AppearanceHandler::HandleUseDefaultTheme(const base::ListValue* args) {
+void AppearanceHandler::HandleUseDefaultTheme(base::Value::ConstListView args) {
   ThemeServiceFactory::GetForProfile(profile_)->UseDefaultTheme();
 }
 
 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
 // of lacros-chrome is complete.
 #if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_LACROS)
-void AppearanceHandler::HandleUseSystemTheme(const base::ListValue* args) {
+void AppearanceHandler::HandleUseSystemTheme(base::Value::ConstListView args) {
   if (profile_->IsChild())
     NOTREACHED();
   else
diff --git a/chrome/browser/ui/webui/settings/appearance_handler.h b/chrome/browser/ui/webui/settings/appearance_handler.h
index ab78d2b..50a9cda3 100644
--- a/chrome/browser/ui/webui/settings/appearance_handler.h
+++ b/chrome/browser/ui/webui/settings/appearance_handler.h
@@ -11,10 +11,6 @@
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace content {
 class WebUI;
 }
@@ -40,13 +36,13 @@
 
  private:
   // Changes the UI theme of the browser to the default theme.
-  void HandleUseDefaultTheme(const base::ListValue* args);
+  void HandleUseDefaultTheme(base::Value::ConstListView args);
 
 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
 // of lacros-chrome is complete.
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
   // Changes the UI theme of the browser to the system (GTK+) theme.
-  void HandleUseSystemTheme(const base::ListValue* args);
+  void HandleUseSystemTheme(base::Value::ConstListView args);
 #endif
 
   raw_ptr<Profile> profile_;  // Weak pointer.
diff --git a/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc b/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc
index be58a12..7ab0886 100644
--- a/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc
+++ b/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc
@@ -63,30 +63,30 @@
 BrowserLifetimeHandler::~BrowserLifetimeHandler() {}
 
 void BrowserLifetimeHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "restart", base::BindRepeating(&BrowserLifetimeHandler::HandleRestart,
                                      base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "relaunch", base::BindRepeating(&BrowserLifetimeHandler::HandleRelaunch,
                                       base::Unretained(this)));
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "signOutAndRestart",
       base::BindRepeating(&BrowserLifetimeHandler::HandleSignOutAndRestart,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "factoryReset",
       base::BindRepeating(&BrowserLifetimeHandler::HandleFactoryReset,
                           base::Unretained(this)));
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "shouldShowRelaunchConfirmationDialog",
       base::BindRepeating(
           &BrowserLifetimeHandler::HandleShouldShowRelaunchConfirmationDialog,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getRelaunchConfirmationDialogDescription",
       base::BindRepeating(&BrowserLifetimeHandler::
                               HandleGetRelaunchConfirmationDialogDescription,
@@ -94,25 +94,23 @@
 #endif
 }
 
-void BrowserLifetimeHandler::HandleRestart(
-    const base::ListValue* args) {
+void BrowserLifetimeHandler::HandleRestart(base::Value::ConstListView args) {
   chrome::AttemptRestart();
 }
 
-void BrowserLifetimeHandler::HandleRelaunch(
-    const base::ListValue* args) {
+void BrowserLifetimeHandler::HandleRelaunch(base::Value::ConstListView args) {
   chrome::AttemptRelaunch();
 }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 void BrowserLifetimeHandler::HandleSignOutAndRestart(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   chrome::AttemptUserExit();
 }
 
 void BrowserLifetimeHandler::HandleFactoryReset(
-    const base::ListValue* args) {
-  base::Value::ConstListView args_list = args->GetListDeprecated();
+    base::Value::ConstListView args) {
+  base::Value::ConstListView args_list = args;
   CHECK_EQ(1U, args_list.size());
   bool tpm_firmware_update_requested = args_list[0].GetBool();
 
@@ -143,9 +141,9 @@
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
 void BrowserLifetimeHandler::HandleGetRelaunchConfirmationDialogDescription(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+  const base::Value& callback_id = args[0];
   size_t incognito_count = BrowserList::GetIncognitoBrowserCount();
   base::Value description;
   if (incognito_count > 0) {
@@ -156,9 +154,9 @@
 }
 
 void BrowserLifetimeHandler::HandleShouldShowRelaunchConfirmationDialog(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+  const base::Value& callback_id = args[0];
   base::Value result = base::Value(BrowserList::GetIncognitoBrowserCount() > 0);
   ResolveJavascriptCallback(callback_id, result);
 }
diff --git a/chrome/browser/ui/webui/settings/browser_lifetime_handler.h b/chrome/browser/ui/webui/settings/browser_lifetime_handler.h
index 375c105..46c7fb4 100644
--- a/chrome/browser/ui/webui/settings/browser_lifetime_handler.h
+++ b/chrome/browser/ui/webui/settings/browser_lifetime_handler.h
@@ -8,10 +8,6 @@
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace settings {
 
 class BrowserLifetimeHandler : public SettingsPageUIHandler {
@@ -29,18 +25,18 @@
   void OnJavascriptDisallowed() override {}
 
  private:
-  void HandleRestart(const base::ListValue* /*args*/);
-  void HandleRelaunch(const base::ListValue* /*args*/);
+  void HandleRestart(base::Value::ConstListView args);
+  void HandleRelaunch(base::Value::ConstListView args);
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  void HandleSignOutAndRestart(const base::ListValue* /*args*/);
-  void HandleFactoryReset(const base::ListValue* /*args*/);
+  void HandleSignOutAndRestart(base::Value::ConstListView args);
+  void HandleFactoryReset(base::Value::ConstListView args);
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
   void HandleGetRelaunchConfirmationDialogDescription(
-      const base::ListValue* /*args*/);
+      base::Value::ConstListView args);
   void HandleShouldShowRelaunchConfirmationDialog(
-      const base::ListValue* /*args*/);
+      base::Value::ConstListView args);
 #endif
 };
 
diff --git a/chrome/browser/ui/webui/settings/captions_handler.cc b/chrome/browser/ui/webui/settings/captions_handler.cc
index a4ce773..9794a20f 100644
--- a/chrome/browser/ui/webui/settings/captions_handler.cc
+++ b/chrome/browser/ui/webui/settings/captions_handler.cc
@@ -41,11 +41,11 @@
 }
 
 void CaptionsHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "openSystemCaptionsDialog",
       base::BindRepeating(&CaptionsHandler::HandleOpenSystemCaptionsDialog,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "liveCaptionSectionReady",
       base::BindRepeating(&CaptionsHandler::HandleLiveCaptionSectionReady,
                           base::Unretained(this)));
@@ -62,12 +62,12 @@
 }
 
 void CaptionsHandler::HandleLiveCaptionSectionReady(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 }
 
 void CaptionsHandler::HandleOpenSystemCaptionsDialog(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
   captions::CaptionSettingsDialog::ShowCaptionSettingsDialog();
 #endif
diff --git a/chrome/browser/ui/webui/settings/captions_handler.h b/chrome/browser/ui/webui/settings/captions_handler.h
index e609d64..fbb1af9 100644
--- a/chrome/browser/ui/webui/settings/captions_handler.h
+++ b/chrome/browser/ui/webui/settings/captions_handler.h
@@ -29,8 +29,8 @@
   void OnJavascriptDisallowed() override;
 
  private:
-  void HandleLiveCaptionSectionReady(const base::ListValue* args);
-  void HandleOpenSystemCaptionsDialog(const base::ListValue* args);
+  void HandleLiveCaptionSectionReady(base::Value::ConstListView args);
+  void HandleOpenSystemCaptionsDialog(base::Value::ConstListView args);
 
   // SodaInstaller::Observer overrides:
   void OnSodaInstalled() override;
diff --git a/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.cc b/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.cc
index 3da4afd6..38df5ed86 100644
--- a/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.cc
+++ b/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.cc
@@ -110,37 +110,37 @@
 }
 
 void ChromeCleanupHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "registerChromeCleanerObserver",
       base::BindRepeating(
           &ChromeCleanupHandler::HandleRegisterChromeCleanerObserver,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "startScanning",
       base::BindRepeating(&ChromeCleanupHandler::HandleStartScanning,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "restartComputer",
       base::BindRepeating(&ChromeCleanupHandler::HandleRestartComputer,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "startCleanup",
       base::BindRepeating(&ChromeCleanupHandler::HandleStartCleanup,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "notifyShowDetails",
       base::BindRepeating(&ChromeCleanupHandler::HandleNotifyShowDetails,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "notifyChromeCleanupLearnMoreClicked",
       base::BindRepeating(
           &ChromeCleanupHandler::HandleNotifyChromeCleanupLearnMoreClicked,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getMoreItemsPluralString",
       base::BindRepeating(&ChromeCleanupHandler::HandleGetMoreItemsPluralString,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getItemsToRemovePluralString",
       base::BindRepeating(
           &ChromeCleanupHandler::HandleGetItemsToRemovePluralString,
@@ -190,8 +190,8 @@
 }
 
 void ChromeCleanupHandler::HandleRegisterChromeCleanerObserver(
-    const base::ListValue* args) {
-  DCHECK_EQ(0U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  DCHECK_EQ(0U, args.size());
 
   base::RecordAction(
       base::UserMetricsAction("SoftwareReporter.CleanupWebui_Shown"));
@@ -201,11 +201,12 @@
                     base::Value(controller_->IsAllowedByPolicy()));
 }
 
-void ChromeCleanupHandler::HandleStartScanning(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
+void ChromeCleanupHandler::HandleStartScanning(
+    base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
   bool allow_logs_upload = false;
-  if (args->GetListDeprecated()[0].is_bool())
-    allow_logs_upload = args->GetListDeprecated()[0].GetBool();
+  if (args[0].is_bool())
+    allow_logs_upload = args[0].GetBool();
 
   // If this operation is not allowed the UI should be disabled.
   CHECK(controller_->IsAllowedByPolicy());
@@ -219,8 +220,9 @@
       base::UserMetricsAction("SoftwareReporter.CleanupWebui_StartScanning"));
 }
 
-void ChromeCleanupHandler::HandleRestartComputer(const base::ListValue* args) {
-  DCHECK_EQ(0U, args->GetListDeprecated().size());
+void ChromeCleanupHandler::HandleRestartComputer(
+    base::Value::ConstListView args) {
+  DCHECK_EQ(0U, args.size());
 
   base::RecordAction(
       base::UserMetricsAction("SoftwareReporter.CleanupWebui_RestartComputer"));
@@ -228,11 +230,11 @@
   controller_->Reboot();
 }
 
-void ChromeCleanupHandler::HandleStartCleanup(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
+void ChromeCleanupHandler::HandleStartCleanup(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
   bool allow_logs_upload = false;
-  if (args->GetListDeprecated()[0].is_bool())
-    allow_logs_upload = args->GetListDeprecated()[0].GetBool();
+  if (args[0].is_bool())
+    allow_logs_upload = args[0].GetBool();
 
   // The state is propagated to all open tabs and should be consistent.
   DCHECK_EQ(controller_->logs_enabled(profile_), allow_logs_upload);
@@ -250,11 +252,11 @@
 }
 
 void ChromeCleanupHandler::HandleNotifyShowDetails(
-    const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
   bool details_section_visible = false;
-  if (args->GetListDeprecated()[0].is_bool())
-    details_section_visible = args->GetListDeprecated()[0].GetBool();
+  if (args[0].is_bool())
+    details_section_visible = args[0].GetBool();
 
   if (details_section_visible) {
     base::RecordAction(
@@ -266,30 +268,30 @@
 }
 
 void ChromeCleanupHandler::HandleNotifyChromeCleanupLearnMoreClicked(
-    const base::ListValue* args) {
-  CHECK_EQ(0U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  CHECK_EQ(0U, args.size());
 
   base::RecordAction(
       base::UserMetricsAction("SoftwareReporter.CleanupWebui_LearnMore"));
 }
 
 void ChromeCleanupHandler::HandleGetMoreItemsPluralString(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
 #if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
   GetPluralString(IDS_SETTINGS_RESET_CLEANUP_DETAILS_MORE, args);
 #endif  // BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
 }
 
 void ChromeCleanupHandler::HandleGetItemsToRemovePluralString(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
 #if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
   GetPluralString(IDS_SETTINGS_RESET_CLEANUP_DETAILS_ITEMS_TO_BE_REMOVED, args);
 #endif  // BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
 }
 
 void ChromeCleanupHandler::GetPluralString(int id,
-                                           const base::ListValue* args) {
-  const auto& list = args->GetListDeprecated();
+                                           base::Value::ConstListView args) {
+  const auto& list = args;
   CHECK_EQ(2U, list.size());
 
   std::string callback_id = list[0].GetString();
diff --git a/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.h b/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.h
index ba4278de..8eeaea7c 100644
--- a/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.h
+++ b/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.h
@@ -53,37 +53,38 @@
   // Callback for the "registerChromeCleanerObserver" message. This registers
   // this object as an observer of the Chrome Cleanup global state and
   // and retrieves the current cleanup state.
-  void HandleRegisterChromeCleanerObserver(const base::ListValue* args);
+  void HandleRegisterChromeCleanerObserver(base::Value::ConstListView args);
 
   // Callback for the "startScanning" message to start scanning the user's
   // system to detect unwanted software.
-  void HandleStartScanning(const base::ListValue* args);
+  void HandleStartScanning(base::Value::ConstListView args);
 
   // Callback for the "restartComputer" message to finalize the cleanup with a
   // system restart.
-  void HandleRestartComputer(const base::ListValue* args);
+  void HandleRestartComputer(base::Value::ConstListView args);
 
   // Callback for the "startCleanup" message to start removing unwanted
   // software from the user's computer.
-  void HandleStartCleanup(const base::ListValue* args);
+  void HandleStartCleanup(base::Value::ConstListView args);
 
   // Callback for the "showDetails" message that notifies Chrome about whether
   // the user expanded or closed the details section of the page.
-  void HandleNotifyShowDetails(const base::ListValue* args);
+  void HandleNotifyShowDetails(base::Value::ConstListView args);
 
   // Callback for the "chromeCleanupLearnMore" message that notifies Chrome that
   // the "learn more" link was clicked.
-  void HandleNotifyChromeCleanupLearnMoreClicked(const base::ListValue* args);
+  void HandleNotifyChromeCleanupLearnMoreClicked(
+      base::Value::ConstListView args);
 
   // Callback for the "getMoreItemsPluralString" message, that obtains the text
   // string for the "show more" items on the detailed view.
-  void HandleGetMoreItemsPluralString(const base::ListValue* args);
+  void HandleGetMoreItemsPluralString(base::Value::ConstListView args);
 
   // Callback for the "getItemsToRemovePluralString" message, that obtains the
   // text string for the detailed view when user-initiated cleanups are enabled.
-  void HandleGetItemsToRemovePluralString(const base::ListValue* args);
+  void HandleGetItemsToRemovePluralString(base::Value::ConstListView args);
 
-  void GetPluralString(int id, const base::ListValue* args);
+  void GetPluralString(int id, base::Value::ConstListView args);
 
   // Raw pointer to a singleton. Must outlive this object.
   raw_ptr<safe_browsing::ChromeCleanerController> controller_;
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
index bce5dad4..e60b234 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
@@ -54,62 +54,62 @@
 }
 
 void AccessibilityHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showChromeVoxSettings",
       base::BindRepeating(&AccessibilityHandler::HandleShowChromeVoxSettings,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showSelectToSpeakSettings",
       base::BindRepeating(
           &AccessibilityHandler::HandleShowSelectToSpeakSettings,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setStartupSoundEnabled",
       base::BindRepeating(&AccessibilityHandler::HandleSetStartupSoundEnabled,
                           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "recordSelectedShowShelfNavigationButtonValue",
       base::BindRepeating(
           &AccessibilityHandler::
               HandleRecordSelectedShowShelfNavigationButtonsValue,
           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "manageA11yPageReady",
       base::BindRepeating(&AccessibilityHandler::HandleManageA11yPageReady,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showChromeVoxTutorial",
       base::BindRepeating(&AccessibilityHandler::HandleShowChromeVoxTutorial,
                           base::Unretained(this)));
 }
 
 void AccessibilityHandler::HandleShowChromeVoxSettings(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   OpenExtensionOptionsPage(extension_misc::kChromeVoxExtensionId);
 }
 
 void AccessibilityHandler::HandleShowSelectToSpeakSettings(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   OpenExtensionOptionsPage(extension_misc::kSelectToSpeakExtensionId);
 }
 
 void AccessibilityHandler::HandleSetStartupSoundEnabled(
-    const base::ListValue* args) {
-  DCHECK_EQ(1U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  DCHECK_EQ(1U, args.size());
   bool enabled = false;
-  if (args->GetListDeprecated()[0].is_bool())
-    enabled = args->GetListDeprecated()[0].GetBool();
+  if (args[0].is_bool())
+    enabled = args[0].GetBool();
   AccessibilityManager::Get()->SetStartupSoundEnabled(enabled);
 }
 
 void AccessibilityHandler::HandleRecordSelectedShowShelfNavigationButtonsValue(
-    const base::ListValue* args) {
-  DCHECK_EQ(1U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  DCHECK_EQ(1U, args.size());
   bool enabled = false;
-  if (args->GetListDeprecated()[0].is_bool())
-    enabled = args->GetListDeprecated()[0].GetBool();
+  if (args[0].is_bool())
+    enabled = args[0].GetBool();
 
   a11y_nav_buttons_toggle_metrics_reporter_timer_.Start(
       FROM_HERE, base::Seconds(10),
@@ -117,7 +117,7 @@
 }
 
 void AccessibilityHandler::HandleManageA11yPageReady(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 }
 
@@ -135,7 +135,7 @@
 }
 
 void AccessibilityHandler::HandleShowChromeVoxTutorial(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AccessibilityManager::Get()->ShowChromeVoxTutorial();
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
index 695d938e..3d17e95 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
@@ -10,10 +10,6 @@
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "components/soda/soda_installer.h"
 
-namespace base {
-class ListValue;
-}
-
 class Profile;
 
 namespace chromeos {
@@ -35,19 +31,19 @@
   void OnJavascriptDisallowed() override;
 
   // Callback which updates if startup sound is enabled. Visible for testing.
-  void HandleManageA11yPageReady(const base::ListValue* args);
+  void HandleManageA11yPageReady(base::Value::ConstListView args);
 
  private:
   friend class AccessibilityHandlerTest;
 
   // Callback for the messages to show settings for ChromeVox or
   // Select To Speak.
-  void HandleShowChromeVoxSettings(const base::ListValue* args);
-  void HandleShowSelectToSpeakSettings(const base::ListValue* args);
-  void HandleSetStartupSoundEnabled(const base::ListValue* args);
+  void HandleShowChromeVoxSettings(base::Value::ConstListView args);
+  void HandleShowSelectToSpeakSettings(base::Value::ConstListView args);
+  void HandleSetStartupSoundEnabled(base::Value::ConstListView args);
   void HandleRecordSelectedShowShelfNavigationButtonsValue(
-      const base::ListValue* args);
-  void HandleShowChromeVoxTutorial(const base::ListValue* args);
+      base::Value::ConstListView args);
+  void HandleShowChromeVoxTutorial(base::Value::ConstListView args);
 
   void OpenExtensionOptionsPage(const char extension_id[]);
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc b/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc
index a3b1ce87..55afba04 100644
--- a/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc
@@ -29,11 +29,11 @@
 
 void AndroidAppsHandler::RegisterMessages() {
   // Note: requestAndroidAppsInfo must be called before observers will be added.
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "requestAndroidAppsInfo",
       base::BindRepeating(&AndroidAppsHandler::HandleRequestAndroidAppsInfo,
                           weak_ptr_factory_.GetWeakPtr()));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showAndroidAppsSettings",
       base::BindRepeating(&AndroidAppsHandler::ShowAndroidAppsSettings,
                           weak_ptr_factory_.GetWeakPtr()));
@@ -94,7 +94,7 @@
 }
 
 void AndroidAppsHandler::HandleRequestAndroidAppsInfo(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   SendAndroidAppsInfo();
 }
@@ -104,11 +104,12 @@
   FireWebUIListener("android-apps-info-update", *info);
 }
 
-void AndroidAppsHandler::ShowAndroidAppsSettings(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
+void AndroidAppsHandler::ShowAndroidAppsSettings(
+    base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
   bool activated_from_keyboard = false;
-  if (args->GetListDeprecated()[0].is_bool())
-    activated_from_keyboard = args->GetListDeprecated()[0].GetBool();
+  if (args[0].is_bool())
+    activated_from_keyboard = args[0].GetBool();
   int flags = activated_from_keyboard ? ui::EF_NONE : ui::EF_LEFT_MOUSE_BUTTON;
 
   app_service_proxy_->Launch(
diff --git a/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h b/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h
index 18b76aa..a80c714 100644
--- a/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h
@@ -54,10 +54,10 @@
 
  private:
   std::unique_ptr<base::DictionaryValue> BuildAndroidAppsInfo();
-  void HandleRequestAndroidAppsInfo(const base::ListValue* args);
+  void HandleRequestAndroidAppsInfo(base::Value::ConstListView args);
   void HandleAppChanged(const std::string& app_id);
   void SendAndroidAppsInfo();
-  void ShowAndroidAppsSettings(const base::ListValue* args);
+  void ShowAndroidAppsSettings(base::Value::ConstListView args);
   int64_t GetDisplayIdForCurrentProfile();
 
   base::ScopedObservation<ArcAppListPrefs, ArcAppListPrefs::Observer>
diff --git a/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.cc b/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.cc
index 91f54a6..3a65d93 100644
--- a/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.cc
@@ -28,7 +28,7 @@
 BluetoothHandler::~BluetoothHandler() {}
 
 void BluetoothHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       kIsDeviceBlockedByPolicy,
       base::BindRepeating(&BluetoothHandler::HandleIsDeviceBlockedByPolicy,
                           base::Unretained(this)));
@@ -45,11 +45,11 @@
 }
 
 void BluetoothHandler::HandleIsDeviceBlockedByPolicy(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
-  const std::string& address = args->GetListDeprecated()[1].GetString();
+  CHECK_EQ(2U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  const std::string& address = args[1].GetString();
 
   if (!bluetooth_adapter_) {
     BLUETOOTH_LOG(EVENT) << "Bluetooth adapter not available.";
diff --git a/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h b/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h
index 63d0c353..d535110 100644
--- a/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h
@@ -32,7 +32,7 @@
   void BluetoothDeviceAdapterReady(
       scoped_refptr<device::BluetoothAdapter> adapter);
 
-  void HandleIsDeviceBlockedByPolicy(const base::ListValue* args);
+  void HandleIsDeviceBlockedByPolicy(base::Value::ConstListView args);
 
   scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_;
   base::WeakPtrFactory<BluetoothHandler> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
index de5c95ee..46f60da 100644
--- a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
@@ -112,25 +112,25 @@
 }
 
 void ChangePictureHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "chooseFile", base::BindRepeating(&ChangePictureHandler::HandleChooseFile,
                                         base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "photoTaken", base::BindRepeating(&ChangePictureHandler::HandlePhotoTaken,
                                         base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "discardPhoto",
       base::BindRepeating(&ChangePictureHandler::HandleDiscardPhoto,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "onChangePicturePageInitialized",
       base::BindRepeating(&ChangePictureHandler::HandlePageInitialized,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "selectImage",
       base::BindRepeating(&ChangePictureHandler::HandleSelectImage,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "requestSelectedImage",
       base::BindRepeating(&ChangePictureHandler::HandleRequestSelectedImage,
                           base::Unretained(this)));
@@ -164,8 +164,8 @@
   FireWebUIListener("default-images-changed", result);
 }
 
-void ChangePictureHandler::HandleChooseFile(const base::ListValue* args) {
-  DCHECK(args && args->GetListDeprecated().empty());
+void ChangePictureHandler::HandleChooseFile(base::Value::ConstListView args) {
+  DCHECK(args.empty());
   select_file_dialog_ = ui::SelectFileDialog::Create(
       this,
       std::make_unique<ChromeSelectFilePolicy>(web_ui()->GetWebContents()));
@@ -186,21 +186,20 @@
       file_type_info.get(), 0, FILE_PATH_LITERAL(""), GetBrowserWindow(), NULL);
 }
 
-void ChangePictureHandler::HandleDiscardPhoto(const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+void ChangePictureHandler::HandleDiscardPhoto(base::Value::ConstListView args) {
+  DCHECK(args.empty());
   AccessibilityManager::Get()->PlayEarcon(
       Sound::kObjectDelete, PlaySoundOption::kOnlyIfSpokenFeedbackEnabled);
 }
 
-void ChangePictureHandler::HandlePhotoTaken(const base::ListValue* args) {
+void ChangePictureHandler::HandlePhotoTaken(base::Value::ConstListView args) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   AccessibilityManager::Get()->PlayEarcon(
       Sound::kCameraSnap, PlaySoundOption::kOnlyIfSpokenFeedbackEnabled);
 
-  if (!args || args->GetListDeprecated().size() != 1 ||
-      !args->GetListDeprecated()[0].is_string())
+  if (args.size() != 1 || !args[0].is_string())
     NOTREACHED();
-  const std::string& image_url = args->GetListDeprecated()[0].GetString();
+  const std::string& image_url = args[0].GetString();
   DCHECK(!image_url.empty());
 
   std::string raw_data;
@@ -222,8 +221,9 @@
   ImageDecoder::Start(this, std::move(raw_data));
 }
 
-void ChangePictureHandler::HandlePageInitialized(const base::ListValue* args) {
-  DCHECK(args && args->GetListDeprecated().empty());
+void ChangePictureHandler::HandlePageInitialized(
+    base::Value::ConstListView args) {
+  DCHECK(args.empty());
 
   AllowJavascript();
 
@@ -319,15 +319,13 @@
   FireWebUIListener("old-image-changed", base::Value(image_url));
 }
 
-void ChangePictureHandler::HandleSelectImage(const base::ListValue* args) {
-  if (!args || args->GetListDeprecated().size() != 2 ||
-      !args->GetListDeprecated()[0].is_string() ||
-      !args->GetListDeprecated()[1].is_string()) {
+void ChangePictureHandler::HandleSelectImage(base::Value::ConstListView args) {
+  if (args.size() != 2 || !args[0].is_string() || !args[1].is_string()) {
     NOTREACHED();
     return;
   }
-  const std::string& image_url = args->GetListDeprecated()[0].GetString();
-  const std::string& image_type = args->GetListDeprecated()[1].GetString();
+  const std::string& image_url = args[0].GetString();
+  const std::string& image_type = args[1].GetString();
   // |image_url| may be empty unless |image_type| is "default".
   DCHECK(!image_type.empty());
 
@@ -386,7 +384,7 @@
 }
 
 void ChangePictureHandler::HandleRequestSelectedImage(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   SendSelectedImage();
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h
index 8bff44ce..81ee50b 100644
--- a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h
@@ -15,10 +15,6 @@
 #include "ui/gfx/native_widget_types.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace user_manager {
 class User;
 }
@@ -79,25 +75,25 @@
   void SetCameraPresent(bool present);
 
   // Opens a file selection dialog to choose user image from file.
-  void HandleChooseFile(const base::ListValue* args);
+  void HandleChooseFile(base::Value::ConstListView args);
 
   // Handles photo taken with WebRTC UI.
-  void HandlePhotoTaken(const base::ListValue* args);
+  void HandlePhotoTaken(base::Value::ConstListView args);
 
   // Handles 'discard-photo' button click.
-  void HandleDiscardPhoto(const base::ListValue* args);
+  void HandleDiscardPhoto(base::Value::ConstListView args);
 
   // Gets the list of available user images and sends it to the page.
-  void HandleGetAvailableImages(const base::ListValue* args);
+  void HandleGetAvailableImages(base::Value::ConstListView args);
 
   // Handles page initialized event.
-  void HandlePageInitialized(const base::ListValue* args);
+  void HandlePageInitialized(base::Value::ConstListView args);
 
   // Selects one of the available images as user's.
-  void HandleSelectImage(const base::ListValue* args);
+  void HandleSelectImage(base::Value::ConstListView args);
 
   // Requests the currently selected image.
-  void HandleRequestSelectedImage(const base::ListValue* args);
+  void HandleRequestSelectedImage(base::Value::ConstListView args);
 
   // ui::SelectFileDialog::Listener implementation.
   void FileSelected(const base::FilePath& path,
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index e69cdcf..da705461 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -276,81 +276,81 @@
 CupsPrintersHandler::~CupsPrintersHandler() = default;
 
 void CupsPrintersHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getCupsSavedPrintersList",
       base::BindRepeating(&CupsPrintersHandler::HandleGetCupsSavedPrintersList,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getCupsEnterprisePrintersList",
       base::BindRepeating(
           &CupsPrintersHandler::HandleGetCupsEnterprisePrintersList,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "updateCupsPrinter",
       base::BindRepeating(&CupsPrintersHandler::HandleUpdateCupsPrinter,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "removeCupsPrinter",
       base::BindRepeating(&CupsPrintersHandler::HandleRemoveCupsPrinter,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "addCupsPrinter",
       base::BindRepeating(&CupsPrintersHandler::HandleAddCupsPrinter,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "reconfigureCupsPrinter",
       base::BindRepeating(&CupsPrintersHandler::HandleReconfigureCupsPrinter,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getPrinterInfo",
       base::BindRepeating(&CupsPrintersHandler::HandleGetPrinterInfo,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getCupsPrinterManufacturersList",
       base::BindRepeating(
           &CupsPrintersHandler::HandleGetCupsPrinterManufacturers,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getCupsPrinterModelsList",
       base::BindRepeating(&CupsPrintersHandler::HandleGetCupsPrinterModels,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "selectPPDFile",
       base::BindRepeating(&CupsPrintersHandler::HandleSelectPPDFile,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "startDiscoveringPrinters",
       base::BindRepeating(&CupsPrintersHandler::HandleStartDiscovery,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "stopDiscoveringPrinters",
       base::BindRepeating(&CupsPrintersHandler::HandleStopDiscovery,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getPrinterPpdManufacturerAndModel",
       base::BindRepeating(
           &CupsPrintersHandler::HandleGetPrinterPpdManufacturerAndModel,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "addDiscoveredPrinter",
       base::BindRepeating(&CupsPrintersHandler::HandleAddDiscoveredPrinter,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "cancelPrinterSetUp",
       base::BindRepeating(&CupsPrintersHandler::HandleSetUpCancel,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getEulaUrl", base::BindRepeating(&CupsPrintersHandler::HandleGetEulaUrl,
                                         base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "queryPrintServer",
       base::BindRepeating(&CupsPrintersHandler::HandleQueryPrintServer,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "openPrintManagementApp",
       base::BindRepeating(&CupsPrintersHandler::HandleOpenPrintManagementApp,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "openScanningApp",
       base::BindRepeating(&CupsPrintersHandler::HandleOpenScanningApp,
                           base::Unretained(this)));
@@ -370,11 +370,11 @@
 }
 
 void CupsPrintersHandler::HandleGetCupsSavedPrintersList(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   std::vector<Printer> printers =
       printers_manager_->GetPrinters(PrinterClass::kSaved);
@@ -384,11 +384,11 @@
 }
 
 void CupsPrintersHandler::HandleGetCupsEnterprisePrintersList(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  std::string callback_id = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(1U, args.size());
+  std::string callback_id = args[0].GetString();
 
   std::vector<Printer> printers =
       printers_manager_->GetPrinters(PrinterClass::kEnterprise);
@@ -397,11 +397,12 @@
   ResolveJavascriptCallback(base::Value(callback_id), response);
 }
 
-void CupsPrintersHandler::HandleUpdateCupsPrinter(const base::ListValue* args) {
-  CHECK_EQ(3U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
-  const std::string& printer_id = args->GetListDeprecated()[1].GetString();
-  const std::string& printer_name = args->GetListDeprecated()[2].GetString();
+void CupsPrintersHandler::HandleUpdateCupsPrinter(
+    base::Value::ConstListView args) {
+  CHECK_EQ(3U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  const std::string& printer_id = args[1].GetString();
+  const std::string& printer_name = args[2].GetString();
 
   Printer printer(printer_id);
   printer.set_display_name(printer_name);
@@ -423,10 +424,11 @@
                                   PrinterSetupResult::kEditSuccess);
 }
 
-void CupsPrintersHandler::HandleRemoveCupsPrinter(const base::ListValue* args) {
+void CupsPrintersHandler::HandleRemoveCupsPrinter(
+    base::Value::ConstListView args) {
   PRINTER_LOG(USER) << "Removing printer";
   // Printer name also expected in 2nd parameter.
-  const std::string& printer_id = args->GetListDeprecated()[0].GetString();
+  const std::string& printer_id = args[0].GetString();
   auto printer = printers_manager_->GetPrinter(printer_id);
   if (!printer)
     return;
@@ -445,21 +447,20 @@
                             base::DoNothing());
 }
 
-void CupsPrintersHandler::HandleGetPrinterInfo(const base::ListValue* args) {
-  DCHECK(args);
-  if (args->GetListDeprecated().empty() ||
-      !args->GetListDeprecated()[0].is_string()) {
+void CupsPrintersHandler::HandleGetPrinterInfo(
+    base::Value::ConstListView args) {
+  if (args.empty() || !args[0].is_string()) {
     NOTREACHED() << "Expected request for a promise";
     return;
   }
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+  const std::string& callback_id = args[0].GetString();
 
-  if (args->GetListDeprecated().size() < 2u) {
+  if (args.size() < 2u) {
     NOTREACHED() << "Dictionary missing";
     return;
   }
 
-  const base::Value& printer_value = args->GetListDeprecated()[1];
+  const base::Value& printer_value = args[1];
   if (!printer_value.is_dict()) {
     NOTREACHED() << "Dictionary missing";
     return;
@@ -618,22 +619,24 @@
   ResolveJavascriptCallback(base::Value(callback_id), info);
 }
 
-void CupsPrintersHandler::HandleAddCupsPrinter(const base::ListValue* args) {
+void CupsPrintersHandler::HandleAddCupsPrinter(
+    base::Value::ConstListView args) {
   AllowJavascript();
   AddOrReconfigurePrinter(args, false /* is_printer_edit */);
 }
 
 void CupsPrintersHandler::HandleReconfigureCupsPrinter(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   AddOrReconfigurePrinter(args, true /* is_printer_edit */);
 }
 
-void CupsPrintersHandler::AddOrReconfigurePrinter(const base::ListValue* args,
-                                                  bool is_printer_edit) {
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  std::string callback_id = args->GetListDeprecated()[0].GetString();
-  const base::Value& printer_value = args->GetListDeprecated()[1];
+void CupsPrintersHandler::AddOrReconfigurePrinter(
+    base::Value::ConstListView args,
+    bool is_printer_edit) {
+  CHECK_EQ(2U, args.size());
+  std::string callback_id = args[0].GetString();
+  const base::Value& printer_value = args[1];
   CHECK(printer_value.is_dict());
   const base::DictionaryValue& printer_dict =
       base::Value::AsDictionaryValue(printer_value);
@@ -837,21 +840,21 @@
 }
 
 void CupsPrintersHandler::HandleGetCupsPrinterManufacturers(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
   ppd_provider_->ResolveManufacturers(
       base::BindOnce(&CupsPrintersHandler::ResolveManufacturersDone,
                      weak_factory_.GetWeakPtr(), callback_id));
 }
 
 void CupsPrintersHandler::HandleGetCupsPrinterModels(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
-  const std::string& manufacturer = args->GetListDeprecated()[1].GetString();
+  CHECK_EQ(2U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  const std::string& manufacturer = args[1].GetString();
 
   // Empty manufacturer queries may be triggered as a part of the ui
   // initialization, and should just return empty results.
@@ -869,9 +872,9 @@
                      weak_factory_.GetWeakPtr(), manufacturer, callback_id));
 }
 
-void CupsPrintersHandler::HandleSelectPPDFile(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  webui_callback_id_ = args->GetListDeprecated()[0].GetString();
+void CupsPrintersHandler::HandleSelectPPDFile(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  webui_callback_id_ = args[0].GetString();
 
   base::FilePath downloads_path =
       DownloadPrefs::FromDownloadManager(profile_->GetDownloadManager())
@@ -956,7 +959,8 @@
   webui_callback_id_.clear();
 }
 
-void CupsPrintersHandler::HandleStartDiscovery(const base::ListValue* args) {
+void CupsPrintersHandler::HandleStartDiscovery(
+    base::Value::ConstListView args) {
   PRINTER_LOG(DEBUG) << "Start printer discovery";
   AllowJavascript();
   discovery_active_ = true;
@@ -972,7 +976,7 @@
   FireWebUIListener("on-printer-discovery-done");
 }
 
-void CupsPrintersHandler::HandleStopDiscovery(const base::ListValue* args) {
+void CupsPrintersHandler::HandleStopDiscovery(base::Value::ConstListView args) {
   PRINTER_LOG(DEBUG) << "Stop printer discovery";
   discovered_printers_.clear();
   automatic_printers_.clear();
@@ -983,9 +987,9 @@
   discovery_active_ = false;
 }
 
-void CupsPrintersHandler::HandleSetUpCancel(const base::ListValue* args) {
+void CupsPrintersHandler::HandleSetUpCancel(base::Value::ConstListView args) {
   PRINTER_LOG(DEBUG) << "Printer setup cancelled";
-  const base::Value& printer_value = args->GetListDeprecated()[0];
+  const base::Value& printer_value = args[0];
   CHECK(printer_value.is_dict());
 
   std::unique_ptr<Printer> printer =
@@ -1046,11 +1050,11 @@
 }
 
 void CupsPrintersHandler::HandleAddDiscoveredPrinter(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
-  const std::string& printer_id = args->GetListDeprecated()[1].GetString();
+  CHECK_EQ(2U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  const std::string& printer_id = args[1].GetString();
 
   PRINTER_LOG(USER) << "Adding discovered printer";
   absl::optional<Printer> printer = printers_manager_->GetPrinter(printer_id);
@@ -1110,11 +1114,11 @@
 }
 
 void CupsPrintersHandler::HandleGetPrinterPpdManufacturerAndModel(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
-  const std::string& printer_id = args->GetListDeprecated()[1].GetString();
+  CHECK_EQ(2U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  const std::string& printer_id = args[1].GetString();
 
   auto printer = printers_manager_->GetPrinter(printer_id);
   if (!printer) {
@@ -1143,11 +1147,11 @@
   ResolveJavascriptCallback(base::Value(callback_id), info);
 }
 
-void CupsPrintersHandler::HandleGetEulaUrl(const base::ListValue* args) {
-  CHECK_EQ(3U, args->GetListDeprecated().size());
-  const std::string callback_id = args->GetListDeprecated()[0].GetString();
-  const std::string ppd_manufacturer = args->GetListDeprecated()[1].GetString();
-  const std::string ppd_model = args->GetListDeprecated()[2].GetString();
+void CupsPrintersHandler::HandleGetEulaUrl(base::Value::ConstListView args) {
+  CHECK_EQ(3U, args.size());
+  const std::string callback_id = args[0].GetString();
+  const std::string ppd_manufacturer = args[1].GetString();
+  const std::string ppd_model = args[2].GetString();
 
   auto resolved_printers_it = resolved_printers_.find(ppd_manufacturer);
   if (resolved_printers_it == resolved_printers_.end()) {
@@ -1221,10 +1225,11 @@
                            GetCupsPrinterInfo(printer));
 }
 
-void CupsPrintersHandler::HandleQueryPrintServer(const base::ListValue* args) {
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
-  const std::string& server_url = args->GetListDeprecated()[1].GetString();
+void CupsPrintersHandler::HandleQueryPrintServer(
+    base::Value::ConstListView args) {
+  CHECK_EQ(2U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  const std::string& server_url = args[1].GetString();
 
   absl::optional<GURL> converted_server_url =
       GenerateServerPrinterUrlWithValidScheme(server_url);
@@ -1302,13 +1307,14 @@
 }
 
 void CupsPrintersHandler::HandleOpenPrintManagementApp(
-    const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+    base::Value::ConstListView args) {
+  DCHECK(args.empty());
   chrome::ShowPrintManagementApp(profile_);
 }
 
-void CupsPrintersHandler::HandleOpenScanningApp(const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+void CupsPrintersHandler::HandleOpenScanningApp(
+    base::Value::ConstListView args) {
+  DCHECK(args.empty());
   chrome::ShowScanningApp(profile_);
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
index 55049bbeb..80a80ba 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
@@ -25,7 +25,6 @@
 
 namespace base {
 class FilePath;
-class ListValue;
 }  // namespace base
 
 namespace local_discovery {
@@ -74,14 +73,14 @@
                       CupsPrintersManager* printers_manager);
 
   // Gets all CUPS printers and return it to WebUI.
-  void HandleGetCupsSavedPrintersList(const base::ListValue* args);
-  void HandleGetCupsEnterprisePrintersList(const base::ListValue* args);
-  void HandleUpdateCupsPrinter(const base::ListValue* args);
-  void HandleRemoveCupsPrinter(const base::ListValue* args);
+  void HandleGetCupsSavedPrintersList(base::Value::ConstListView args);
+  void HandleGetCupsEnterprisePrintersList(base::Value::ConstListView args);
+  void HandleUpdateCupsPrinter(base::Value::ConstListView args);
+  void HandleRemoveCupsPrinter(base::Value::ConstListView args);
 
   // For a CupsPrinterInfo in |args|, retrieves the relevant PrinterInfo object
   // using an IPP call to the printer.
-  void HandleGetPrinterInfo(const base::ListValue* args);
+  void HandleGetPrinterInfo(base::Value::ConstListView args);
 
   // Handles the callback for HandleGetPrinterInfo. |callback_id| is the
   // identifier to resolve the correct Promise. |result| indicates if the query
@@ -114,11 +113,11 @@
                      const Printer::PpdReference& ppd_ref,
                      const std::string& usb_manufacturer);
 
-  void HandleAddCupsPrinter(const base::ListValue* args);
+  void HandleAddCupsPrinter(base::Value::ConstListView args);
 
-  void HandleReconfigureCupsPrinter(const base::ListValue* args);
+  void HandleReconfigureCupsPrinter(base::Value::ConstListView args);
 
-  void AddOrReconfigurePrinter(const base::ListValue* args,
+  void AddOrReconfigurePrinter(base::Value::ConstListView args,
                                bool is_printer_edit);
 
   // Handles the result of adding a printer which the user specified the
@@ -137,15 +136,15 @@
   // printer supported.  Takes one argument, the callback id for the result.
   // The callback will be invoked with {success: <boolean>, models:
   // <Array<string>>}.
-  void HandleGetCupsPrinterManufacturers(const base::ListValue* args);
+  void HandleGetCupsPrinterManufacturers(base::Value::ConstListView args);
 
   // Given a manufacturer, get a list of all models of printers for which we can
   // get drivers.  Takes two arguments - the callback id and the manufacturer
   // name for which we want to list models.  The callback will be called with
   // {success: <boolean>, models: Array<string>}.
-  void HandleGetCupsPrinterModels(const base::ListValue* args);
+  void HandleGetCupsPrinterModels(base::Value::ConstListView args);
 
-  void HandleSelectPPDFile(const base::ListValue* args);
+  void HandleSelectPPDFile(base::Value::ConstListView args);
 
   // PpdProvider callback handlers.
   void ResolveManufacturersDone(const std::string& callback_id,
@@ -156,14 +155,14 @@
                            PpdProvider::CallbackResultCode result_code,
                            const PpdProvider::ResolvedPrintersList& printers);
 
-  void HandleStartDiscovery(const base::ListValue* args);
-  void HandleStopDiscovery(const base::ListValue* args);
+  void HandleStartDiscovery(base::Value::ConstListView args);
+  void HandleStopDiscovery(base::Value::ConstListView args);
 
   // Logs printer set ups that are abandoned.
-  void HandleSetUpCancel(const base::ListValue* args);
+  void HandleSetUpCancel(base::Value::ConstListView args);
 
   // Given a printer id, find the corresponding ppdManufacturer and ppdModel.
-  void HandleGetPrinterPpdManufacturerAndModel(const base::ListValue* args);
+  void HandleGetPrinterPpdManufacturerAndModel(base::Value::ConstListView args);
   void OnGetPrinterPpdManufacturerAndModel(
       const std::string& callback_id,
       PpdProvider::CallbackResultCode result_code,
@@ -174,7 +173,7 @@
   void UpdateDiscoveredPrinters();
 
   // Attempt to add a discovered printer.
-  void HandleAddDiscoveredPrinter(const base::ListValue* args);
+  void HandleAddDiscoveredPrinter(base::Value::ConstListView args);
 
   // Post printer setup callback.
   void OnAddedDiscoveredPrinter(const std::string& callback_id,
@@ -191,7 +190,7 @@
                          const std::vector<Printer>& printers) override;
 
   // Handles getting the EULA URL if available.
-  void HandleGetEulaUrl(const base::ListValue* args);
+  void HandleGetEulaUrl(base::Value::ConstListView args);
 
   // Post EULA URL callback.
   void OnGetEulaUrl(const std::string& callback_id,
@@ -218,7 +217,7 @@
                     const Printer& printer,
                     const net::IPEndPoint& endpoint);
 
-  void HandleQueryPrintServer(const base::ListValue* args);
+  void HandleQueryPrintServer(base::Value::ConstListView args);
 
   void QueryPrintServer(const std::string& callback_id,
                         const GURL& server_url,
@@ -231,9 +230,9 @@
       const GURL& server_url,
       std::vector<PrinterDetector::DetectedPrinter>&& returned_printers);
 
-  void HandleOpenPrintManagementApp(const base::ListValue* args);
+  void HandleOpenPrintManagementApp(base::Value::ConstListView args);
 
-  void HandleOpenScanningApp(const base::ListValue* args);
+  void HandleOpenScanningApp(base::Value::ConstListView args);
 
   Profile* profile_;
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc b/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc
index 406c3fb..3dc254b3 100644
--- a/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc
@@ -69,18 +69,18 @@
 DateTimeHandler::~DateTimeHandler() = default;
 
 void DateTimeHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "dateTimePageReady",
       base::BindRepeating(&DateTimeHandler::HandleDateTimePageReady,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getTimeZones", base::BindRepeating(&DateTimeHandler::HandleGetTimeZones,
                                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showSetDateTimeUI",
       base::BindRepeating(&DateTimeHandler::HandleShowSetDateTimeUI,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "handleShowParentAccessForTimeZone",
       base::BindRepeating(&DateTimeHandler::HandleShowParentAccessForTimeZone,
                           base::Unretained(this)));
@@ -115,7 +115,7 @@
   local_state_pref_change_registrar_.RemoveAll();
 }
 
-void DateTimeHandler::HandleDateTimePageReady(const base::ListValue* args) {
+void DateTimeHandler::HandleDateTimePageReady(base::Value::ConstListView args) {
   AllowJavascript();
 
   // Send the time zone automatic detection policy in case it changed after the
@@ -123,15 +123,15 @@
   NotifyTimezoneAutomaticDetectionPolicy();
 }
 
-void DateTimeHandler::HandleGetTimeZones(const base::ListValue* args) {
+void DateTimeHandler::HandleGetTimeZones(base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+  CHECK_EQ(1U, args.size());
+  const base::Value& callback_id = args[0];
   ResolveJavascriptCallback(callback_id, *system::GetTimezoneList());
 }
 
-void DateTimeHandler::HandleShowSetDateTimeUI(const base::ListValue* args) {
+void DateTimeHandler::HandleShowSetDateTimeUI(base::Value::ConstListView args) {
   // Make sure the clock status hasn't changed since the button was clicked.
   if (!SystemClockClient::Get()->CanSetTime())
     return;
@@ -140,7 +140,7 @@
 }
 
 void DateTimeHandler::HandleShowParentAccessForTimeZone(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   DCHECK(user_manager::UserManager::Get()->GetActiveUser()->IsChild());
 
   if (!parent_access::ParentAccessService::IsApprovalRequired(
diff --git a/chrome/browser/ui/webui/settings/chromeos/date_time_handler.h b/chrome/browser/ui/webui/settings/chromeos/date_time_handler.h
index f017eb0..8d654d50 100644
--- a/chrome/browser/ui/webui/settings/chromeos/date_time_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/date_time_handler.h
@@ -12,10 +12,6 @@
 #include "chromeos/dbus/system_clock/system_clock_client.h"
 #include "components/prefs/pref_change_registrar.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace chromeos {
 namespace settings {
 
@@ -40,17 +36,17 @@
   void SystemClockCanSetTimeChanged(bool can_set_time) override;
 
   // Called when the page is ready.
-  void HandleDateTimePageReady(const base::ListValue* args);
+  void HandleDateTimePageReady(base::Value::ConstListView args);
 
   // Handler to fetch the list of time zones.
-  void HandleGetTimeZones(const base::ListValue* args);
+  void HandleGetTimeZones(base::Value::ConstListView args);
 
   // Called to show the Set Time UI.
-  void HandleShowSetDateTimeUI(const base::ListValue* args);
+  void HandleShowSetDateTimeUI(base::Value::ConstListView args);
 
   // Handles clicks on the timezone row on the settings page. This should only
   // be called when the current user is a child.
-  void HandleShowParentAccessForTimeZone(const base::ListValue* args);
+  void HandleShowParentAccessForTimeZone(base::Value::ConstListView args);
 
   // Called when the parent access code was validated with result equals
   // |success|.
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_display_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_display_handler.cc
index 5dab7bf..b51601f 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_display_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_display_handler.cc
@@ -24,26 +24,24 @@
 }
 
 void DisplayHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "highlightDisplay",
       base::BindRepeating(&DisplayHandler::HandleHighlightDisplay,
                           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "dragDisplayDelta",
       base::BindRepeating(&DisplayHandler::HandleDragDisplayDelta,
                           base::Unretained(this)));
 }
 
-void DisplayHandler::HandleHighlightDisplay(const base::ListValue* args) {
+void DisplayHandler::HandleHighlightDisplay(base::Value::ConstListView args) {
   AllowJavascript();
 
   int64_t display_id;
 
-  if (args->GetListDeprecated().empty() ||
-      !args->GetListDeprecated()[0].is_string() ||
-      !base::StringToInt64(args->GetListDeprecated()[0].GetString(),
-                           &display_id)) {
+  if (args.empty() || !args[0].is_string() ||
+      !base::StringToInt64(args[0].GetString(), &display_id)) {
     cros_display_config_->HighlightDisplay(display::kInvalidDisplayId);
     return;
   }
@@ -51,11 +49,11 @@
   cros_display_config_->HighlightDisplay(display_id);
 }
 
-void DisplayHandler::HandleDragDisplayDelta(const base::ListValue* args) {
-  DCHECK_EQ(3U, args->GetListDeprecated().size());
+void DisplayHandler::HandleDragDisplayDelta(base::Value::ConstListView args) {
+  DCHECK_EQ(3U, args.size());
   AllowJavascript();
 
-  const auto& args_list = args->GetListDeprecated();
+  const auto& args_list = args;
   const std::string& display_id_str = args_list[0].GetString();
   int32_t delta_x = static_cast<int32_t>(args_list[1].GetInt());
   int32_t delta_y = static_cast<int32_t>(args_list[2].GetInt());
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_display_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_display_handler.h
index 0331b77..a9b5ab0 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_display_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/device_display_handler.h
@@ -10,10 +10,6 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
-namespace base {
-class ListValue;
-}  // namespace base
-
 namespace chromeos {
 namespace settings {
 
@@ -31,8 +27,8 @@
   void OnJavascriptDisallowed() override {}
 
  private:
-  void HandleHighlightDisplay(const base::ListValue* args);
-  void HandleDragDisplayDelta(const base::ListValue* args);
+  void HandleHighlightDisplay(base::Value::ConstListView args);
+  void HandleDragDisplayDelta(base::Value::ConstListView args);
 
   mojo::Remote<ash::mojom::CrosDisplayConfigController> cros_display_config_;
 };
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
index d6ba540..90395f89 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
@@ -59,23 +59,22 @@
 const char KeyboardHandler::kShowKeysChangedName[] = "show-keys-changed";
 
 void KeyboardHandler::TestAPI::Initialize() {
-  base::ListValue args;
-  handler_->HandleInitialize(&args);
+  handler_->HandleInitialize(base::Value::ConstListView());
 }
 
 KeyboardHandler::KeyboardHandler() = default;
 KeyboardHandler::~KeyboardHandler() = default;
 
 void KeyboardHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "initializeKeyboardSettings",
       base::BindRepeating(&KeyboardHandler::HandleInitialize,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showKeyboardShortcutViewer",
       base::BindRepeating(&KeyboardHandler::HandleShowKeyboardShortcutViewer,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "initializeKeyboardWatcher",
       base::BindRepeating(&KeyboardHandler::HandleKeyboardChange,
                           base::Unretained(this)));
@@ -98,18 +97,18 @@
   }
 }
 
-void KeyboardHandler::HandleInitialize(const base::ListValue* args) {
+void KeyboardHandler::HandleInitialize(base::Value::ConstListView args) {
   AllowJavascript();
   UpdateShowKeys();
   UpdateKeyboards();
 }
 
 void KeyboardHandler::HandleShowKeyboardShortcutViewer(
-    const base::ListValue* args) const {
+    base::Value::ConstListView args) const {
   ash::ToggleKeyboardShortcutViewer();
 }
 
-void KeyboardHandler::HandleKeyboardChange(const base::ListValue* args) {
+void KeyboardHandler::HandleKeyboardChange(base::Value::ConstListView args) {
   AllowJavascript();
   UpdateKeyboards();
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h
index 8cfc038b..6bbcaa3 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h
@@ -10,10 +10,6 @@
 #include "ui/events/devices/device_data_manager.h"
 #include "ui/events/devices/input_device_event_observer.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace chromeos {
 namespace settings {
 
@@ -58,13 +54,13 @@
 
  private:
   // Initializes the page with the current keyboard information.
-  void HandleInitialize(const base::ListValue* args);
+  void HandleInitialize(base::Value::ConstListView args);
 
   // Shows the Ash keyboard shortcut viewer.
-  void HandleShowKeyboardShortcutViewer(const base::ListValue* args) const;
+  void HandleShowKeyboardShortcutViewer(base::Value::ConstListView args) const;
 
   // Determines what types of keyboards are attached.
-  void HandleKeyboardChange(const base::ListValue* args);
+  void HandleKeyboardChange(base::Value::ConstListView args);
 
   // Shows or hides the Caps Lock and Diamond key settings based on whether the
   // system status.
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_name_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_name_handler.cc
index bce9295..a0cb89e1 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_name_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_name_handler.cc
@@ -40,12 +40,12 @@
 }
 
 void DeviceNameHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "notifyReadyForDeviceName",
       base::BindRepeating(&DeviceNameHandler::HandleNotifyReadyForDeviceName,
                           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "attemptSetDeviceName",
       base::BindRepeating(&DeviceNameHandler::HandleAttemptSetDeviceName,
                           base::Unretained(this)));
@@ -62,11 +62,11 @@
 }
 
 void DeviceNameHandler::HandleAttemptSetDeviceName(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  DCHECK_EQ(2U, args->GetListDeprecated().size());
-  const base::Value::ConstListView args_list = args->GetListDeprecated();
+  DCHECK_EQ(2U, args.size());
+  const base::Value::ConstListView args_list = args;
   const std::string callback_id = args_list[0].GetString();
   const std::string name_from_user = args_list[1].GetString();
   DeviceNameStore::SetDeviceNameResult result =
@@ -77,7 +77,7 @@
 }
 
 void DeviceNameHandler::HandleNotifyReadyForDeviceName(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   FireWebUIListener("settings.updateDeviceNameMetadata",
                     base::Value(GetDeviceNameMetadata()));
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_name_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_name_handler.h
index f1f87404..9a6fbdda 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_name_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/device_name_handler.h
@@ -9,10 +9,6 @@
 #include "chrome/browser/ash/device_name/device_name_store.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace chromeos {
 namespace settings {
 
@@ -34,8 +30,8 @@
   void OnJavascriptDisallowed() override;
 
  protected:
-  void HandleAttemptSetDeviceName(const base::ListValue* args);
-  void HandleNotifyReadyForDeviceName(const base::ListValue* args);
+  void HandleAttemptSetDeviceName(base::Value::ConstListView args);
+  void HandleNotifyReadyForDeviceName(base::Value::ConstListView args);
 
  private:
   friend class TestDeviceNameHandler;
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_name_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/device_name_handler_unittest.cc
index 67f62ad..55dc0d3 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_name_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_name_handler_unittest.cc
@@ -49,7 +49,7 @@
     // listening to changes in device name metadata.
     base::Value args(base::Value::Type::LIST);
     args.Append("callback-id");
-    handler()->HandleNotifyReadyForDeviceName(&base::Value::AsListValue(args));
+    handler()->HandleNotifyReadyForDeviceName(args.GetListDeprecated());
 
     // On notifying, device name metadata should be received and be equal to the
     // default values.
@@ -87,7 +87,7 @@
     base::Value args(base::Value::Type::LIST);
     args.Append("callback-id");
     args.Append(device_name);
-    handler()->HandleAttemptSetDeviceName(&base::Value::AsListValue(args));
+    handler()->HandleAttemptSetDeviceName(args.GetListDeprecated());
 
     const content::TestWebUI::CallData& call_data =
         *web_ui()->call_data().back();
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.cc
index f36dcf2..b3b22e0 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.cc
@@ -16,7 +16,7 @@
 PointerHandler::~PointerHandler() {}
 
 void PointerHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "initializePointerSettings",
       base::BindRepeating(&PointerHandler::HandleInitialize,
                           base::Unretained(this)));
@@ -52,7 +52,7 @@
   FireWebUIListener("has-pointing-stick-changed", base::Value(exists));
 }
 
-void PointerHandler::HandleInitialize(const base::ListValue* args) {
+void PointerHandler::HandleInitialize(base::Value::ConstListView args) {
   AllowJavascript();
 
   // CheckDevices() results in TouchpadExists() and MouseExists() being called.
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h
index 2bc0da3..8e4318d 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h
@@ -10,10 +10,6 @@
 #include "chrome/browser/ash/system/pointer_device_observer.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace chromeos {
 namespace settings {
 
@@ -42,7 +38,7 @@
   void PointingStickExists(bool exists) override;
 
   // Initializes the page with the current pointer information.
-  void HandleInitialize(const base::ListValue* args);
+  void HandleInitialize(base::Value::ConstListView args);
 
   std::unique_ptr<chromeos::system::PointerDeviceObserver>
       pointer_device_observer_;
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
index d2d45cc..7f93962e 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
@@ -116,8 +116,7 @@
 
 void PowerHandler::TestAPI::RequestPowerManagementSettings() {
   base::Value args(base::Value::Type::LIST);
-  handler_->HandleRequestPowerManagementSettings(
-      &base::Value::AsListValue(args));
+  handler_->HandleRequestPowerManagementSettings(args.GetListDeprecated());
 }
 
 void PowerHandler::TestAPI::SetIdleBehavior(IdleBehavior behavior,
@@ -125,14 +124,14 @@
   base::Value args(base::Value::Type::LIST);
   args.Append(static_cast<int>(behavior));
   args.Append(when_on_ac);
-  handler_->HandleSetIdleBehavior(&base::Value::AsListValue(args));
+  handler_->HandleSetIdleBehavior(args.GetListDeprecated());
 }
 
 void PowerHandler::TestAPI::SetLidClosedBehavior(
     PowerPolicyController::Action behavior) {
   base::Value args(base::Value::Type::LIST);
   args.Append(behavior);
-  handler_->HandleSetLidClosedBehavior(&base::Value::AsListValue(args));
+  handler_->HandleSetLidClosedBehavior(args.GetListDeprecated());
 }
 
 PowerHandler::PowerHandler(PrefService* prefs) : prefs_(prefs) {}
@@ -140,22 +139,22 @@
 PowerHandler::~PowerHandler() {}
 
 void PowerHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "updatePowerStatus",
       base::BindRepeating(&PowerHandler::HandleUpdatePowerStatus,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setPowerSource", base::BindRepeating(&PowerHandler::HandleSetPowerSource,
                                             base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "requestPowerManagementSettings",
       base::BindRepeating(&PowerHandler::HandleRequestPowerManagementSettings,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setLidClosedBehavior",
       base::BindRepeating(&PowerHandler::HandleSetLidClosedBehavior,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setIdleBehavior",
       base::BindRepeating(&PowerHandler::HandleSetIdleBehavior,
                           base::Unretained(this)));
@@ -209,28 +208,28 @@
   SendPowerManagementSettings(false /* force */);
 }
 
-void PowerHandler::HandleUpdatePowerStatus(const base::ListValue* args) {
+void PowerHandler::HandleUpdatePowerStatus(base::Value::ConstListView args) {
   AllowJavascript();
   chromeos::PowerManagerClient::Get()->RequestStatusUpdate();
 }
 
-void PowerHandler::HandleSetPowerSource(const base::ListValue* args) {
+void PowerHandler::HandleSetPowerSource(base::Value::ConstListView args) {
   AllowJavascript();
 
-  const std::string& id = args->GetListDeprecated()[0].GetString();
+  const std::string& id = args[0].GetString();
   chromeos::PowerManagerClient::Get()->SetPowerSource(id);
 }
 
 void PowerHandler::HandleRequestPowerManagementSettings(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   SendPowerManagementSettings(true /* force */);
 }
 
-void PowerHandler::HandleSetIdleBehavior(const base::ListValue* args) {
+void PowerHandler::HandleSetIdleBehavior(base::Value::ConstListView args) {
   AllowJavascript();
 
-  const auto& list = args->GetListDeprecated();
+  const auto& list = args;
   CHECK_GE(list.size(), 2u);
   int value = list[0].GetInt();
   bool when_on_ac = list[1].GetBool();
@@ -277,10 +276,10 @@
   }
 }
 
-void PowerHandler::HandleSetLidClosedBehavior(const base::ListValue* args) {
+void PowerHandler::HandleSetLidClosedBehavior(base::Value::ConstListView args) {
   AllowJavascript();
 
-  const auto& list = args->GetListDeprecated();
+  const auto& list = args;
   CHECK_GE(list.size(), 1u);
   int value = list[0].GetInt();
   switch (static_cast<PowerPolicyController::Action>(value)) {
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
index c0af573f..e50bbd2c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
@@ -19,7 +19,6 @@
 class PrefService;
 
 namespace base {
-class ListValue;
 class TimeTicks;
 }  // namespace base
 
@@ -120,18 +119,18 @@
   };
 
   // Handler to request updating the power status.
-  void HandleUpdatePowerStatus(const base::ListValue* args);
+  void HandleUpdatePowerStatus(base::Value::ConstListView args);
 
   // Handler to change the power source.
-  void HandleSetPowerSource(const base::ListValue* args);
+  void HandleSetPowerSource(base::Value::ConstListView args);
 
   // Handler to request the current power management settings. Just calls
   // SendPowerManagementSettings().
-  void HandleRequestPowerManagementSettings(const base::ListValue* args);
+  void HandleRequestPowerManagementSettings(base::Value::ConstListView args);
 
   // Handlers to change the idle and lid-closed behaviors.
-  void HandleSetIdleBehavior(const base::ListValue* args);
-  void HandleSetLidClosedBehavior(const base::ListValue* args);
+  void HandleSetIdleBehavior(base::Value::ConstListView args);
+  void HandleSetLidClosedBehavior(base::Value::ConstListView args);
 
   // Updates the UI with the current battery status.
   void SendBatteryStatus();
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
index 4d64bbd..6addee03 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
@@ -85,22 +85,22 @@
 void StorageHandler::RegisterMessages() {
   DCHECK(web_ui());
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "updateAndroidEnabled",
       base::BindRepeating(&StorageHandler::HandleUpdateAndroidEnabled,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "updateStorageInfo",
       base::BindRepeating(&StorageHandler::HandleUpdateStorageInfo,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "openMyFiles", base::BindRepeating(&StorageHandler::HandleOpenMyFiles,
                                          base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "openArcStorage",
       base::BindRepeating(&StorageHandler::HandleOpenArcStorage,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "updateExternalStorages",
       base::BindRepeating(&StorageHandler::HandleUpdateExternalStorages,
                           base::Unretained(this)));
@@ -161,12 +161,12 @@
 }
 
 void StorageHandler::HandleUpdateAndroidEnabled(
-    const base::ListValue* unused_args) {
+    base::Value::ConstListView unused_args) {
   // OnJavascriptAllowed() calls ArcSessionManager::AddObserver() later.
   AllowJavascript();
 }
 
-void StorageHandler::HandleUpdateStorageInfo(const base::ListValue* args) {
+void StorageHandler::HandleUpdateStorageInfo(base::Value::ConstListView args) {
   AllowJavascript();
   total_disk_space_calculator_.StartCalculation();
   free_disk_space_calculator_.StartCalculation();
@@ -177,7 +177,7 @@
   other_users_size_calculator_.StartCalculation();
 }
 
-void StorageHandler::HandleOpenMyFiles(const base::ListValue* unused_args) {
+void StorageHandler::HandleOpenMyFiles(base::Value::ConstListView unused_args) {
   const base::FilePath my_files_path =
       file_manager::util::GetMyFilesFolderForProfile(profile_);
   platform_util::OpenItem(profile_, my_files_path, platform_util::OPEN_FOLDER,
@@ -185,7 +185,7 @@
 }
 
 void StorageHandler::HandleOpenArcStorage(
-    const base::ListValue* unused_args) {
+    base::Value::ConstListView unused_args) {
   auto* arc_storage_manager =
       arc::ArcStorageManager::GetForBrowserContext(profile_);
   if (arc_storage_manager)
@@ -193,7 +193,7 @@
 }
 
 void StorageHandler::HandleUpdateExternalStorages(
-    const base::ListValue* unused_args) {
+    base::Value::ConstListView unused_args) {
   UpdateExternalStorages();
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h
index 161bb176..3d8552c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h
@@ -83,11 +83,11 @@
 
  private:
   // Handlers of JS messages.
-  void HandleUpdateAndroidEnabled(const base::ListValue* unused_args);
-  void HandleUpdateStorageInfo(const base::ListValue* unused_args);
-  void HandleOpenMyFiles(const base::ListValue* unused_args);
-  void HandleOpenArcStorage(const base::ListValue* unused_args);
-  void HandleUpdateExternalStorages(const base::ListValue* unused_args);
+  void HandleUpdateAndroidEnabled(base::Value::ConstListView unused_args);
+  void HandleUpdateStorageInfo(base::Value::ConstListView unused_args);
+  void HandleOpenMyFiles(base::Value::ConstListView unused_args);
+  void HandleOpenArcStorage(base::Value::ConstListView unused_args);
+  void HandleUpdateExternalStorages(base::Value::ConstListView unused_args);
 
   // Updates storage row on the UI.
   void UpdateStorageItem(
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc
index 6caa5e6..0de6550 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc
@@ -38,24 +38,24 @@
 
   // Note: initializeStylusSettings must be called before observers will be
   // added.
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "initializeStylusSettings",
       base::BindRepeating(&StylusHandler::HandleInitialize,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "requestNoteTakingApps",
       base::BindRepeating(&StylusHandler::HandleRequestApps,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setPreferredNoteTakingApp",
       base::BindRepeating(&StylusHandler::HandleSetPreferredNoteTakingApp,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setPreferredNoteTakingAppEnabledOnLockScreen",
       base::BindRepeating(
           &StylusHandler::HandleSetPreferredNoteTakingAppEnabledOnLockScreen,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showPlayStoreApps",
       base::BindRepeating(&StylusHandler::HandleShowPlayStoreApps,
                           base::Unretained(this)));
@@ -114,14 +114,14 @@
                     base::Value(waiting_for_android));
 }
 
-void StylusHandler::HandleRequestApps(const base::ListValue* unused_args) {
+void StylusHandler::HandleRequestApps(base::Value::ConstListView unused_args) {
   AllowJavascript();
   UpdateNoteTakingApps();
 }
 
 void StylusHandler::HandleSetPreferredNoteTakingApp(
-    const base::ListValue* args) {
-  const std::string& app_id = args->GetListDeprecated()[0].GetString();
+    base::Value::ConstListView args) {
+  const std::string& app_id = args[0].GetString();
 
   // Sanity check: make sure that the ID we got back from WebUI is in the
   // currently-available set.
@@ -135,16 +135,16 @@
 }
 
 void StylusHandler::HandleSetPreferredNoteTakingAppEnabledOnLockScreen(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   bool enabled = false;
-  CHECK(args->GetListDeprecated()[0].is_bool());
-  enabled = args->GetListDeprecated()[0].GetBool();
+  CHECK(args[0].is_bool());
+  enabled = args[0].GetBool();
 
   NoteTakingHelper::Get()->SetPreferredAppEnabledOnLockScreen(
       Profile::FromWebUI(web_ui()), enabled);
 }
 
-void StylusHandler::HandleInitialize(const base::ListValue* args) {
+void StylusHandler::HandleInitialize(base::Value::ConstListView args) {
   AllowJavascript();
   if (ui::DeviceDataManager::GetInstance()->AreDeviceListsComplete())
     SendHasStylus();
@@ -156,10 +156,8 @@
                     base::Value(ash::stylus_utils::HasStylusInput()));
 }
 
-void StylusHandler::HandleShowPlayStoreApps(const base::ListValue* args) {
-  const std::string& apps_url = !args->GetListDeprecated().empty()
-                                    ? args->GetListDeprecated()[0].GetString()
-                                    : "";
+void StylusHandler::HandleShowPlayStoreApps(base::Value::ConstListView args) {
+  const std::string& apps_url = !args.empty() ? args[0].GetString() : "";
   Profile* profile = Profile::FromWebUI(web_ui());
   if (!arc::IsArcAllowedForProfile(profile)) {
     VLOG(1) << "ARC is not enabled for this profile";
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h
index 7408e950..976b4f7 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h
@@ -14,10 +14,6 @@
 #include "ui/events/devices/device_data_manager.h"
 #include "ui/events/devices/input_device_event_observer.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace chromeos {
 namespace settings {
 
@@ -47,17 +43,17 @@
 
  private:
   void UpdateNoteTakingApps();
-  void HandleRequestApps(const base::ListValue* unused_args);
-  void HandleSetPreferredNoteTakingApp(const base::ListValue* args);
+  void HandleRequestApps(base::Value::ConstListView unused_args);
+  void HandleSetPreferredNoteTakingApp(base::Value::ConstListView args);
   void HandleSetPreferredNoteTakingAppEnabledOnLockScreen(
-      const base::ListValue* args);
-  void HandleInitialize(const base::ListValue* args);
+      base::Value::ConstListView args);
+  void HandleInitialize(base::Value::ConstListView args);
 
   // Enables or disables the stylus UI section.
   void SendHasStylus();
 
   // Called by JS to show the Play Store Android app.
-  void HandleShowPlayStoreApps(const base::ListValue* args);
+  void HandleShowPlayStoreApps(base::Value::ConstListView args);
 
   // IDs of available note-taking apps.
   std::set<std::string> note_taking_app_ids_;
diff --git a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
index a5da4397..2b44e021 100644
--- a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
@@ -64,38 +64,38 @@
 
 void FingerprintHandler::RegisterMessages() {
   // Note: getFingerprintsList must be called before observers will be added.
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getFingerprintsList",
       base::BindRepeating(&FingerprintHandler::HandleGetFingerprintsList,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getNumFingerprints",
       base::BindRepeating(&FingerprintHandler::HandleGetNumFingerprints,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "startEnroll", base::BindRepeating(&FingerprintHandler::HandleStartEnroll,
                                          base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "cancelCurrentEnroll",
       base::BindRepeating(&FingerprintHandler::HandleCancelCurrentEnroll,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getEnrollmentLabel",
       base::BindRepeating(&FingerprintHandler::HandleGetEnrollmentLabel,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "removeEnrollment",
       base::BindRepeating(&FingerprintHandler::HandleRemoveEnrollment,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "changeEnrollmentLabel",
       base::BindRepeating(&FingerprintHandler::HandleChangeEnrollmentLabel,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "startAuthentication",
       base::BindRepeating(&FingerprintHandler::HandleStartAuthentication,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "endCurrentAuthentication",
       base::BindRepeating(&FingerprintHandler::HandleEndCurrentAuthentication,
                           base::Unretained(this)));
@@ -159,9 +159,9 @@
 }
 
 void FingerprintHandler::HandleGetFingerprintsList(
-    const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+    base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   AllowJavascript();
   fp_service_->GetRecordsForUser(
@@ -188,9 +188,10 @@
   ResolveJavascriptCallback(base::Value(callback_id), *fingerprint_info);
 }
 
-void FingerprintHandler::HandleGetNumFingerprints(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+void FingerprintHandler::HandleGetNumFingerprints(
+    base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   int fingerprints_num =
       profile_->GetPrefs()->GetInteger(prefs::kQuickUnlockFingerprintRecord);
@@ -200,10 +201,10 @@
                             base::Value(fingerprints_num));
 }
 
-void FingerprintHandler::HandleStartEnroll(const base::ListValue* args) {
+void FingerprintHandler::HandleStartEnroll(base::Value::ConstListView args) {
   AllowJavascript();
 
-  const std::string& auth_token = args->GetListDeprecated()[0].GetString();
+  const std::string& auth_token = args[0].GetString();
 
   // Auth token expiration will trigger password prompt.
   // Silently fail if auth token is incorrect.
@@ -227,7 +228,7 @@
 }
 
 void FingerprintHandler::HandleCancelCurrentEnroll(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   fp_service_->CancelCurrentEnrollSession(
       base::BindOnce(&FingerprintHandler::OnCancelCurrentEnrollSession,
@@ -239,8 +240,9 @@
     LOG(ERROR) << "Failed to cancel current fingerprint enroll session.";
 }
 
-void FingerprintHandler::HandleGetEnrollmentLabel(const base::ListValue* args) {
-  const auto& list = args->GetListDeprecated();
+void FingerprintHandler::HandleGetEnrollmentLabel(
+    base::Value::ConstListView args) {
+  const auto& list = args;
   CHECK_EQ(2U, list.size());
   std::string callback_id = list[0].GetString();
   int index = list[1].GetInt();
@@ -259,8 +261,9 @@
   ResolveJavascriptCallback(base::Value(callback_id), base::Value(label));
 }
 
-void FingerprintHandler::HandleRemoveEnrollment(const base::ListValue* args) {
-  const auto& list = args->GetListDeprecated();
+void FingerprintHandler::HandleRemoveEnrollment(
+    base::Value::ConstListView args) {
+  const auto& list = args;
   CHECK_EQ(2U, list.size());
   std::string callback_id = list[0].GetString();
   int index = list[1].GetInt();
@@ -282,8 +285,8 @@
 }
 
 void FingerprintHandler::HandleChangeEnrollmentLabel(
-    const base::ListValue* args) {
-  const auto& list = args->GetListDeprecated();
+    base::Value::ConstListView args) {
+  const auto& list = args;
   CHECK_EQ(3U, list.size());
 
   std::string callback_id = list[0].GetString();
@@ -308,13 +311,13 @@
 }
 
 void FingerprintHandler::HandleStartAuthentication(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   fp_service_->StartAuthSession();
 }
 
 void FingerprintHandler::HandleEndCurrentAuthentication(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   fp_service_->EndCurrentAuthSession(
       base::BindOnce(&FingerprintHandler::OnEndCurrentAuthSession,
diff --git a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h
index 565b39a..7cfc5243d 100644
--- a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h
@@ -16,10 +16,6 @@
 
 class Profile;
 
-namespace base {
-class ListValue;
-}  // namespace base
-
 namespace chromeos {
 namespace settings {
 
@@ -55,15 +51,15 @@
   void OnSessionStateChanged() override;
 
  private:
-  void HandleGetFingerprintsList(const base::ListValue* args);
-  void HandleGetNumFingerprints(const base::ListValue* args);
-  void HandleStartEnroll(const base::ListValue* args);
-  void HandleCancelCurrentEnroll(const base::ListValue* args);
-  void HandleGetEnrollmentLabel(const base::ListValue* args);
-  void HandleRemoveEnrollment(const base::ListValue* args);
-  void HandleChangeEnrollmentLabel(const base::ListValue* args);
-  void HandleStartAuthentication(const base::ListValue* args);
-  void HandleEndCurrentAuthentication(const base::ListValue* args);
+  void HandleGetFingerprintsList(base::Value::ConstListView args);
+  void HandleGetNumFingerprints(base::Value::ConstListView args);
+  void HandleStartEnroll(base::Value::ConstListView args);
+  void HandleCancelCurrentEnroll(base::Value::ConstListView args);
+  void HandleGetEnrollmentLabel(base::Value::ConstListView args);
+  void HandleRemoveEnrollment(base::Value::ConstListView args);
+  void HandleChangeEnrollmentLabel(base::Value::ConstListView args);
+  void HandleStartAuthentication(base::Value::ConstListView args);
+  void HandleEndCurrentAuthentication(base::Value::ConstListView args);
 
   void OnGetFingerprintsList(const std::string& callback_id,
                              const base::flat_map<std::string, std::string>&
diff --git a/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc b/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
index 05725bee..bdfad8c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
@@ -51,49 +51,50 @@
 }
 
 void GoogleAssistantHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showGoogleAssistantSettings",
       base::BindRepeating(
           &GoogleAssistantHandler::HandleShowGoogleAssistantSettings,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "retrainAssistantVoiceModel",
       base::BindRepeating(&GoogleAssistantHandler::HandleRetrainVoiceModel,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "syncVoiceModelStatus",
       base::BindRepeating(&GoogleAssistantHandler::HandleSyncVoiceModelStatus,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "initializeGoogleAssistantPage",
       base::BindRepeating(&GoogleAssistantHandler::HandleInitialized,
                           base::Unretained(this)));
 }
 
 void GoogleAssistantHandler::HandleShowGoogleAssistantSettings(
-    const base::ListValue* args) {
-  CHECK_EQ(0U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  CHECK_EQ(0U, args.size());
   ash::AssistantController::Get()->OpenAssistantSettings();
 }
 
 void GoogleAssistantHandler::HandleRetrainVoiceModel(
-    const base::ListValue* args) {
-  CHECK_EQ(0U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  CHECK_EQ(0U, args.size());
   chromeos::AssistantOptInDialog::Show(ash::FlowType::kSpeakerIdRetrain,
                                        base::DoNothing());
 }
 
 void GoogleAssistantHandler::HandleSyncVoiceModelStatus(
-    const base::ListValue* args) {
-  CHECK_EQ(0U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  CHECK_EQ(0U, args.size());
 
   auto* settings = assistant::AssistantSettings::Get();
   if (settings)
     settings->SyncSpeakerIdEnrollmentStatus();
 }
 
-void GoogleAssistantHandler::HandleInitialized(const base::ListValue* args) {
-  CHECK_EQ(0U, args->GetListDeprecated().size());
+void GoogleAssistantHandler::HandleInitialized(
+    base::Value::ConstListView args) {
+  CHECK_EQ(0U, args.size());
   AllowJavascript();
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.h b/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.h
index 0c48147..6a8939c2 100644
--- a/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.h
@@ -31,13 +31,13 @@
 
  private:
   // WebUI call to launch into the Google Assistant app settings.
-  void HandleShowGoogleAssistantSettings(const base::ListValue* args);
+  void HandleShowGoogleAssistantSettings(base::Value::ConstListView args);
   // WebUI call to retrain Assistant voice model.
-  void HandleRetrainVoiceModel(const base::ListValue* args);
+  void HandleRetrainVoiceModel(base::Value::ConstListView args);
   // WebUI call to sync Assistant voice model status.
-  void HandleSyncVoiceModelStatus(const base::ListValue* args);
+  void HandleSyncVoiceModelStatus(base::Value::ConstListView args);
   // WebUI call to signal js side is ready.
-  void HandleInitialized(const base::ListValue* args);
+  void HandleInitialized(base::Value::ConstListView args);
 
   bool pending_hotword_update_ = false;
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.cc b/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.cc
index a5342068..5292baa 100644
--- a/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.cc
@@ -42,21 +42,21 @@
 GuestOsHandler::~GuestOsHandler() = default;
 
 void GuestOsHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getGuestOsSharedPathsDisplayText",
       base::BindRepeating(
           &GuestOsHandler::HandleGetGuestOsSharedPathsDisplayText,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "removeGuestOsSharedPath",
       base::BindRepeating(&GuestOsHandler::HandleRemoveGuestOsSharedPath,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "notifyGuestOsSharedUsbDevicesPageReady",
       base::BindRepeating(
           &GuestOsHandler::HandleNotifyGuestOsSharedUsbDevicesPageReady,
           weak_ptr_factory_.GetWeakPtr()));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setGuestOsUsbDeviceShared",
       base::BindRepeating(&GuestOsHandler::HandleSetGuestOsUsbDeviceShared,
                           weak_ptr_factory_.GetWeakPtr()));
@@ -73,13 +73,13 @@
 }
 
 void GuestOsHandler::HandleGetGuestOsSharedPathsDisplayText(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  std::string callback_id = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(2U, args.size());
+  std::string callback_id = args[0].GetString();
 
   base::Value texts(base::Value::Type::LIST);
-  for (const auto& path : args->GetListDeprecated()[1].GetListDeprecated()) {
+  for (const auto& path : args[1].GetListDeprecated()) {
     texts.Append(file_manager::util::GetPathDisplayTextForSettings(
         profile_, path.GetString()));
   }
@@ -87,11 +87,11 @@
 }
 
 void GuestOsHandler::HandleRemoveGuestOsSharedPath(
-    const base::ListValue* args) {
-  CHECK_EQ(3U, args->GetListDeprecated().size());
-  std::string callback_id = args->GetListDeprecated()[0].GetString();
-  std::string vm_name = args->GetListDeprecated()[1].GetString();
-  std::string path = args->GetListDeprecated()[2].GetString();
+    base::Value::ConstListView args) {
+  CHECK_EQ(3U, args.size());
+  std::string callback_id = args[0].GetString();
+  std::string vm_name = args[1].GetString();
+  std::string path = args[2].GetString();
 
   guest_os::GuestOsSharePath::GetForProfile(profile_)->UnsharePath(
       vm_name, base::FilePath(path),
@@ -112,15 +112,15 @@
 }
 
 void GuestOsHandler::HandleNotifyGuestOsSharedUsbDevicesPageReady(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   OnUsbDevicesChanged();
 }
 
 void GuestOsHandler::HandleSetGuestOsUsbDeviceShared(
-    const base::ListValue* args) {
-  CHECK_EQ(3U, args->GetListDeprecated().size());
-  const auto& args_list = args->GetListDeprecated();
+    base::Value::ConstListView args) {
+  CHECK_EQ(3U, args.size());
+  const auto& args_list = args;
   const std::string& vm_name = args_list[0].GetString();
   const std::string& guid = args_list[1].GetString();
   bool shared = args_list[2].GetBool();
diff --git a/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.h b/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.h
index e7954f7..037706c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.h
@@ -37,14 +37,14 @@
   // Callback for the "getSharedPathsDisplayText" message.  Converts actual
   // paths in chromeos to values suitable to display to users.
   // E.g. /home/chronos/u-<hash>/Downloads/foo => "Downloads > foo".
-  void HandleGetGuestOsSharedPathsDisplayText(const base::ListValue* args);
+  void HandleGetGuestOsSharedPathsDisplayText(base::Value::ConstListView args);
   // Remove a specified path from being shared.
-  void HandleRemoveGuestOsSharedPath(const base::ListValue* args);
+  void HandleRemoveGuestOsSharedPath(base::Value::ConstListView args);
   // Called when the shared USB devices page is ready.
   void HandleNotifyGuestOsSharedUsbDevicesPageReady(
-      const base::ListValue* args);
+      base::Value::ConstListView args);
   // Set the share state of a USB device.
-  void HandleSetGuestOsUsbDeviceShared(const base::ListValue* args);
+  void HandleSetGuestOsUsbDeviceShared(base::Value::ConstListView args);
 
   void OnGuestOsSharedPathRemoved(const std::string& callback_id,
                                   const std::string& path,
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
index bed3051b..d2e8f12 100644
--- a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
@@ -78,24 +78,24 @@
 }
 
 void InternetHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       kAddThirdPartyVpnMessage,
       base::BindRepeating(&InternetHandler::AddThirdPartyVpn,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       kConfigureThirdPartyVpnMessage,
       base::BindRepeating(&InternetHandler::ConfigureThirdPartyVpn,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       kRequestGmsCoreNotificationsDisabledDeviceNames,
       base::BindRepeating(
           &InternetHandler::RequestGmsCoreNotificationsDisabledDeviceNames,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       kShowCarrierAccountDetail,
       base::BindRepeating(&InternetHandler::ShowCarrierAccountDetail,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       kShowCellularSetupUI,
       base::BindRepeating(&InternetHandler::ShowCellularSetupUI,
                           base::Unretained(this)));
@@ -109,13 +109,12 @@
   SetGmsCoreNotificationsDisabledDeviceNames();
 }
 
-void InternetHandler::AddThirdPartyVpn(const base::ListValue* args) {
-  if (args->GetListDeprecated().size() < 1 ||
-      !args->GetListDeprecated()[0].is_string()) {
+void InternetHandler::AddThirdPartyVpn(base::Value::ConstListView args) {
+  if (args.size() < 1 || !args[0].is_string()) {
     NOTREACHED() << "Invalid args for: " << kAddThirdPartyVpnMessage;
     return;
   }
-  const std::string& app_id = args->GetListDeprecated()[0].GetString();
+  const std::string& app_id = args[0].GetString();
   if (app_id.empty()) {
     NET_LOG(ERROR) << "Empty app id for " << kAddThirdPartyVpnMessage;
     return;
@@ -146,13 +145,12 @@
       ->SendShowAddDialogToExtension(app_id);
 }
 
-void InternetHandler::ConfigureThirdPartyVpn(const base::ListValue* args) {
-  if (args->GetListDeprecated().size() < 1 ||
-      !args->GetListDeprecated()[0].is_string()) {
+void InternetHandler::ConfigureThirdPartyVpn(base::Value::ConstListView args) {
+  if (args.size() < 1 || !args[0].is_string()) {
     NOTREACHED() << "Invalid args for: " << kConfigureThirdPartyVpnMessage;
     return;
   }
-  const std::string& guid = args->GetListDeprecated()[0].GetString();
+  const std::string& guid = args[0].GetString();
   if (profile_ != GetProfileForPrimaryUser()) {
     NET_LOG(ERROR) << "Only the primary user can configure VPNs";
     return;
@@ -202,28 +200,27 @@
 }
 
 void InternetHandler::RequestGmsCoreNotificationsDisabledDeviceNames(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   SetGmsCoreNotificationsDisabledDeviceNames();
 }
 
-void InternetHandler::ShowCarrierAccountDetail(const base::ListValue* args) {
-  if (args->GetListDeprecated().size() < 1 ||
-      !args->GetListDeprecated()[0].is_string()) {
+void InternetHandler::ShowCarrierAccountDetail(
+    base::Value::ConstListView args) {
+  if (args.size() < 1 || !args[0].is_string()) {
     NOTREACHED() << "Invalid args for: " << kShowCarrierAccountDetail;
     return;
   }
-  const std::string& guid = args->GetListDeprecated()[0].GetString();
+  const std::string& guid = args[0].GetString();
   chromeos::NetworkConnect::Get()->ShowCarrierAccountDetail(guid);
 }
 
-void InternetHandler::ShowCellularSetupUI(const base::ListValue* args) {
-  if (args->GetListDeprecated().size() < 1 ||
-      !args->GetListDeprecated()[0].is_string()) {
+void InternetHandler::ShowCellularSetupUI(base::Value::ConstListView args) {
+  if (args.size() < 1 || !args[0].is_string()) {
     NOTREACHED() << "Invalid args for: " << kConfigureThirdPartyVpnMessage;
     return;
   }
-  const std::string& guid = args->GetListDeprecated()[0].GetString();
+  const std::string& guid = args[0].GetString();
   chromeos::NetworkConnect::Get()->ShowMobileSetup(guid);
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_handler.h b/chrome/browser/ui/webui/settings/chromeos/internet_handler.h
index db4eb91..46d9e77 100644
--- a/chrome/browser/ui/webui/settings/chromeos/internet_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/internet_handler.h
@@ -41,12 +41,12 @@
   friend class InternetHandlerTest;
 
   // Settings JS handlers.
-  void AddThirdPartyVpn(const base::ListValue* args);
-  void ConfigureThirdPartyVpn(const base::ListValue* args);
+  void AddThirdPartyVpn(base::Value::ConstListView args);
+  void ConfigureThirdPartyVpn(base::Value::ConstListView args);
   void RequestGmsCoreNotificationsDisabledDeviceNames(
-      const base::ListValue* args);
-  void ShowCarrierAccountDetail(const base::ListValue* args);
-  void ShowCellularSetupUI(const base::ListValue* args);
+      base::Value::ConstListView args);
+  void ShowCarrierAccountDetail(base::Value::ConstListView args);
+  void ShowCellularSetupUI(base::Value::ConstListView args);
 
   // Sets list of names of devices whose "Google Play Services" notifications
   // are disabled.
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/internet_handler_unittest.cc
index 6c69ef6..83df3245 100644
--- a/chrome/browser/ui/webui/settings/chromeos/internet_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/internet_handler_unittest.cc
@@ -57,7 +57,8 @@
   }
 
   void RequestGmsCoreNotificationsDisabledDeviceNames() {
-    handler_->RequestGmsCoreNotificationsDisabledDeviceNames(nullptr);
+    handler_->RequestGmsCoreNotificationsDisabledDeviceNames(
+        base::Value::ConstListView());
   }
 
   void VerifyMostRecentDeviceNamesSent(
diff --git a/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc b/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc
index 817e32a7..8e84149 100644
--- a/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc
@@ -199,24 +199,24 @@
 }
 
 void KerberosAccountsHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getKerberosAccounts",
       base::BindRepeating(&KerberosAccountsHandler::HandleGetKerberosAccounts,
                           weak_factory_.GetWeakPtr()));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "addKerberosAccount",
       base::BindRepeating(&KerberosAccountsHandler::HandleAddKerberosAccount,
                           weak_factory_.GetWeakPtr()));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "removeKerberosAccount",
       base::BindRepeating(&KerberosAccountsHandler::HandleRemoveKerberosAccount,
                           weak_factory_.GetWeakPtr()));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "validateKerberosConfig",
       base::BindRepeating(
           &KerberosAccountsHandler::HandleValidateKerberosConfig,
           weak_factory_.GetWeakPtr()));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setAsActiveKerberosAccount",
       base::BindRepeating(
           &KerberosAccountsHandler::HandleSetAsActiveKerberosAccount,
@@ -224,11 +224,11 @@
 }
 
 void KerberosAccountsHandler::HandleGetKerberosAccounts(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   if (!kerberos_credentials_manager_->IsKerberosEnabled()) {
     ResolveJavascriptCallback(base::Value(callback_id), base::Value());
@@ -284,20 +284,20 @@
 }
 
 void KerberosAccountsHandler::HandleAddKerberosAccount(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
   // TODO(https://crbug.com/961246):
   //   - Prevent account changes when Kerberos is disabled.
   //   - Remove all accounts when Kerberos is disabled.
 
-  CHECK_EQ(6U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
-  const std::string& principal_name = args->GetListDeprecated()[1].GetString();
-  const std::string& password = args->GetListDeprecated()[2].GetString();
-  const bool remember_password = args->GetListDeprecated()[3].GetBool();
-  const std::string& config = args->GetListDeprecated()[4].GetString();
-  const bool allow_existing = args->GetListDeprecated()[5].GetBool();
+  CHECK_EQ(6U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  const std::string& principal_name = args[1].GetString();
+  const std::string& password = args[2].GetString();
+  const bool remember_password = args[3].GetBool();
+  const std::string& config = args[4].GetString();
+  const bool allow_existing = args[5].GetBool();
 
   if (!kerberos_credentials_manager_->IsKerberosEnabled()) {
     ResolveJavascriptCallback(base::Value(callback_id),
@@ -320,12 +320,12 @@
 }
 
 void KerberosAccountsHandler::HandleRemoveKerberosAccount(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
-  const std::string& principal_name = args->GetListDeprecated()[1].GetString();
+  CHECK_EQ(2U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  const std::string& principal_name = args[1].GetString();
 
   if (!kerberos_credentials_manager_->IsKerberosEnabled()) {
     ResolveJavascriptCallback(base::Value(callback_id),
@@ -345,12 +345,12 @@
 }
 
 void KerberosAccountsHandler::HandleValidateKerberosConfig(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
-  const std::string& krb5conf = args->GetListDeprecated()[1].GetString();
+  CHECK_EQ(2U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  const std::string& krb5conf = args[1].GetString();
 
   if (!kerberos_credentials_manager_->IsKerberosEnabled()) {
     ResolveJavascriptCallback(base::Value(callback_id),
@@ -380,11 +380,11 @@
 }
 
 void KerberosAccountsHandler::HandleSetAsActiveKerberosAccount(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& principal_name = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(1U, args.size());
+  const std::string& principal_name = args[0].GetString();
 
   kerberos_credentials_manager_->SetActiveAccount(principal_name);
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h b/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h
index 3b9839e..da103de7 100644
--- a/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h
@@ -58,31 +58,31 @@
       KerberosCredentialsManager* kerberos_credentials_manager);
 
   // WebUI "getKerberosAccounts" message callback.
-  void HandleGetKerberosAccounts(const base::ListValue* args);
+  void HandleGetKerberosAccounts(base::Value::ConstListView args);
 
   // WebUI "addKerberosAccount" message callback.
-  void HandleAddKerberosAccount(const base::ListValue* args);
+  void HandleAddKerberosAccount(base::Value::ConstListView args);
 
   // Callback for the credential manager's AddAccountAndAuthenticate method.
   void OnAddAccountAndAuthenticate(const std::string& callback_id,
                                    kerberos::ErrorType error);
 
   // WebUI "removeKerberosAccount" message callback.
-  void HandleRemoveKerberosAccount(const base::ListValue* args);
+  void HandleRemoveKerberosAccount(base::Value::ConstListView args);
 
   // Callback for the credential manager's RemoveAccount method.
   void OnRemoveAccount(const std::string& callback_id,
                        kerberos::ErrorType error);
 
   // WebUI "validateKerberosConfig" message callback.
-  void HandleValidateKerberosConfig(const base::ListValue* args);
+  void HandleValidateKerberosConfig(base::Value::ConstListView args);
 
   // Callback for the credential manager's ValidateConfig method.
   void OnValidateConfig(const std::string& callback_id,
                         const kerberos::ValidateConfigResponse& response);
 
   // WebUI "setAsActiveKerberosAccount" message callback.
-  void HandleSetAsActiveKerberosAccount(const base::ListValue* args);
+  void HandleSetAsActiveKerberosAccount(base::Value::ConstListView args);
 
   // Callback for the credential manager's ListAccounts method.
   void OnListAccounts(const std::string& callback_id,
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc
index 01b022b7..bbd32af 100644
--- a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc
@@ -97,59 +97,59 @@
 MultideviceHandler::~MultideviceHandler() {}
 
 void MultideviceHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showMultiDeviceSetupDialog",
       base::BindRepeating(&MultideviceHandler::HandleShowMultiDeviceSetupDialog,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getPageContentData",
       base::BindRepeating(&MultideviceHandler::HandleGetPageContent,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setFeatureEnabledState",
       base::BindRepeating(&MultideviceHandler::HandleSetFeatureEnabledState,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "removeHostDevice",
       base::BindRepeating(&MultideviceHandler::HandleRemoveHostDevice,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "retryPendingHostSetup",
       base::BindRepeating(&MultideviceHandler::HandleRetryPendingHostSetup,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setUpAndroidSms",
       base::BindRepeating(&MultideviceHandler::HandleSetUpAndroidSms,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getSmartLockSignInEnabled",
       base::BindRepeating(&MultideviceHandler::HandleGetSmartLockSignInEnabled,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setSmartLockSignInEnabled",
       base::BindRepeating(&MultideviceHandler::HandleSetSmartLockSignInEnabled,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getSmartLockSignInAllowed",
       base::BindRepeating(&MultideviceHandler::HandleGetSmartLockSignInAllowed,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getAndroidSmsInfo",
       base::BindRepeating(&MultideviceHandler::HandleGetAndroidSmsInfo,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "attemptNotificationSetup",
       base::BindRepeating(&MultideviceHandler::HandleAttemptNotificationSetup,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "cancelNotificationSetup",
       base::BindRepeating(&MultideviceHandler::HandleCancelNotificationSetup,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "attemptAppsSetup",
       base::BindRepeating(&MultideviceHandler::HandleAttemptAppsSetup,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "cancelAppsSetup",
       base::BindRepeating(&MultideviceHandler::HandleCancelAppsSetup,
                           base::Unretained(this)));
@@ -300,17 +300,17 @@
 }
 
 void MultideviceHandler::HandleShowMultiDeviceSetupDialog(
-    const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+    base::Value::ConstListView args) {
+  DCHECK(args.empty());
   multidevice_setup::MultiDeviceSetupDialog::Show();
 }
 
-void MultideviceHandler::HandleGetPageContent(const base::ListValue* args) {
+void MultideviceHandler::HandleGetPageContent(base::Value::ConstListView args) {
   // This callback is expected to be the first one executed when the page is
   // loaded, so it should be the one to allow JS calls.
   AllowJavascript();
 
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+  const base::Value& callback_id = args[0];
   DCHECK(callback_id.is_string());
 
   std::unique_ptr<base::DictionaryValue> page_content_dictionary =
@@ -323,8 +323,8 @@
 }
 
 void MultideviceHandler::HandleSetFeatureEnabledState(
-    const base::ListValue* args) {
-  const auto& list = args->GetListDeprecated();
+    base::Value::ConstListView args) {
+  const auto& list = args;
   DCHECK_GE(list.size(), 3u);
   std::string callback_id = list[0].GetString();
 
@@ -356,26 +356,28 @@
   }
 }
 
-void MultideviceHandler::HandleRemoveHostDevice(const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+void MultideviceHandler::HandleRemoveHostDevice(
+    base::Value::ConstListView args) {
+  DCHECK(args.empty());
   multidevice_setup_client_->RemoveHostDevice();
 }
 
 void MultideviceHandler::HandleRetryPendingHostSetup(
-    const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+    base::Value::ConstListView args) {
+  DCHECK(args.empty());
   multidevice_setup_client_->RetrySetHostNow(
       base::BindOnce(&OnRetrySetHostNowResult));
 }
 
-void MultideviceHandler::HandleSetUpAndroidSms(const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+void MultideviceHandler::HandleSetUpAndroidSms(
+    base::Value::ConstListView args) {
+  DCHECK(args.empty());
   android_sms_app_manager_->SetUpAndLaunchAndroidSmsApp();
 }
 
 void MultideviceHandler::HandleGetSmartLockSignInEnabled(
-    const base::ListValue* args) {
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+    base::Value::ConstListView args) {
+  const base::Value& callback_id = args[0];
   CHECK(callback_id.is_string());
 
   bool signInEnabled = prefs_->GetBoolean(
@@ -384,15 +386,13 @@
 }
 
 void MultideviceHandler::HandleSetSmartLockSignInEnabled(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   bool enabled = false;
-  if (args->GetListDeprecated()[0].is_bool())
-    enabled = args->GetListDeprecated()[0].GetBool();
+  if (args[0].is_bool())
+    enabled = args[0].GetBool();
 
-  const bool auth_token_present = args->GetListDeprecated().size() >= 2 &&
-                                  args->GetListDeprecated()[1].is_string();
-  const std::string& auth_token =
-      auth_token_present ? args->GetListDeprecated()[1].GetString() : "";
+  const bool auth_token_present = args.size() >= 2 && args[1].is_string();
+  const std::string& auth_token = auth_token_present ? args[1].GetString() : "";
 
   // Either the user is disabling sign-in, or they are enabling it and the auth
   // token must be present.
@@ -407,8 +407,8 @@
 }
 
 void MultideviceHandler::HandleGetSmartLockSignInAllowed(
-    const base::ListValue* args) {
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+    base::Value::ConstListView args) {
+  const base::Value& callback_id = args[0];
   CHECK(callback_id.is_string());
 
   bool sign_in_allowed =
@@ -442,14 +442,15 @@
   return android_sms_info;
 }
 
-void MultideviceHandler::HandleGetAndroidSmsInfo(const base::ListValue* args) {
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+void MultideviceHandler::HandleGetAndroidSmsInfo(
+    base::Value::ConstListView args) {
+  const base::Value& callback_id = args[0];
 
   ResolveJavascriptCallback(callback_id, *GenerateAndroidSmsInfo());
 }
 
 void MultideviceHandler::HandleAttemptNotificationSetup(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   DCHECK(features::IsPhoneHubEnabled());
   DCHECK(!notification_access_operation_);
 
@@ -468,14 +469,15 @@
 }
 
 void MultideviceHandler::HandleCancelNotificationSetup(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   DCHECK(features::IsPhoneHubEnabled());
   DCHECK(notification_access_operation_);
 
   notification_access_operation_.reset();
 }
 
-void MultideviceHandler::HandleAttemptAppsSetup(const base::ListValue* args) {
+void MultideviceHandler::HandleAttemptAppsSetup(
+    base::Value::ConstListView args) {
   DCHECK(features::IsEcheSWAEnabled());
   DCHECK(features::IsEchePhoneHubPermissionsOnboarding());
   DCHECK(!apps_access_operation_);
@@ -495,7 +497,8 @@
   DCHECK(apps_access_operation_);
 }
 
-void MultideviceHandler::HandleCancelAppsSetup(const base::ListValue* args) {
+void MultideviceHandler::HandleCancelAppsSetup(
+    base::Value::ConstListView args) {
   DCHECK(features::IsEcheSWAEnabled());
   DCHECK(features::IsEchePhoneHubPermissionsOnboarding());
   DCHECK(apps_access_operation_);
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h
index 8187dacf..6e109ff 100644
--- a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h
@@ -102,20 +102,20 @@
   // update (e.g., not due to a getPageContent() request).
   void UpdatePageContent();
 
-  void HandleShowMultiDeviceSetupDialog(const base::ListValue* args);
-  void HandleGetPageContent(const base::ListValue* args);
-  void HandleSetFeatureEnabledState(const base::ListValue* args);
-  void HandleRemoveHostDevice(const base::ListValue* args);
-  void HandleRetryPendingHostSetup(const base::ListValue* args);
-  void HandleSetUpAndroidSms(const base::ListValue* args);
-  void HandleGetSmartLockSignInEnabled(const base::ListValue* args);
-  void HandleSetSmartLockSignInEnabled(const base::ListValue* args);
-  void HandleGetSmartLockSignInAllowed(const base::ListValue* args);
-  void HandleGetAndroidSmsInfo(const base::ListValue* args);
-  void HandleAttemptNotificationSetup(const base::ListValue* args);
-  void HandleCancelNotificationSetup(const base::ListValue* args);
-  void HandleAttemptAppsSetup(const base::ListValue* args);
-  void HandleCancelAppsSetup(const base::ListValue* args);
+  void HandleShowMultiDeviceSetupDialog(base::Value::ConstListView args);
+  void HandleGetPageContent(base::Value::ConstListView args);
+  void HandleSetFeatureEnabledState(base::Value::ConstListView args);
+  void HandleRemoveHostDevice(base::Value::ConstListView args);
+  void HandleRetryPendingHostSetup(base::Value::ConstListView args);
+  void HandleSetUpAndroidSms(base::Value::ConstListView args);
+  void HandleGetSmartLockSignInEnabled(base::Value::ConstListView args);
+  void HandleSetSmartLockSignInEnabled(base::Value::ConstListView args);
+  void HandleGetSmartLockSignInAllowed(base::Value::ConstListView args);
+  void HandleGetAndroidSmsInfo(base::Value::ConstListView args);
+  void HandleAttemptNotificationSetup(base::Value::ConstListView args);
+  void HandleCancelNotificationSetup(base::Value::ConstListView args);
+  void HandleAttemptAppsSetup(base::Value::ConstListView args);
+  void HandleCancelAppsSetup(base::Value::ConstListView args);
 
   void OnSetFeatureStateEnabledResult(const std::string& js_callback_id,
                                       bool success);
diff --git a/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc b/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc
index 1ad2942..6301680 100644
--- a/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc
@@ -35,13 +35,13 @@
 ParentalControlsHandler::~ParentalControlsHandler() = default;
 
 void ParentalControlsHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showAddSupervisionDialog",
       base::BindRepeating(
           &ParentalControlsHandler::HandleShowAddSupervisionDialog,
           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "launchFamilyLinkSettings",
       base::BindRepeating(
           &ParentalControlsHandler::HandleLaunchFamilyLinkSettings,
@@ -52,14 +52,14 @@
 void ParentalControlsHandler::OnJavascriptDisallowed() {}
 
 void ParentalControlsHandler::HandleShowAddSupervisionDialog(
-    const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+    base::Value::ConstListView args) {
+  DCHECK(args.empty());
   AddSupervisionDialog::Show();
 }
 
 void ParentalControlsHandler::HandleLaunchFamilyLinkSettings(
-    const base::ListValue* args) {
-  DCHECK(args->GetListDeprecated().empty());
+    base::Value::ConstListView args) {
+  DCHECK(args.empty());
 
   apps::AppServiceProxy* proxy =
       apps::AppServiceProxyFactory::GetForProfile(profile_);
diff --git a/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.h b/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.h
index a013cf5..298ce79f 100644
--- a/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.h
@@ -32,8 +32,8 @@
   void OnJavascriptDisallowed() override;
 
   // Callbacks for handling chrome.send() events.
-  void HandleShowAddSupervisionDialog(const base::ListValue* args);
-  void HandleLaunchFamilyLinkSettings(const base::ListValue* args);
+  void HandleShowAddSupervisionDialog(base::Value::ConstListView args);
+  void HandleLaunchFamilyLinkSettings(base::Value::ConstListView args);
 
   Profile* profile_;
 };
diff --git a/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.cc b/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.cc
index a067e0b..e84167ad 100644
--- a/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.cc
@@ -73,13 +73,13 @@
 PeripheralDataAccessHandler::~PeripheralDataAccessHandler() = default;
 
 void PeripheralDataAccessHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "isThunderboltSupported",
       base::BindRepeating(
           &PeripheralDataAccessHandler::HandleThunderboltSupported,
           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getPolicyState",
       base::BindRepeating(&PeripheralDataAccessHandler::HandleGetPolicyState,
                           base::Unretained(this)));
@@ -90,10 +90,10 @@
 void PeripheralDataAccessHandler::OnJavascriptDisallowed() {}
 
 void PeripheralDataAccessHandler::HandleThunderboltSupported(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(1u, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(1u, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   // PathExist is a blocking call. PostTask it and wait on the result.
   base::ThreadPool::PostTaskAndReplyWithResult(
@@ -104,10 +104,10 @@
 }
 
 void PeripheralDataAccessHandler::HandleGetPolicyState(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(1u, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(1u, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   const std::string& pref_name = InstallAttributes::Get()->IsEnterpriseManaged()
                                      ? local_state_pref_name
diff --git a/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.h b/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.h
index 496e275..911dd724 100644
--- a/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.h
@@ -30,10 +30,10 @@
 
  private:
   // Handles checking if thunderbolt is supported in this device.
-  void HandleThunderboltSupported(const base::ListValue* args);
+  void HandleThunderboltSupported(base::Value::ConstListView args);
 
   // Handles returning the policy state.
-  void HandleGetPolicyState(const base::ListValue* args);
+  void HandleGetPolicyState(base::Value::ConstListView args);
 
   // Observer for the CrosSetting.
   void OnPeripheralDataAccessProtectionChanged();
diff --git a/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc b/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc
index ee43b71..b44c172 100644
--- a/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc
@@ -24,12 +24,12 @@
 PluginVmHandler::~PluginVmHandler() = default;
 
 void PluginVmHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "isRelaunchNeededForNewPermissions",
       base::BindRepeating(
           &PluginVmHandler::HandleIsRelaunchNeededForNewPermissions,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "relaunchPluginVm",
       base::BindRepeating(&PluginVmHandler::HandleRelaunchPluginVm,
                           base::Unretained(this)));
@@ -40,20 +40,20 @@
 void PluginVmHandler::OnJavascriptDisallowed() {}
 
 void PluginVmHandler::HandleIsRelaunchNeededForNewPermissions(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
+  CHECK_EQ(1U, args.size());
   bool requires_relaunch =
       plugin_vm::PluginVmManagerFactory::GetForProfile(profile_)
           ->IsRelaunchNeededForNewPermissions();
   ResolveJavascriptCallback(
-      /*callback_id=*/base::Value(args->GetListDeprecated()[0].GetString()),
+      /*callback_id=*/base::Value(args[0].GetString()),
       base::Value(requires_relaunch));
 }
 
-void PluginVmHandler::HandleRelaunchPluginVm(const base::ListValue* args) {
-  CHECK_EQ(0U, args->GetListDeprecated().size());
+void PluginVmHandler::HandleRelaunchPluginVm(base::Value::ConstListView args) {
+  CHECK_EQ(0U, args.size());
   plugin_vm::PluginVmManagerFactory::GetForProfile(profile_)
       ->RelaunchPluginVm();
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h b/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h
index 93ae19c..9411a572 100644
--- a/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h
@@ -30,9 +30,9 @@
  private:
   // Checks if Plugin VM would need to be relaunched if the proposed changes are
   // made.
-  void HandleIsRelaunchNeededForNewPermissions(const base::ListValue* args);
+  void HandleIsRelaunchNeededForNewPermissions(base::Value::ConstListView args);
   // Relaunches Plugin VM.
-  void HandleRelaunchPluginVm(const base::ListValue* args);
+  void HandleRelaunchPluginVm(base::Value::ConstListView args);
 
   Profile* profile_;
   // weak_ptr_factory_ should always be last member.
diff --git a/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc b/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc
index a0734d31..8ff04565 100644
--- a/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc
@@ -22,11 +22,11 @@
 QuickUnlockHandler::~QuickUnlockHandler() = default;
 
 void QuickUnlockHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "RequestPinLoginState",
       base::BindRepeating(&QuickUnlockHandler::HandleRequestPinLoginState,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "RequestQuickUnlockDisabledByPolicy",
       base::BindRepeating(
           &QuickUnlockHandler::HandleQuickUnlockDisabledByPolicy,
@@ -47,7 +47,7 @@
 }
 
 void QuickUnlockHandler::HandleRequestPinLoginState(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   quick_unlock::PinBackend::GetInstance()->HasLoginSupport(
       base::BindOnce(&QuickUnlockHandler::OnPinLoginAvailable,
@@ -55,9 +55,9 @@
 }
 
 void QuickUnlockHandler::HandleQuickUnlockDisabledByPolicy(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(0U, args->GetListDeprecated().size());
+  CHECK_EQ(0U, args.size());
 
   UpdateQuickUnlockDisabledByPolicy();
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h b/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h
index cc92e82..2b87d94d 100644
--- a/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h
@@ -12,10 +12,6 @@
 class PrefService;
 class Profile;
 
-namespace base {
-class ListValue;
-}  // namespace base
-
 namespace chromeos {
 namespace settings {
 
@@ -33,10 +29,10 @@
   void OnJavascriptDisallowed() override;
 
  private:
-  void HandleRequestPinLoginState(const base::ListValue* args);
+  void HandleRequestPinLoginState(base::Value::ConstListView args);
   void OnPinLoginAvailable(bool is_available);
 
-  void HandleQuickUnlockDisabledByPolicy(const base::ListValue* args);
+  void HandleQuickUnlockDisabledByPolicy(base::Value::ConstListView args);
   void UpdateQuickUnlockDisabledByPolicy();
 
   Profile* profile_;
diff --git a/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc b/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc
index ce57dee..581cf03 100644
--- a/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc
@@ -86,18 +86,18 @@
 }
 
 void SwitchAccessHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "refreshAssignmentsFromPrefs",
       base::BindRepeating(
           &SwitchAccessHandler::HandleRefreshAssignmentsFromPrefs,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "notifySwitchAccessActionAssignmentPaneActive",
       base::BindRepeating(
           &SwitchAccessHandler::
               HandleNotifySwitchAccessActionAssignmentPaneActive,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "notifySwitchAccessActionAssignmentPaneInactive",
       base::BindRepeating(
           &SwitchAccessHandler::
@@ -155,13 +155,13 @@
 }
 
 void SwitchAccessHandler::HandleRefreshAssignmentsFromPrefs(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   OnSwitchAccessAssignmentsUpdated();
 }
 
 void SwitchAccessHandler::HandleNotifySwitchAccessActionAssignmentPaneActive(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   OnSwitchAccessAssignmentsUpdated();
   web_ui()->GetWebContents()->GetNativeView()->AddPreTargetHandler(this);
@@ -169,7 +169,7 @@
 }
 
 void SwitchAccessHandler::HandleNotifySwitchAccessActionAssignmentPaneInactive(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   web_ui()->GetWebContents()->GetNativeView()->RemovePreTargetHandler(this);
   ash::AccessibilityController::Get()->SuspendSwitchAccessKeyHandling(false);
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.h b/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.h
index bcb4943..6a973fc 100644
--- a/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.h
@@ -9,10 +9,6 @@
 #include "components/prefs/pref_change_registrar.h"
 #include "ui/events/event_handler.h"
 
-namespace base {
-class ListValue;
-}
-
 class PrefService;
 
 namespace chromeos {
@@ -35,11 +31,11 @@
   void OnKeyEvent(ui::KeyEvent* event) override;
 
  private:
-  void HandleRefreshAssignmentsFromPrefs(const base::ListValue* args);
+  void HandleRefreshAssignmentsFromPrefs(base::Value::ConstListView args);
   void HandleNotifySwitchAccessActionAssignmentPaneActive(
-      const base::ListValue* args);
+      base::Value::ConstListView args);
   void HandleNotifySwitchAccessActionAssignmentPaneInactive(
-      const base::ListValue* args);
+      base::Value::ConstListView args);
   void OnSwitchAccessAssignmentsUpdated();
 
   std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
diff --git a/chrome/browser/ui/webui/settings/chromeos/tts_handler.cc b/chrome/browser/ui/webui/settings/chromeos/tts_handler.cc
index 30fc43f..9fd92d6 100644
--- a/chrome/browser/ui/webui/settings/chromeos/tts_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/tts_handler.cc
@@ -31,13 +31,13 @@
   RemoveTtsControllerDelegates();
 }
 
-void TtsHandler::HandleGetAllTtsVoiceData(const base::ListValue* args) {
+void TtsHandler::HandleGetAllTtsVoiceData(base::Value::ConstListView args) {
   OnVoicesChanged();
 }
 
-void TtsHandler::HandleGetTtsExtensions(const base::ListValue* args) {
+void TtsHandler::HandleGetTtsExtensions(base::Value::ConstListView args) {
   // Ensure the built in tts engine is loaded to be able to respond to messages.
-  WakeTtsEngine(nullptr);
+  WakeTtsEngine(base::Value::ConstListView());
 
   base::ListValue responses;
   Profile* profile = Profile::FromWebUI(web_ui());
@@ -107,7 +107,7 @@
   FireWebUIListener("all-voice-data-updated", responses);
 
   // Also refresh the TTS extensions in case they have changed.
-  HandleGetTtsExtensions(nullptr);
+  HandleGetTtsExtensions(base::Value::ConstListView());
 }
 
 void TtsHandler::OnTtsEvent(content::TtsUtterance* utterance,
@@ -123,10 +123,10 @@
   }
 }
 
-void TtsHandler::HandlePreviewTtsVoice(const base::ListValue* args) {
-  DCHECK_EQ(2U, args->GetListDeprecated().size());
-  const std::string& text = args->GetListDeprecated()[0].GetString();
-  const std::string& voice_id = args->GetListDeprecated()[1].GetString();
+void TtsHandler::HandlePreviewTtsVoice(base::Value::ConstListView args) {
+  DCHECK_EQ(2U, args.size());
+  const std::string& text = args[0].GetString();
+  const std::string& voice_id = args[1].GetString();
 
   if (text.empty() || voice_id.empty())
     return;
@@ -154,18 +154,18 @@
 }
 
 void TtsHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getAllTtsVoiceData",
       base::BindRepeating(&TtsHandler::HandleGetAllTtsVoiceData,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getTtsExtensions",
       base::BindRepeating(&TtsHandler::HandleGetTtsExtensions,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "previewTtsVoice", base::BindRepeating(&TtsHandler::HandlePreviewTtsVoice,
                                              base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "wakeTtsEngine",
       base::BindRepeating(&TtsHandler::WakeTtsEngine, base::Unretained(this)));
 }
@@ -190,7 +190,7 @@
              : 0;
 }
 
-void TtsHandler::WakeTtsEngine(const base::ListValue* args) {
+void TtsHandler::WakeTtsEngine(base::Value::ConstListView args) {
   Profile* profile = Profile::FromWebUI(web_ui());
   TtsExtensionEngine::GetInstance()->LoadBuiltInTtsEngine(profile);
   extensions::ProcessManager::Get(profile)->WakeEventPage(
diff --git a/chrome/browser/ui/webui/settings/chromeos/tts_handler.h b/chrome/browser/ui/webui/settings/chromeos/tts_handler.h
index 2ec989d..e1fd16d8 100644
--- a/chrome/browser/ui/webui/settings/chromeos/tts_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/tts_handler.h
@@ -23,9 +23,9 @@
 
   ~TtsHandler() override;
 
-  void HandleGetAllTtsVoiceData(const base::ListValue* args);
-  void HandleGetTtsExtensions(const base::ListValue* args);
-  void HandlePreviewTtsVoice(const base::ListValue* args);
+  void HandleGetAllTtsVoiceData(base::Value::ConstListView args);
+  void HandleGetTtsExtensions(base::Value::ConstListView args);
+  void HandlePreviewTtsVoice(base::Value::ConstListView args);
 
   // SettingsPageUIHandler implementation.
   void RegisterMessages() override;
@@ -43,7 +43,7 @@
                   const std::string& error_message) override;
 
  private:
-  void WakeTtsEngine(const base::ListValue* args);
+  void WakeTtsEngine(base::Value::ConstListView args);
   void OnTtsEngineAwake(bool success);
   int GetVoiceLangMatchScore(const content::VoiceData* voice,
                              const std::string& app_locale);
diff --git a/chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.cc b/chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.cc
index e8e09c7a..199fef4 100644
--- a/chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.cc
@@ -19,39 +19,40 @@
 void WallpaperHandler::OnJavascriptDisallowed() {}
 
 void WallpaperHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "openWallpaperManager",
       base::BindRepeating(&WallpaperHandler::HandleOpenWallpaperManager,
                           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "isWallpaperSettingVisible",
       base::BindRepeating(&WallpaperHandler::HandleIsWallpaperSettingVisible,
                           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "isWallpaperPolicyControlled",
       base::BindRepeating(&WallpaperHandler::HandleIsWallpaperPolicyControlled,
                           base::Unretained(this)));
 }
 
 void WallpaperHandler::HandleIsWallpaperSettingVisible(
-    const base::ListValue* args) {
-  CHECK_EQ(args->GetListDeprecated().size(), 1U);
+    base::Value::ConstListView args) {
+  CHECK_EQ(args.size(), 1U);
   ResolveCallback(
-      args->GetListDeprecated()[0],
+      args[0],
       WallpaperControllerClientImpl::Get()->ShouldShowWallpaperSetting());
 }
 
 void WallpaperHandler::HandleIsWallpaperPolicyControlled(
-    const base::ListValue* args) {
-  CHECK_EQ(args->GetListDeprecated().size(), 1U);
+    base::Value::ConstListView args) {
+  CHECK_EQ(args.size(), 1U);
   bool result = WallpaperControllerClientImpl::Get()
                     ->IsActiveUserWallpaperControlledByPolicy();
-  ResolveCallback(args->GetListDeprecated()[0], result);
+  ResolveCallback(args[0], result);
 }
 
-void WallpaperHandler::HandleOpenWallpaperManager(const base::ListValue* args) {
+void WallpaperHandler::HandleOpenWallpaperManager(
+    base::Value::ConstListView args) {
   WallpaperControllerClientImpl::Get()->OpenWallpaperPickerIfAllowed();
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.h b/chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.h
index be20cd5d..94f54f03 100644
--- a/chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.h
@@ -7,10 +7,6 @@
 
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 
-namespace base {
-class ListValue;
-}  // namespace base
-
 namespace chromeos {
 namespace settings {
 
@@ -31,13 +27,13 @@
 
  private:
   // Whether the wallpaper setting should be shown.
-  void HandleIsWallpaperSettingVisible(const base::ListValue* args);
+  void HandleIsWallpaperSettingVisible(base::Value::ConstListView args);
 
   // Whether the wallpaper is policy controlled.
-  void HandleIsWallpaperPolicyControlled(const base::ListValue* args);
+  void HandleIsWallpaperPolicyControlled(base::Value::ConstListView args);
 
   // Open the wallpaper manager app.
-  void HandleOpenWallpaperManager(const base::ListValue* args);
+  void HandleOpenWallpaperManager(base::Value::ConstListView args);
 
   // Helper function to resolve the Javascript callback.
   void ResolveCallback(const base::Value& callback_id, bool result);
diff --git a/chrome/browser/ui/webui/settings/downloads_handler.cc b/chrome/browser/ui/webui/settings/downloads_handler.cc
index d11915fc..c36c212 100644
--- a/chrome/browser/ui/webui/settings/downloads_handler.cc
+++ b/chrome/browser/ui/webui/settings/downloads_handler.cc
@@ -42,26 +42,26 @@
 }
 
 void DownloadsHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "initializeDownloads",
       base::BindRepeating(&DownloadsHandler::HandleInitialize,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "resetAutoOpenFileTypes",
       base::BindRepeating(&DownloadsHandler::HandleResetAutoOpenFileTypes,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "selectDownloadLocation",
       base::BindRepeating(&DownloadsHandler::HandleSelectDownloadLocation,
                           base::Unretained(this)));
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getDownloadLocationText",
       base::BindRepeating(&DownloadsHandler::HandleGetDownloadLocationText,
                           base::Unretained(this)));
 #endif
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setDownloadsConnectionAccountLink",
       base::BindRepeating(
           &DownloadsHandler::HandleSetDownloadsConnectionAccountLink,
@@ -85,7 +85,7 @@
   pref_registrar_.RemoveAll();
 }
 
-void DownloadsHandler::HandleInitialize(const base::ListValue* args) {
+void DownloadsHandler::HandleInitialize(base::Value::ConstListView args) {
   AllowJavascript();
   SendDownloadsConnectionPolicyToJavascript();
   SendAutoOpenDownloadsToJavascript();
@@ -100,14 +100,14 @@
 }
 
 void DownloadsHandler::HandleResetAutoOpenFileTypes(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   base::RecordAction(UserMetricsAction("Options_ResetAutoOpenFiles"));
   content::DownloadManager* manager = profile_->GetDownloadManager();
   DownloadPrefs::FromDownloadManager(manager)->ResetAutoOpenByUser();
 }
 
 void DownloadsHandler::HandleSelectDownloadLocation(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   // Early return if the select folder dialog is already active.
   if (select_folder_dialog_)
     return;
@@ -143,11 +143,11 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 void DownloadsHandler::HandleGetDownloadLocationText(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
-  const std::string& path = args->GetListDeprecated()[1].GetString();
+  CHECK_EQ(2U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  const std::string& path = args[1].GetString();
 
   ResolveJavascriptCallback(
       base::Value(callback_id),
@@ -183,10 +183,10 @@
 }
 
 void DownloadsHandler::HandleSetDownloadsConnectionAccountLink(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   DCHECK(IsDownloadsConnectionPolicyEnabled());
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  bool enable_link = args->GetListDeprecated()[0].GetBool();
+  CHECK_EQ(1U, args.size());
+  bool enable_link = args[0].GetBool();
   ec::SetFileSystemConnectorAccountLinkForSettingsPage(
       enable_link, profile_,
       base::BindOnce(&DownloadsHandler::OnDownloadsConnectionAccountLinkSet,
diff --git a/chrome/browser/ui/webui/settings/downloads_handler.h b/chrome/browser/ui/webui/settings/downloads_handler.h
index 7d6014da..2f98eb8 100644
--- a/chrome/browser/ui/webui/settings/downloads_handler.h
+++ b/chrome/browser/ui/webui/settings/downloads_handler.h
@@ -38,16 +38,16 @@
 
   // Callback for the "initializeDownloads" message. This starts observers and
   // retrieves the current browser state.
-  void HandleInitialize(const base::ListValue* args);
+  void HandleInitialize(base::Value::ConstListView args);
 
   void SendAutoOpenDownloadsToJavascript();
 
   // Resets the list of filetypes that are auto-opened after download.
-  void HandleResetAutoOpenFileTypes(const base::ListValue* args);
+  void HandleResetAutoOpenFileTypes(base::Value::ConstListView args);
 
   // Callback for the "selectDownloadLocation" message. This will prompt the
   // user for a destination folder using platform-specific APIs.
-  void HandleSelectDownloadLocation(const base::ListValue* args);
+  void HandleSelectDownloadLocation(base::Value::ConstListView args);
 
   // SelectFileDialog::Listener implementation.
   void FileSelected(const base::FilePath& path,
@@ -59,7 +59,7 @@
   // Callback for the "getDownloadLocationText" message.  Converts actual
   // paths in chromeos to values suitable to display to users.
   // E.g. /home/chronos/u-<hash>/Downloads => "Downloads".
-  void HandleGetDownloadLocationText(const base::ListValue* args);
+  void HandleGetDownloadLocationText(base::Value::ConstListView args);
 #endif
 
   bool IsDownloadsConnectionPolicyEnabled() const;
@@ -70,7 +70,7 @@
   // there is an existing linked account and arg is false, this removes the
   // linked account info and stored authentication tokens; otherwise, this
   // merely sends the latest stored account info.
-  void HandleSetDownloadsConnectionAccountLink(const base::ListValue* args);
+  void HandleSetDownloadsConnectionAccountLink(base::Value::ConstListView args);
   // Callback for file system connector code, since prompting the user to sign
   // in is async.
   void OnDownloadsConnectionAccountLinkSet(bool success);
diff --git a/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc b/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc
index fbc2f9f..1336ca7 100644
--- a/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc
@@ -168,7 +168,7 @@
     expected_init_callback_count += param.connection_init_enabled;
 
     base::ListValue args;
-    handler()->HandleInitialize(&args);
+    handler()->HandleInitialize(args.GetListDeprecated());
 
     EXPECT_TRUE(handler()->IsJavascriptAllowed());
     ASSERT_EQ(web_ui_call_data().size(), expected_init_callback_count);
diff --git a/chrome/browser/ui/webui/settings/extension_control_handler.cc b/chrome/browser/ui/webui/settings/extension_control_handler.cc
index 4c99bc5..c0fde8e 100644
--- a/chrome/browser/ui/webui/settings/extension_control_handler.cc
+++ b/chrome/browser/ui/webui/settings/extension_control_handler.cc
@@ -19,15 +19,15 @@
 ExtensionControlHandler::~ExtensionControlHandler() {}
 
 void ExtensionControlHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "disableExtension",
       base::BindRepeating(&ExtensionControlHandler::HandleDisableExtension,
                           base::Unretained(this)));
 }
 
 void ExtensionControlHandler::HandleDisableExtension(
-    const base::ListValue* args) {
-  const std::string& extension_id = args->GetListDeprecated()[0].GetString();
+    base::Value::ConstListView args) {
+  const std::string& extension_id = args[0].GetString();
   extensions::ExtensionService* extension_service =
       extensions::ExtensionSystem::Get(Profile::FromWebUI(web_ui()))
           ->extension_service();
diff --git a/chrome/browser/ui/webui/settings/extension_control_handler.h b/chrome/browser/ui/webui/settings/extension_control_handler.h
index 1f61ec7..0a8a888 100644
--- a/chrome/browser/ui/webui/settings/extension_control_handler.h
+++ b/chrome/browser/ui/webui/settings/extension_control_handler.h
@@ -7,10 +7,6 @@
 
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace settings {
 
 class ExtensionControlHandler : public SettingsPageUIHandler {
@@ -30,7 +26,7 @@
  private:
   // Handler for the "disableExtension" message. Extension ID is passed as the
   // single string argument.
-  void HandleDisableExtension(const base::ListValue* args);
+  void HandleDisableExtension(base::Value::ConstListView args);
 };
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/font_handler.cc b/chrome/browser/ui/webui/settings/font_handler.cc
index 953e1c23..1bde43b9 100644
--- a/chrome/browser/ui/webui/settings/font_handler.cc
+++ b/chrome/browser/ui/webui/settings/font_handler.cc
@@ -38,7 +38,7 @@
 FontHandler::~FontHandler() {}
 
 void FontHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "fetchFontsData", base::BindRepeating(&FontHandler::HandleFetchFontsData,
                                             base::Unretained(this)));
 }
@@ -47,9 +47,9 @@
 
 void FontHandler::OnJavascriptDisallowed() {}
 
-void FontHandler::HandleFetchFontsData(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+void FontHandler::HandleFetchFontsData(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   AllowJavascript();
   content::GetFontListAsync(base::BindOnce(&FontHandler::FontListHasLoaded,
diff --git a/chrome/browser/ui/webui/settings/font_handler.h b/chrome/browser/ui/webui/settings/font_handler.h
index f80c7d1..3d30449 100644
--- a/chrome/browser/ui/webui/settings/font_handler.h
+++ b/chrome/browser/ui/webui/settings/font_handler.h
@@ -13,10 +13,6 @@
 
 class Profile;
 
-namespace base {
-class ListValue;
-}  // namespace base
-
 namespace settings {
 
 // Handle OS font list and font preference settings.
@@ -36,7 +32,7 @@
 
  private:
   // Handler for script asking for font information.
-  void HandleFetchFontsData(const base::ListValue* args);
+  void HandleFetchFontsData(base::Value::ConstListView args);
 
   // Callback to handle fonts loading.
   void FontListHasLoaded(std::string callback_id,
diff --git a/chrome/browser/ui/webui/settings/hats_handler.cc b/chrome/browser/ui/webui/settings/hats_handler.cc
index 47b1987..3d0887d9 100644
--- a/chrome/browser/ui/webui/settings/hats_handler.cc
+++ b/chrome/browser/ui/webui/settings/hats_handler.cc
@@ -48,19 +48,18 @@
 HatsHandler::~HatsHandler() = default;
 
 void HatsHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "trustSafetyInteractionOccurred",
       base::BindRepeating(&HatsHandler::HandleTrustSafetyInteractionOccurred,
                           base::Unretained(this)));
 }
 
 void HatsHandler::HandleTrustSafetyInteractionOccurred(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  auto interaction = static_cast<TrustSafetyInteraction>(
-      args->GetListDeprecated()[0].GetInt());
+  CHECK_EQ(1U, args.size());
+  auto interaction = static_cast<TrustSafetyInteraction>(args[0].GetInt());
 
   // Both the HaTS service, and the T&S sentiment service (which is another
   // wrapper on the HaTS service), may decide to launch surveys based on this
diff --git a/chrome/browser/ui/webui/settings/hats_handler.h b/chrome/browser/ui/webui/settings/hats_handler.h
index ec8688e..f0f54c4 100644
--- a/chrome/browser/ui/webui/settings/hats_handler.h
+++ b/chrome/browser/ui/webui/settings/hats_handler.h
@@ -24,7 +24,7 @@
   // WebUIMessageHandler implementation.
   void RegisterMessages() override;
 
-  void HandleTrustSafetyInteractionOccurred(const base::ListValue* args);
+  void HandleTrustSafetyInteractionOccurred(base::Value::ConstListView args);
 
  private:
   friend class HatsHandlerTest;
diff --git a/chrome/browser/ui/webui/settings/hats_handler_unittest.cc b/chrome/browser/ui/webui/settings/hats_handler_unittest.cc
index c731bfaa..d3d38c00 100644
--- a/chrome/browser/ui/webui/settings/hats_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/hats_handler_unittest.cc
@@ -112,14 +112,12 @@
   base::Value args(base::Value::Type::LIST);
   args.Append(
       static_cast<int>(HatsHandler::TrustSafetyInteraction::USED_PRIVACY_CARD));
-  handler()->HandleTrustSafetyInteractionOccurred(
-      &base::Value::AsListValue(args));
+  handler()->HandleTrustSafetyInteractionOccurred(args.GetListDeprecated());
   task_environment()->RunUntilIdle();
 
   args.GetListDeprecated()[0] = base::Value(
       static_cast<int>(HatsHandler::TrustSafetyInteraction::RAN_SAFETY_CHECK));
-  handler()->HandleTrustSafetyInteractionOccurred(
-      &base::Value::AsListValue(args));
+  handler()->HandleTrustSafetyInteractionOccurred(args.GetListDeprecated());
   task_environment()->RunUntilIdle();
 }
 
@@ -132,8 +130,7 @@
   base::Value args(base::Value::Type::LIST);
   args.Append(static_cast<int>(
       HatsHandler::TrustSafetyInteraction::COMPLETED_PRIVACY_GUIDE));
-  handler()->HandleTrustSafetyInteractionOccurred(
-      &base::Value::AsListValue(args));
+  handler()->HandleTrustSafetyInteractionOccurred(args.GetListDeprecated());
   task_environment()->RunUntilIdle();
 }
 
@@ -167,8 +164,7 @@
   base::Value args(base::Value::Type::LIST);
   args.Append(
       static_cast<int>(HatsHandler::TrustSafetyInteraction::USED_PRIVACY_CARD));
-  handler()->HandleTrustSafetyInteractionOccurred(
-      &base::Value::AsListValue(args));
+  handler()->HandleTrustSafetyInteractionOccurred(args.GetListDeprecated());
   task_environment()->RunUntilIdle();
 }
 
@@ -189,8 +185,7 @@
   base::Value args(base::Value::Type::LIST);
   args.Append(static_cast<int>(
       HatsHandler::TrustSafetyInteraction::OPENED_PRIVACY_SANDBOX));
-  handler()->HandleTrustSafetyInteractionOccurred(
-      &base::Value::AsListValue(args));
+  handler()->HandleTrustSafetyInteractionOccurred(args.GetListDeprecated());
   task_environment()->RunUntilIdle();
 }
 
@@ -203,14 +198,12 @@
   base::Value args(base::Value::Type::LIST);
   args.Append(
       static_cast<int>(HatsHandler::TrustSafetyInteraction::USED_PRIVACY_CARD));
-  handler()->HandleTrustSafetyInteractionOccurred(
-      &base::Value::AsListValue(args));
+  handler()->HandleTrustSafetyInteractionOccurred(args.GetListDeprecated());
 
   EXPECT_CALL(*mock_sentiment_service_, RanSafetyCheck()).Times(1);
   args.GetListDeprecated()[0] = base::Value(
       static_cast<int>(HatsHandler::TrustSafetyInteraction::RAN_SAFETY_CHECK));
-  handler()->HandleTrustSafetyInteractionOccurred(
-      &base::Value::AsListValue(args));
+  handler()->HandleTrustSafetyInteractionOccurred(args.GetListDeprecated());
 }
 
 TEST_F(HatsHandlerNoSandboxTest, TrustSafetySentimentInteractions) {
@@ -224,14 +217,12 @@
   args.Append(
       static_cast<int>(HatsHandler::TrustSafetyInteraction::RAN_SAFETY_CHECK));
   profile()->GetPrefs()->SetBoolean(prefs::kPrivacySandboxPageViewed, true);
-  handler()->HandleTrustSafetyInteractionOccurred(
-      &base::Value::AsListValue(args));
+  handler()->HandleTrustSafetyInteractionOccurred(args.GetListDeprecated());
 
   EXPECT_CALL(*mock_sentiment_service_, OpenedPasswordManager(web_contents()));
   args.GetListDeprecated()[0] = base::Value(static_cast<int>(
       HatsHandler::TrustSafetyInteraction::OPENED_PASSWORD_MANAGER));
-  handler()->HandleTrustSafetyInteractionOccurred(
-      &base::Value::AsListValue(args));
+  handler()->HandleTrustSafetyInteractionOccurred(args.GetListDeprecated());
 }
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/import_data_handler.cc b/chrome/browser/ui/webui/settings/import_data_handler.cc
index b5e64571..7ddbe3ce 100644
--- a/chrome/browser/ui/webui/settings/import_data_handler.cc
+++ b/chrome/browser/ui/webui/settings/import_data_handler.cc
@@ -55,14 +55,14 @@
 void ImportDataHandler::RegisterMessages() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "initializeImportDialog",
       base::BindRepeating(&ImportDataHandler::HandleInitializeImportDialog,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "importData", base::BindRepeating(&ImportDataHandler::HandleImportData,
                                         base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "importFromBookmarksFile",
       base::BindRepeating(&ImportDataHandler::HandleImportFromBookmarksFile,
                           base::Unretained(this)));
@@ -103,9 +103,9 @@
                                     source_profile.importer_type);
 }
 
-void ImportDataHandler::HandleImportData(const base::ListValue* args) {
+void ImportDataHandler::HandleImportData(base::Value::ConstListView args) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  const auto& list = args->GetListDeprecated();
+  const auto& list = args;
   CHECK_GE(list.size(), 2u);
 
   int browser_index = list[0].GetInt();
@@ -145,11 +145,11 @@
 }
 
 void ImportDataHandler::HandleInitializeImportDialog(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   importer_list_ = std::make_unique<ImporterList>();
   importer_list_->DetectSourceProfiles(
@@ -160,13 +160,13 @@
 }
 
 void ImportDataHandler::HandleImportFromBookmarksFile(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (select_file_dialog_)
     return;
 
-  DCHECK(args && args->GetListDeprecated().empty());
+  DCHECK(args.empty());
   select_file_dialog_ = ui::SelectFileDialog::Create(
       this,
       std::make_unique<ChromeSelectFilePolicy>(web_ui()->GetWebContents()));
diff --git a/chrome/browser/ui/webui/settings/import_data_handler.h b/chrome/browser/ui/webui/settings/import_data_handler.h
index 8f1fc60d..445e400 100644
--- a/chrome/browser/ui/webui/settings/import_data_handler.h
+++ b/chrome/browser/ui/webui/settings/import_data_handler.h
@@ -43,15 +43,15 @@
 
   // Handler for the "importData" message. First argument is the selected
   // browser index, and second argument is the types of data to import.
-  void HandleImportData(const base::ListValue* args);
+  void HandleImportData(base::Value::ConstListView args);
 
   // Handler for the "initializeImportDialog" message. First argument is a
   // callback id.
-  void HandleInitializeImportDialog(const base::ListValue* args);
+  void HandleInitializeImportDialog(base::Value::ConstListView args);
 
   // Handler for the "importFromBookmarksFile" message. Opens a file selection
   // dialog to choose the bookmarks HTML file.
-  void HandleImportFromBookmarksFile(const base::ListValue* args);
+  void HandleImportFromBookmarksFile(base::Value::ConstListView args);
 
   void SendBrowserProfileData(const std::string& callback_id);
 
diff --git a/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.cc b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.cc
index f9f9a4d3..67e2838 100644
--- a/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.cc
+++ b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.cc
@@ -28,27 +28,27 @@
 IncompatibleApplicationsHandler::~IncompatibleApplicationsHandler() = default;
 
 void IncompatibleApplicationsHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "requestIncompatibleApplicationsList",
       base::BindRepeating(&IncompatibleApplicationsHandler::
                               HandleRequestIncompatibleApplicationsList,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "startApplicationUninstallation",
       base::BindRepeating(&IncompatibleApplicationsHandler::
                               HandleStartApplicationUninstallation,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getSubtitlePluralString",
       base::BindRepeating(
           &IncompatibleApplicationsHandler::HandleGetSubtitlePluralString,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getSubtitleNoAdminRightsPluralString",
       base::BindRepeating(&IncompatibleApplicationsHandler::
                               HandleGetSubtitleNoAdminRightsPluralString,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getListTitlePluralString",
       base::BindRepeating(
           &IncompatibleApplicationsHandler::HandleGetListTitlePluralString,
@@ -62,8 +62,8 @@
 }
 
 void IncompatibleApplicationsHandler::HandleRequestIncompatibleApplicationsList(
-    const base::ListValue* args) {
-  CHECK_EQ(1u, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  CHECK_EQ(1u, args.size());
 
   AllowJavascript();
 
@@ -111,46 +111,47 @@
   UMA_HISTOGRAM_COUNTS_100("IncompatibleApplicationsPage.NumApplications",
                            incompatible_applications.size());
 
-  const base::Value& callback_id = args->GetListDeprecated().front();
+  const base::Value& callback_id = args.front();
   ResolveJavascriptCallback(callback_id, application_list);
 }
 
 void IncompatibleApplicationsHandler::HandleStartApplicationUninstallation(
-    const base::ListValue* args) {
-  CHECK_EQ(1u, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  CHECK_EQ(1u, args.size());
   base::RecordAction(base::UserMetricsAction(
       "IncompatibleApplicationsPage.UninstallationStarted"));
 
   // Open the Apps & Settings page with the application name highlighted.
   uninstall_application::LaunchUninstallFlow(
-      base::UTF8ToWide(args->GetListDeprecated()[0].GetString()));
+      base::UTF8ToWide(args[0].GetString()));
 }
 
 void IncompatibleApplicationsHandler::HandleGetSubtitlePluralString(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   GetPluralString(IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_SUBPAGE_SUBTITLE,
                   args);
 }
 
 void IncompatibleApplicationsHandler::
-    HandleGetSubtitleNoAdminRightsPluralString(const base::ListValue* args) {
+    HandleGetSubtitleNoAdminRightsPluralString(
+        base::Value::ConstListView args) {
   GetPluralString(
       IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_SUBPAGE_SUBTITLE_NO_ADMIN_RIGHTS,
       args);
 }
 
 void IncompatibleApplicationsHandler::HandleGetListTitlePluralString(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   GetPluralString(IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_LIST_TITLE, args);
 }
 
 void IncompatibleApplicationsHandler::GetPluralString(
     int id,
-    const base::ListValue* args) {
-  CHECK_EQ(2U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  CHECK_EQ(2U, args.size());
 
-  const base::Value& callback_id = args->GetListDeprecated()[0];
-  int num_applications = args->GetListDeprecated()[1].GetInt();
+  const base::Value& callback_id = args[0];
+  int num_applications = args[1].GetInt();
   DCHECK_GT(num_applications, 0);
 
   ResolveJavascriptCallback(
diff --git a/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h
index 20e5ece..10d2cb9 100644
--- a/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h
+++ b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h
@@ -13,10 +13,6 @@
 
 class RegistryKeyWatcher;
 
-namespace base {
-class ListValue;
-}
-
 namespace settings {
 
 // Incompatible Applications settings page UI handler.
@@ -38,15 +34,17 @@
 
  private:
   // Sends the list of incompatible applications to the caller via a promise.
-  void HandleRequestIncompatibleApplicationsList(const base::ListValue* args);
+  void HandleRequestIncompatibleApplicationsList(
+      base::Value::ConstListView args);
 
   // Initiates the uninstallation of the application passed using |args|.
-  void HandleStartApplicationUninstallation(const base::ListValue* args);
+  void HandleStartApplicationUninstallation(base::Value::ConstListView args);
 
-  void HandleGetSubtitlePluralString(const base::ListValue* args);
-  void HandleGetSubtitleNoAdminRightsPluralString(const base::ListValue* args);
-  void HandleGetListTitlePluralString(const base::ListValue* args);
-  void GetPluralString(int id, const base::ListValue* args);
+  void HandleGetSubtitlePluralString(base::Value::ConstListView args);
+  void HandleGetSubtitleNoAdminRightsPluralString(
+      base::Value::ConstListView args);
+  void HandleGetListTitlePluralString(base::Value::ConstListView args);
+  void GetPluralString(int id, base::Value::ConstListView args);
 
   // Callback for the registry key watchers.
   void OnApplicationRemoved(
diff --git a/chrome/browser/ui/webui/settings/languages_handler.cc b/chrome/browser/ui/webui/settings/languages_handler.cc
index aa71f99c..bebc625 100644
--- a/chrome/browser/ui/webui/settings/languages_handler.cc
+++ b/chrome/browser/ui/webui/settings/languages_handler.cc
@@ -33,19 +33,19 @@
 LanguagesHandler::~LanguagesHandler() = default;
 
 void LanguagesHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getProspectiveUILanguage",
       base::BindRepeating(&LanguagesHandler::HandleGetProspectiveUILanguage,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setProspectiveUILanguage",
       base::BindRepeating(&LanguagesHandler::HandleSetProspectiveUILanguage,
                           base::Unretained(this)));
 }
 
 void LanguagesHandler::HandleGetProspectiveUILanguage(
-    const base::ListValue* args) {
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+    base::Value::ConstListView args) {
+  const base::Value& callback_id = args[0];
 
   AllowJavascript();
 
@@ -64,20 +64,20 @@
 }
 
 void LanguagesHandler::HandleSetProspectiveUILanguage(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(1U, args->GetListDeprecated().size());
+  CHECK_EQ(1U, args.size());
 
 #if BUILDFLAG(IS_WIN)
   PrefService* prefs = g_browser_process->local_state();
-  const std::string& language_code = args->GetListDeprecated()[0].GetString();
+  const std::string& language_code = args[0].GetString();
   prefs->SetString(language::prefs::kApplicationLocale, language_code);
 #elif BUILDFLAG(IS_CHROMEOS_ASH)
   // Secondary users and public session users cannot change the locale.
   user_manager::UserManager* user_manager = user_manager::UserManager::Get();
   const user_manager::User* user =
       ash::ProfileHelper::Get()->GetUserByProfile(profile_);
-  const std::string& language_code = args->GetListDeprecated()[0].GetString();
+  const std::string& language_code = args[0].GetString();
   if (user &&
       user->GetAccountId() == user_manager->GetPrimaryUser()->GetAccountId() &&
       user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
diff --git a/chrome/browser/ui/webui/settings/languages_handler.h b/chrome/browser/ui/webui/settings/languages_handler.h
index a7e7b70..97f98b7 100644
--- a/chrome/browser/ui/webui/settings/languages_handler.h
+++ b/chrome/browser/ui/webui/settings/languages_handler.h
@@ -12,10 +12,6 @@
 class Profile;
 #endif
 
-namespace base {
-class ListValue;
-}  // namespace base
-
 namespace settings {
 
 // Chrome "Languages" settings page UI handler.
@@ -41,11 +37,11 @@
   // Returns the prospective UI language. May not match the actual UI language,
   // depending on the user's permissions and whether the language is substituted
   // for another locale.
-  void HandleGetProspectiveUILanguage(const base::ListValue* args);
+  void HandleGetProspectiveUILanguage(base::Value::ConstListView args);
 
   // Changes the preferred UI language, provided the user is allowed to do so.
   // The actual UI language will not change until the next restart.
-  void HandleSetProspectiveUILanguage(const base::ListValue* args);
+  void HandleSetProspectiveUILanguage(base::Value::ConstListView args);
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   Profile* profile_;  // Weak pointer.
diff --git a/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc b/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc
index 92da5d7..ba2c35b8 100644
--- a/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc
+++ b/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc
@@ -30,11 +30,11 @@
 MetricsReportingHandler::~MetricsReportingHandler() {}
 
 void MetricsReportingHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getMetricsReporting",
       base::BindRepeating(&MetricsReportingHandler::HandleGetMetricsReporting,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setMetricsReportingEnabled",
       base::BindRepeating(
           &MetricsReportingHandler::HandleSetMetricsReportingEnabled,
@@ -55,11 +55,11 @@
 }
 
 void MetricsReportingHandler::HandleGetMetricsReporting(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  const base::Value* callback_id;
-  CHECK(args->Get(0, &callback_id));
-  ResolveJavascriptCallback(*callback_id, *CreateMetricsReportingDict());
+  CHECK_GT(args.size(), 0u);
+  const base::Value& callback_id = args[0];
+  ResolveJavascriptCallback(callback_id, *CreateMetricsReportingDict());
 }
 
 std::unique_ptr<base::DictionaryValue>
@@ -85,7 +85,7 @@
 }
 
 void MetricsReportingHandler::HandleSetMetricsReportingEnabled(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   if (IsMetricsReportingPolicyManaged()) {
     NOTREACHED();
     // NOTE: ChangeMetricsReportingState() already checks whether metrics
@@ -96,7 +96,7 @@
     return;
   }
 
-  bool enabled = args->GetListDeprecated()[0].GetBool();
+  bool enabled = args[0].GetBool();
   ChangeMetricsReportingState(enabled);
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/ui/webui/settings/metrics_reporting_handler.h b/chrome/browser/ui/webui/settings/metrics_reporting_handler.h
index e4cebe0..9dc4198 100644
--- a/chrome/browser/ui/webui/settings/metrics_reporting_handler.h
+++ b/chrome/browser/ui/webui/settings/metrics_reporting_handler.h
@@ -43,7 +43,7 @@
  protected:
   // Handler for "getMetricsReporting" message. No arguments. Protected for
   // testing.
-  void HandleGetMetricsReporting(const base::ListValue* args);
+  void HandleGetMetricsReporting(base::Value::ConstListView args);
 
  private:
   // Describes the state of metrics reporting in a base::DictionaryValue.
@@ -52,7 +52,7 @@
 
   // Handler for "setMetricsReportingEnabled" message. Passed a single,
   // |enabled| boolean argument.
-  void HandleSetMetricsReportingEnabled(const base::ListValue* args);
+  void HandleSetMetricsReportingEnabled(base::Value::ConstListView args);
 
   // Called when the local state pref controlling metrics reporting changes.
   void OnPrefChanged(const std::string& pref_name);
diff --git a/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc b/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc
index bb2f758..8cd9d1a 100644
--- a/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc
@@ -45,7 +45,7 @@
 
     base::ListValue args;
     args.Append(std::make_unique<base::Value>(1));
-    handler()->HandleGetMetricsReporting(&args);
+    handler()->HandleGetMetricsReporting(args);
 
     EXPECT_TRUE(handler()->IsJavascriptAllowed());
     EXPECT_EQ(1u, test_web_ui()->call_data().size());
diff --git a/chrome/browser/ui/webui/settings/native_certificates_handler.cc b/chrome/browser/ui/webui/settings/native_certificates_handler.cc
index c8b2ec6..8676588 100644
--- a/chrome/browser/ui/webui/settings/native_certificates_handler.cc
+++ b/chrome/browser/ui/webui/settings/native_certificates_handler.cc
@@ -17,7 +17,7 @@
 NativeCertificatesHandler::~NativeCertificatesHandler() {}
 
 void NativeCertificatesHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showManageSSLCertificates",
       base::BindRepeating(
           &NativeCertificatesHandler::HandleShowManageSSLCertificates,
@@ -25,7 +25,7 @@
 }
 
 void NativeCertificatesHandler::HandleShowManageSSLCertificates(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   base::RecordAction(base::UserMetricsAction("Options_ManageSSLCertificates"));
   settings_utils::ShowManageSSLCertificates(web_ui()->GetWebContents());
 }
diff --git a/chrome/browser/ui/webui/settings/native_certificates_handler.h b/chrome/browser/ui/webui/settings/native_certificates_handler.h
index 8fd3386..b0cddee 100644
--- a/chrome/browser/ui/webui/settings/native_certificates_handler.h
+++ b/chrome/browser/ui/webui/settings/native_certificates_handler.h
@@ -26,7 +26,7 @@
 
   // Callback for the "showManageSSLCertificates" message. This will invoke
   // an appropriate certificate management action based on the platform.
-  void HandleShowManageSSLCertificates(const base::ListValue* args);
+  void HandleShowManageSSLCertificates(base::Value::ConstListView args);
 };
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/on_startup_handler.cc b/chrome/browser/ui/webui/settings/on_startup_handler.cc
index bb91c70..93f0bf18 100644
--- a/chrome/browser/ui/webui/settings/on_startup_handler.cc
+++ b/chrome/browser/ui/webui/settings/on_startup_handler.cc
@@ -39,11 +39,11 @@
 }
 
 void OnStartupHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getNtpExtension",
       base::BindRepeating(&OnStartupHandler::HandleGetNtpExtension,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "validateStartupPage",
       base::BindRepeating(&OnStartupHandler::HandleValidateStartupPage,
                           base::Unretained(this)));
@@ -79,17 +79,18 @@
   return dict;
 }
 
-void OnStartupHandler::HandleGetNtpExtension(const base::ListValue* args) {
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+void OnStartupHandler::HandleGetNtpExtension(base::Value::ConstListView args) {
+  const base::Value& callback_id = args[0];
   AllowJavascript();
 
   ResolveJavascriptCallback(callback_id, GetNtpExtension());
 }
 
-void OnStartupHandler::HandleValidateStartupPage(const base::ListValue* args) {
-  CHECK_EQ(args->GetListDeprecated().size(), 2U);
-  const base::Value& callback_id = args->GetListDeprecated()[0];
-  const std::string& url_string = args->GetListDeprecated()[1].GetString();
+void OnStartupHandler::HandleValidateStartupPage(
+    base::Value::ConstListView args) {
+  CHECK_EQ(args.size(), 2U);
+  const base::Value& callback_id = args[0];
+  const std::string& url_string = args[1].GetString();
   AllowJavascript();
 
   bool valid = settings_utils::FixupAndValidateStartupPage(url_string, nullptr);
diff --git a/chrome/browser/ui/webui/settings/on_startup_handler.h b/chrome/browser/ui/webui/settings/on_startup_handler.h
index c296750..a79d88a 100644
--- a/chrome/browser/ui/webui/settings/on_startup_handler.h
+++ b/chrome/browser/ui/webui/settings/on_startup_handler.h
@@ -14,10 +14,6 @@
 
 class Profile;
 
-namespace base {
-class ListValue;
-}
-
 namespace settings {
 
 class OnStartupHandler : public SettingsPageUIHandler,
@@ -48,11 +44,11 @@
   base::Value GetNtpExtension();
 
   // Handler for the "getNtpExtension" message. No arguments.
-  void HandleGetNtpExtension(const base::ListValue* /*args*/);
+  void HandleGetNtpExtension(base::Value::ConstListView args);
 
   // Handles the "validateStartupPage" message. Passed a URL that might be a
   // valid startup page.
-  void HandleValidateStartupPage(const base::ListValue* args);
+  void HandleValidateStartupPage(base::Value::ConstListView args);
 
   // extensions::ExtensionRegistryObserver.
   void OnExtensionUnloaded(content::BrowserContext* browser_context,
diff --git a/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc b/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc
index daba42d..9c316e5 100644
--- a/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc
@@ -80,7 +80,7 @@
 TEST_F(OnStartupHandlerTest, HandleGetNtpExtension) {
   base::Value list_args(base::Value::Type::LIST);
   list_args.Append(kCallbackId);
-  handler()->HandleGetNtpExtension(&base::Value::AsListValue(list_args));
+  handler()->HandleGetNtpExtension(list_args.GetListDeprecated());
 
   EXPECT_EQ(1U, web_ui()->call_data().size());
 
@@ -98,7 +98,7 @@
   base::Value list_args(base::Value::Type::LIST);
   list_args.Append(kCallbackId);
   list_args.Append("http://example.com");
-  handler()->HandleValidateStartupPage(&base::Value::AsListValue(list_args));
+  handler()->HandleValidateStartupPage(list_args.GetListDeprecated());
 
   EXPECT_EQ(1U, web_ui()->call_data().size());
 
@@ -119,7 +119,7 @@
   base::Value list_args(base::Value::Type::LIST);
   list_args.Append(kCallbackId);
   list_args.Append("@");
-  handler()->HandleValidateStartupPage(&base::Value::AsListValue(list_args));
+  handler()->HandleValidateStartupPage(list_args.GetListDeprecated());
 
   EXPECT_EQ(1U, web_ui()->call_data().size());
 
diff --git a/chrome/browser/ui/webui/settings/privacy_sandbox_handler.cc b/chrome/browser/ui/webui/settings/privacy_sandbox_handler.cc
index 06c1cb61..a0ce4d23 100644
--- a/chrome/browser/ui/webui/settings/privacy_sandbox_handler.cc
+++ b/chrome/browser/ui/webui/settings/privacy_sandbox_handler.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/webui/settings/privacy_sandbox_handler.h"
 
-#include "chrome/browser/federated_learning/floc_id_provider_factory.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -43,27 +42,27 @@
 }  // namespace
 
 void PrivacySandboxHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getFlocId", base::BindRepeating(&PrivacySandboxHandler::HandleGetFlocId,
                                        base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "resetFlocId",
       base::BindRepeating(&PrivacySandboxHandler::HandleResetFlocId,
                           base::Unretained(this)));
 }
 
-void PrivacySandboxHandler::HandleGetFlocId(const base::ListValue* args) {
+void PrivacySandboxHandler::HandleGetFlocId(base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+  CHECK_EQ(1U, args.size());
+  const base::Value& callback_id = args[0];
 
   ResolveJavascriptCallback(callback_id,
                             GetFlocIdInformation(Profile::FromWebUI(web_ui())));
 }
 
-void PrivacySandboxHandler::HandleResetFlocId(const base::ListValue* args) {
-  CHECK_EQ(0U, args->GetListDeprecated().size());
+void PrivacySandboxHandler::HandleResetFlocId(base::Value::ConstListView args) {
+  CHECK_EQ(0U, args.size());
   AllowJavascript();
 
   auto* privacy_sandbox_service =
diff --git a/chrome/browser/ui/webui/settings/privacy_sandbox_handler.h b/chrome/browser/ui/webui/settings/privacy_sandbox_handler.h
index 5229cc6..10f89e6 100644
--- a/chrome/browser/ui/webui/settings/privacy_sandbox_handler.h
+++ b/chrome/browser/ui/webui/settings/privacy_sandbox_handler.h
@@ -23,9 +23,9 @@
   FRIEND_TEST_ALL_PREFIXES(PrivacySandboxHandlerTest, GetFlocId);
   FRIEND_TEST_ALL_PREFIXES(PrivacySandboxHandlerTest, ResetFlocId);
 
-  void HandleGetFlocId(const base::ListValue* args);
+  void HandleGetFlocId(base::Value::ConstListView args);
 
-  void HandleResetFlocId(const base::ListValue* args);
+  void HandleResetFlocId(base::Value::ConstListView args);
 
   // SettingsPageUIHandler:
   void OnJavascriptAllowed() override {}
diff --git a/chrome/browser/ui/webui/settings/privacy_sandbox_handler_unittest.cc b/chrome/browser/ui/webui/settings/privacy_sandbox_handler_unittest.cc
index eb094023..21305da 100644
--- a/chrome/browser/ui/webui/settings/privacy_sandbox_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/privacy_sandbox_handler_unittest.cc
@@ -5,12 +5,10 @@
 #include "chrome/browser/ui/webui/settings/privacy_sandbox_handler.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/federated_learning/floc_id_provider_factory.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/federated_learning/floc_id.h"
 #include "components/privacy_sandbox/privacy_sandbox_settings.h"
 #include "components/privacy_sandbox/privacy_sandbox_test_util.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
@@ -87,14 +85,9 @@
 };
 
 TEST_F(PrivacySandboxHandlerTest, GetFlocId) {
-  federated_learning::FlocId floc_id = federated_learning::FlocId::CreateValid(
-      123456, base::Time(), base::Time::Now(),
-      /*sorting_lsh_version=*/0);
-  floc_id.SaveToPrefs(profile()->GetTestingPrefService());
-
   base::Value args(base::Value::Type::LIST);
   args.Append(kCallbackId);
-  handler()->HandleGetFlocId(&base::Value::AsListValue(args));
+  handler()->HandleGetFlocId(args.GetListDeprecated());
 
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
   EXPECT_EQ(kCallbackId, data.arg1()->GetString());
@@ -104,11 +97,6 @@
 }
 
 TEST_F(PrivacySandboxHandlerTest, ResetFlocId) {
-  federated_learning::FlocId floc_id = federated_learning::FlocId::CreateValid(
-      123456, base::Time(), base::Time::Now(),
-      /*sorting_lsh_version=*/0);
-  floc_id.SaveToPrefs(profile()->GetTestingPrefService());
-
   // Observers of the PrivacySandboxSettings service should be informed that
   // the FLoC ID was reset.
   privacy_sandbox_test_util::MockPrivacySandboxObserver observer;
@@ -116,7 +104,7 @@
   EXPECT_CALL(observer, OnFlocDataAccessibleSinceUpdated(true));
 
   base::Value args(base::Value::Type::LIST);
-  handler()->HandleResetFlocId(&base::Value::AsListValue(args));
+  handler()->HandleResetFlocId(args.GetListDeprecated());
 
   // Resetting the FLoC ID should also fire the appropriate WebUI listener.
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
diff --git a/chrome/browser/ui/webui/settings/profile_info_handler.cc b/chrome/browser/ui/webui/settings/profile_info_handler.cc
index cc6600a9..3810ea3 100644
--- a/chrome/browser/ui/webui/settings/profile_info_handler.cc
+++ b/chrome/browser/ui/webui/settings/profile_info_handler.cc
@@ -45,12 +45,12 @@
 ProfileInfoHandler::~ProfileInfoHandler() {}
 
 void ProfileInfoHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getProfileInfo",
       base::BindRepeating(&ProfileInfoHandler::HandleGetProfileInfo,
                           base::Unretained(this)));
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getProfileStatsCount",
       base::BindRepeating(&ProfileInfoHandler::HandleGetProfileStats,
                           base::Unretained(this)));
@@ -97,17 +97,18 @@
   PushProfileInfo();
 }
 
-void ProfileInfoHandler::HandleGetProfileInfo(const base::ListValue* args) {
+void ProfileInfoHandler::HandleGetProfileInfo(base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+  CHECK_EQ(1U, args.size());
+  const base::Value& callback_id = args[0];
 
   ResolveJavascriptCallback(callback_id, *GetAccountNameAndIcon());
 }
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
-void ProfileInfoHandler::HandleGetProfileStats(const base::ListValue* args) {
+void ProfileInfoHandler::HandleGetProfileStats(
+    base::Value::ConstListView args) {
   AllowJavascript();
 
   ProfileStatisticsFactory::GetForProfile(profile_)->GatherStatistics(
diff --git a/chrome/browser/ui/webui/settings/profile_info_handler.h b/chrome/browser/ui/webui/settings/profile_info_handler.h
index 6e8cb7b..dcdc645 100644
--- a/chrome/browser/ui/webui/settings/profile_info_handler.h
+++ b/chrome/browser/ui/webui/settings/profile_info_handler.h
@@ -63,11 +63,11 @@
   FRIEND_TEST_ALL_PREFIXES(ProfileInfoHandlerTest, PushProfileInfo);
 
   // Callbacks from the page.
-  void HandleGetProfileInfo(const base::ListValue* args);
+  void HandleGetProfileInfo(base::Value::ConstListView args);
   void PushProfileInfo();
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
-  void HandleGetProfileStats(const base::ListValue* args);
+  void HandleGetProfileStats(base::Value::ConstListView args);
 
   // Returns the sum of the counts of individual profile states. Returns 0 if
   // there exists a stat that was not successfully retrieved.
diff --git a/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc b/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc
index f0a617e..3e07c539 100644
--- a/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc
@@ -117,7 +117,7 @@
 TEST_F(ProfileInfoHandlerTest, GetProfileInfo) {
   base::Value list_args(base::Value::Type::LIST);
   list_args.Append("get-profile-info-callback-id");
-  handler()->HandleGetProfileInfo(&base::Value::AsListValue(list_args));
+  handler()->HandleGetProfileInfo(list_args.GetListDeprecated());
 
   EXPECT_EQ(1U, web_ui()->call_data().size());
 
diff --git a/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc b/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc
index 5eec19c49..f99ee40 100644
--- a/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc
+++ b/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc
@@ -66,25 +66,25 @@
 }
 
 void ProtocolHandlersHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "observeProtocolHandlers",
       base::BindRepeating(
           &ProtocolHandlersHandler::HandleObserveProtocolHandlers,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "observeProtocolHandlersEnabledState",
       base::BindRepeating(
           &ProtocolHandlersHandler::HandleObserveProtocolHandlersEnabledState,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "removeHandler",
       base::BindRepeating(&ProtocolHandlersHandler::HandleRemoveHandler,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setHandlersEnabled",
       base::BindRepeating(&ProtocolHandlersHandler::HandleSetHandlersEnabled,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setDefault",
       base::BindRepeating(&ProtocolHandlersHandler::HandleSetDefault,
                           base::Unretained(this)));
@@ -168,14 +168,14 @@
 }
 
 void ProtocolHandlersHandler::HandleObserveProtocolHandlers(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   SendHandlersEnabledValue();
   UpdateHandlerList();
 }
 
 void ProtocolHandlersHandler::HandleObserveProtocolHandlersEnabledState(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   SendHandlersEnabledValue();
 }
@@ -185,7 +185,8 @@
                     base::Value(GetProtocolHandlerRegistry()->enabled()));
 }
 
-void ProtocolHandlersHandler::HandleRemoveHandler(const base::ListValue* args) {
+void ProtocolHandlersHandler::HandleRemoveHandler(
+    base::Value::ConstListView args) {
   ProtocolHandler handler(ParseHandlerFromArgs(args));
   CHECK(!handler.IsEmpty());
   GetProtocolHandlerRegistry()->RemoveHandler(handler);
@@ -196,25 +197,26 @@
 }
 
 void ProtocolHandlersHandler::HandleSetHandlersEnabled(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   bool enabled = true;
-  CHECK(args->GetListDeprecated()[0].is_bool());
-  enabled = args->GetListDeprecated()[0].GetBool();
+  CHECK(args[0].is_bool());
+  enabled = args[0].GetBool();
   if (enabled)
     GetProtocolHandlerRegistry()->Enable();
   else
     GetProtocolHandlerRegistry()->Disable();
 }
 
-void ProtocolHandlersHandler::HandleSetDefault(const base::ListValue* args) {
+void ProtocolHandlersHandler::HandleSetDefault(
+    base::Value::ConstListView args) {
   const ProtocolHandler& handler(ParseHandlerFromArgs(args));
   CHECK(!handler.IsEmpty());
   GetProtocolHandlerRegistry()->OnAcceptRegisterProtocolHandler(handler);
 }
 
 ProtocolHandler ProtocolHandlersHandler::ParseHandlerFromArgs(
-    const base::ListValue* args) const {
-  base::Value::ConstListView args_list = args->GetListDeprecated();
+    base::Value::ConstListView args) const {
+  base::Value::ConstListView args_list = args;
   bool ok = args_list.size() >= 2u && args_list[0].is_string() &&
             args_list[1].is_string();
   if (!ok)
diff --git a/chrome/browser/ui/webui/settings/protocol_handlers_handler.h b/chrome/browser/ui/webui/settings/protocol_handlers_handler.h
index 4a512f10..5e57110 100644
--- a/chrome/browser/ui/webui/settings/protocol_handlers_handler.h
+++ b/chrome/browser/ui/webui/settings/protocol_handlers_handler.h
@@ -61,25 +61,26 @@
   // Called to fetch the state of the protocol handlers. If the full list of
   // handlers is not needed, consider HandleObserveProtocolHandlersEnabledState
   // instead.
-  void HandleObserveProtocolHandlers(const base::ListValue* args);
+  void HandleObserveProtocolHandlers(base::Value::ConstListView args);
 
   // Called to begin updates to the handlers enabled status. This is a subset
   // (lighter alternative) of HandleObserveProtocolHandlers. There's no need to
   // call this function if HandleObserveProtocolHandlers is called.
-  void HandleObserveProtocolHandlersEnabledState(const base::ListValue* args);
+  void HandleObserveProtocolHandlersEnabledState(
+      base::Value::ConstListView args);
 
   // Notifies the JS side whether the handlers are enabled or not.
   void SendHandlersEnabledValue();
 
   // Called when the user toggles whether custom handlers are enabled.
-  void HandleSetHandlersEnabled(const base::ListValue* args);
+  void HandleSetHandlersEnabled(base::Value::ConstListView args);
 
   // Called when the user sets a new default handler for a protocol.
-  void HandleSetDefault(const base::ListValue* args);
+  void HandleSetDefault(base::Value::ConstListView args);
 
   // Parses a ProtocolHandler out of the arguments passed back from the view.
   // |args| is a list of [protocol, url].
-  ProtocolHandler ParseHandlerFromArgs(const base::ListValue* args) const;
+  ProtocolHandler ParseHandlerFromArgs(base::Value::ConstListView args) const;
 
   // Returns a JSON object describing the set of protocol handlers for the
   // given protocol.
@@ -94,7 +95,7 @@
 
   // Remove a handler.
   // |args| is a list of [protocol, url].
-  void HandleRemoveHandler(const base::ListValue* args);
+  void HandleRemoveHandler(base::Value::ConstListView args);
 
   custom_handlers::ProtocolHandlerRegistry* GetProtocolHandlerRegistry();
 
diff --git a/chrome/browser/ui/webui/settings/reset_settings_handler.cc b/chrome/browser/ui/webui/settings/reset_settings_handler.cc
index caaed59..91322a9 100644
--- a/chrome/browser/ui/webui/settings/reset_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/reset_settings_handler.cc
@@ -97,33 +97,33 @@
 }
 
 void ResetSettingsHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "performResetProfileSettings",
       base::BindRepeating(&ResetSettingsHandler::HandleResetProfileSettings,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "onShowResetProfileDialog",
       base::BindRepeating(&ResetSettingsHandler::OnShowResetProfileDialog,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getReportedSettings",
       base::BindRepeating(&ResetSettingsHandler::HandleGetReportedSettings,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "onHideResetProfileDialog",
       base::BindRepeating(&ResetSettingsHandler::OnHideResetProfileDialog,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "onHideResetProfileBanner",
       base::BindRepeating(&ResetSettingsHandler::OnHideResetProfileBanner,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getTriggeredResetToolName",
       base::BindRepeating(
           &ResetSettingsHandler::HandleGetTriggeredResetToolName,
           base::Unretained(this)));
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "onPowerwashDialogShow",
       base::BindRepeating(&ResetSettingsHandler::OnShowPowerwashDialog,
                           base::Unretained(this)));
@@ -131,13 +131,13 @@
 }
 
 void ResetSettingsHandler::HandleResetProfileSettings(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(3U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
-  const bool& send_settings = args->GetListDeprecated()[1].GetBool();
-  std::string request_origin_string = args->GetListDeprecated()[2].GetString();
+  CHECK_EQ(3U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  const bool& send_settings = args[1].GetBool();
+  std::string request_origin_string = args[2].GetString();
   reset_report::ChromeResetReport::ResetRequestOrigin request_origin =
       ResetRequestOriginFromString(request_origin_string);
 
@@ -174,11 +174,11 @@
 }
 
 void ResetSettingsHandler::HandleGetReportedSettings(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   setting_snapshot_->RequestShortcuts(
       base::BindOnce(&ResetSettingsHandler::OnGetReportedSettingsDone,
@@ -192,7 +192,7 @@
 }
 
 void ResetSettingsHandler::OnShowResetProfileDialog(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   if (!GetResetter()->IsActive()) {
     setting_snapshot_ = std::make_unique<ResettableSettingsSnapshot>(profile_);
   }
@@ -208,13 +208,13 @@
 }
 
 void ResetSettingsHandler::OnHideResetProfileDialog(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   if (!GetResetter()->IsActive())
     setting_snapshot_.reset();
 }
 
 void ResetSettingsHandler::OnHideResetProfileBanner(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   chrome_prefs::ClearResetTime(profile_);
 }
 
@@ -262,11 +262,11 @@
 }
 
 void ResetSettingsHandler::HandleGetTriggeredResetToolName(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+  CHECK_EQ(1U, args.size());
+  const base::Value& callback_id = args[0];
 
   // Set up the localized strings for the triggered profile reset dialog.
   // Custom reset tool names are supported on Windows only.
@@ -295,7 +295,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 void ResetSettingsHandler::OnShowPowerwashDialog(
-     const base::ListValue* args) {
+    base::Value::ConstListView args) {
   UMA_HISTOGRAM_ENUMERATION(
       "Reset.ChromeOS.PowerwashDialogShown",
       ash::reset::DialogViewType::kFromOptions,
diff --git a/chrome/browser/ui/webui/settings/reset_settings_handler.h b/chrome/browser/ui/webui/settings/reset_settings_handler.h
index dbd387f..1dfee21 100644
--- a/chrome/browser/ui/webui/settings/reset_settings_handler.h
+++ b/chrome/browser/ui/webui/settings/reset_settings_handler.h
@@ -15,10 +15,6 @@
 #include "chrome/browser/profile_resetter/profile_reset_report.pb.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 
-namespace base {
-class ListValue;
-}  // namespace base
-
 class BrandcodeConfigFetcher;
 class Profile;
 class ProfileResetter;
@@ -54,26 +50,26 @@
   virtual ProfileResetter* GetResetter();
 
   // Javascript callback to start clearing data.
-  void HandleResetProfileSettings(const base::ListValue* args);
+  void HandleResetProfileSettings(base::Value::ConstListView args);
 
  private:
   // Retrieves the settings that will be reported, called from Javascript.
-  void HandleGetReportedSettings(const base::ListValue* args);
+  void HandleGetReportedSettings(base::Value::ConstListView args);
 
   // Called once the settings that will be reported have been retrieved.
   void OnGetReportedSettingsDone(std::string callback_id);
 
   // Called when the reset profile dialog is shown.
-  void OnShowResetProfileDialog(const base::ListValue* args);
+  void OnShowResetProfileDialog(base::Value::ConstListView args);
 
   // Called when the reset profile dialog is hidden.
-  void OnHideResetProfileDialog(const base::ListValue* args);
+  void OnHideResetProfileDialog(base::Value::ConstListView args);
 
   // Called when the reset profile banner is shown.
-  void OnHideResetProfileBanner(const base::ListValue* args);
+  void OnHideResetProfileBanner(base::Value::ConstListView args);
 
   // Retrieve the triggered reset tool name, called from Javascript.
-  void HandleGetTriggeredResetToolName(const base::ListValue* args);
+  void HandleGetTriggeredResetToolName(base::Value::ConstListView args);
 
   // Called when BrandcodeConfigFetcher completed fetching settings.
   void OnSettingsFetched();
@@ -93,7 +89,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Will be called when powerwash dialog is shown.
-  void OnShowPowerwashDialog(const base::ListValue* args);
+  void OnShowPowerwashDialog(base::Value::ConstListView args);
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   const raw_ptr<Profile> profile_;
diff --git a/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc
index 9339fa9..8fd1f13 100644
--- a/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc
@@ -95,7 +95,7 @@
   list.Append(expected_callback_id);
   list.Append(false);
   list.Append("");
-  handler()->HandleResetProfileSettings(&base::Value::AsListValue(list));
+  handler()->HandleResetProfileSettings(list.GetListDeprecated());
   // Check that the delegate ProfileResetter was called.
   EXPECT_EQ(1u, handler()->resets());
   // Check that Javascript side is notified after resetting is done.
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler.cc b/chrome/browser/ui/webui/settings/safety_check_handler.cc
index eed5463..d911b24 100644
--- a/chrome/browser/ui/webui/settings/safety_check_handler.cc
+++ b/chrome/browser/ui/webui/settings/safety_check_handler.cc
@@ -358,7 +358,8 @@
       extension_service_(extension_service),
       timestamp_delegate_(std::move(timestamp_delegate)) {}
 
-void SafetyCheckHandler::HandlePerformSafetyCheck(const base::ListValue* args) {
+void SafetyCheckHandler::HandlePerformSafetyCheck(
+    base::Value::ConstListView args) {
   SendSafetyCheckStartedWebUiUpdates();
 
   // Run safety check after a delay. This ensures that the "running" state is
@@ -372,8 +373,8 @@
 }
 
 void SafetyCheckHandler::HandleGetParentRanDisplayString(
-    const base::ListValue* args) {
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+    base::Value::ConstListView args) {
+  const base::Value& callback_id = args[0];
 
   // Send updated timestamp-based display strings to all SC children who have
   // such strings.
@@ -1055,11 +1056,11 @@
 void SafetyCheckHandler::RegisterMessages() {
   // Usage of base::Unretained(this) is safe, because web_ui() owns `this` and
   // won't release ownership until destruction.
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       kPerformSafetyCheck,
       base::BindRepeating(&SafetyCheckHandler::HandlePerformSafetyCheck,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       kGetParentRanDisplayString,
       base::BindRepeating(&SafetyCheckHandler::HandleGetParentRanDisplayString,
                           base::Unretained(this)));
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler.h b/chrome/browser/ui/webui/settings/safety_check_handler.h
index d249ec04..650c97e 100644
--- a/chrome/browser/ui/webui/settings/safety_check_handler.h
+++ b/chrome/browser/ui/webui/settings/safety_check_handler.h
@@ -189,11 +189,11 @@
 
   // Handles triggering the safety check from the frontend (by user pressing a
   // button).
-  void HandlePerformSafetyCheck(const base::ListValue* args);
+  void HandlePerformSafetyCheck(base::Value::ConstListView args);
 
   // Handles updating the safety check parent display string to show how long
   // ago the safety check last ran.
-  void HandleGetParentRanDisplayString(const base::ListValue* args);
+  void HandleGetParentRanDisplayString(base::Value::ConstListView args);
 
   // Triggers an update check and invokes OnUpdateCheckResult once results
   // are available.
diff --git a/chrome/browser/ui/webui/settings/search_engines_handler.cc b/chrome/browser/ui/webui/settings/search_engines_handler.cc
index f4a424f..6a1ea0e 100644
--- a/chrome/browser/ui/webui/settings/search_engines_handler.cc
+++ b/chrome/browser/ui/webui/settings/search_engines_handler.cc
@@ -57,37 +57,37 @@
 }
 
 void SearchEnginesHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getSearchEnginesList",
       base::BindRepeating(&SearchEnginesHandler::HandleGetSearchEnginesList,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setDefaultSearchEngine",
       base::BindRepeating(&SearchEnginesHandler::HandleSetDefaultSearchEngine,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setIsActiveSearchEngine",
       base::BindRepeating(&SearchEnginesHandler::HandleSetIsActiveSearchEngine,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "removeSearchEngine",
       base::BindRepeating(&SearchEnginesHandler::HandleRemoveSearchEngine,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "validateSearchEngineInput",
       base::BindRepeating(
           &SearchEnginesHandler::HandleValidateSearchEngineInput,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "searchEngineEditStarted",
       base::BindRepeating(&SearchEnginesHandler::HandleSearchEngineEditStarted,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "searchEngineEditCancelled",
       base::BindRepeating(
           &SearchEnginesHandler::HandleSearchEngineEditCancelled,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "searchEngineEditCompleted",
       base::BindRepeating(
           &SearchEnginesHandler::HandleSearchEngineEditCompleted,
@@ -252,15 +252,15 @@
 }
 
 void SearchEnginesHandler::HandleGetSearchEnginesList(
-    const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+    base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  const base::Value& callback_id = args[0];
   AllowJavascript();
   ResolveJavascriptCallback(callback_id, *GetSearchEnginesList());
 }
 
 void SearchEnginesHandler::HandleSetDefaultSearchEngine(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   int index;
   if (!ExtractIntegerValue(args, &index)) {
     NOTREACHED();
@@ -275,10 +275,10 @@
 }
 
 void SearchEnginesHandler::HandleSetIsActiveSearchEngine(
-    const base::ListValue* args) {
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  const int index = args->GetListDeprecated()[0].GetInt();
-  const bool is_active = args->GetListDeprecated()[1].GetBool();
+    base::Value::ConstListView args) {
+  CHECK_EQ(2U, args.size());
+  const int index = args[0].GetInt();
+  const bool is_active = args[1].GetBool();
 
   if (index < 0 || index >= list_controller_.table_model()->RowCount())
     return;
@@ -287,7 +287,7 @@
 }
 
 void SearchEnginesHandler::HandleRemoveSearchEngine(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   int index;
   if (!ExtractIntegerValue(args, &index)) {
     NOTREACHED();
@@ -303,7 +303,7 @@
 }
 
 void SearchEnginesHandler::HandleSearchEngineEditStarted(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   int index;
   if (!ExtractIntegerValue(args, &index)) {
     NOTREACHED();
@@ -336,12 +336,12 @@
 }
 
 void SearchEnginesHandler::HandleValidateSearchEngineInput(
-    const base::ListValue* args) {
-  CHECK_EQ(3U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  CHECK_EQ(3U, args.size());
 
-  const base::Value& callback_id = args->GetListDeprecated()[0];
-  const std::string& field_name = args->GetListDeprecated()[1].GetString();
-  const std::string& field_value = args->GetListDeprecated()[2].GetString();
+  const base::Value& callback_id = args[0];
+  const std::string& field_name = args[1].GetString();
+  const std::string& field_value = args[2].GetString();
   ResolveJavascriptCallback(
       callback_id, base::Value(CheckFieldValidity(field_name, field_value)));
 }
@@ -365,7 +365,7 @@
 }
 
 void SearchEnginesHandler::HandleSearchEngineEditCancelled(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   if (!edit_controller_.get())
     return;
   edit_controller_->CleanUpCancelledAdd();
@@ -373,12 +373,12 @@
 }
 
 void SearchEnginesHandler::HandleSearchEngineEditCompleted(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   if (!edit_controller_.get())
     return;
-  const std::string& search_engine = args->GetListDeprecated()[0].GetString();
-  const std::string& keyword = args->GetListDeprecated()[1].GetString();
-  const std::string& query_url = args->GetListDeprecated()[2].GetString();
+  const std::string& search_engine = args[0].GetString();
+  const std::string& keyword = args[1].GetString();
+  const std::string& query_url = args[2].GetString();
 
   // Recheck validity. It's possible to get here with invalid input if e.g. the
   // user calls the right JS functions directly from the web inspector.
diff --git a/chrome/browser/ui/webui/settings/search_engines_handler.h b/chrome/browser/ui/webui/settings/search_engines_handler.h
index 8691bc6..1f2ef5cc 100644
--- a/chrome/browser/ui/webui/settings/search_engines_handler.h
+++ b/chrome/browser/ui/webui/settings/search_engines_handler.h
@@ -18,11 +18,6 @@
 
 class Profile;
 
-namespace base {
-class DictionaryValue;
-class ListValue;
-}
-
 namespace extensions {
 class Extension;
 }
@@ -59,28 +54,28 @@
 
  private:
   // Retrieves all search engines and returns them to WebUI.
-  void HandleGetSearchEnginesList(const base::ListValue* args);
+  void HandleGetSearchEnginesList(base::Value::ConstListView args);
 
   std::unique_ptr<base::DictionaryValue> GetSearchEnginesList();
 
   // Removes the search engine at the given index. Called from WebUI.
-  void HandleRemoveSearchEngine(const base::ListValue* args);
+  void HandleRemoveSearchEngine(base::Value::ConstListView args);
 
   // Sets the search engine at the given index to be default. Called from WebUI.
-  void HandleSetDefaultSearchEngine(const base::ListValue* args);
+  void HandleSetDefaultSearchEngine(base::Value::ConstListView args);
 
   // Activates or deactivates the search engine at the given index. Called from
   // WebUI.
-  void HandleSetIsActiveSearchEngine(const base::ListValue* args);
+  void HandleSetIsActiveSearchEngine(base::Value::ConstListView args);
 
   // Starts an edit session for the search engine at the given index. If the
   // index is -1, starts editing a new search engine instead of an existing one.
   // Called from WebUI.
-  void HandleSearchEngineEditStarted(const base::ListValue* args);
+  void HandleSearchEngineEditStarted(base::Value::ConstListView args);
 
   // Validates the given search engine values, and reports the results back
   // to WebUI. Called from WebUI.
-  void HandleValidateSearchEngineInput(const base::ListValue* args);
+  void HandleValidateSearchEngineInput(base::Value::ConstListView args);
 
   // Checks whether the given user input field (searchEngine, keyword, queryUrl)
   // is populated with a valid value.
@@ -89,11 +84,11 @@
 
   // Called when an edit is canceled.
   // Called from WebUI.
-  void HandleSearchEngineEditCancelled(const base::ListValue* args);
+  void HandleSearchEngineEditCancelled(base::Value::ConstListView args);
 
   // Called when an edit is finished and should be saved.
   // Called from WebUI.
-  void HandleSearchEngineEditCompleted(const base::ListValue* args);
+  void HandleSearchEngineEditCompleted(base::Value::ConstListView args);
 
   // Returns a dictionary to pass to WebUI representing the given search engine.
   std::unique_ptr<base::DictionaryValue> CreateDictionaryForEngine(
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
index aaae75e..c75e456 100644
--- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
@@ -140,39 +140,39 @@
 }
 
 void CookiesViewHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "localData.getDisplayList",
       base::BindRepeating(&CookiesViewHandler::HandleGetDisplayList,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "localData.removeAll",
       base::BindRepeating(&CookiesViewHandler::HandleRemoveAll,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "localData.removeShownItems",
       base::BindRepeating(&CookiesViewHandler::HandleRemoveShownItems,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "localData.removeItem",
       base::BindRepeating(&CookiesViewHandler::HandleRemoveItem,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "localData.getCookieDetails",
       base::BindRepeating(&CookiesViewHandler::HandleGetCookieDetails,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "localData.getNumCookiesString",
       base::BindRepeating(&CookiesViewHandler::HandleGetNumCookiesString,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "localData.removeSite",
       base::BindRepeating(&CookiesViewHandler::HandleRemoveSite,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "localData.removeThirdPartyCookies",
       base::BindRepeating(&CookiesViewHandler::HandleRemoveThirdParty,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "localData.reload",
       base::BindRepeating(&CookiesViewHandler::HandleReloadCookies,
                           base::Unretained(this)));
@@ -233,10 +233,11 @@
   cookies_tree_model_->AddCookiesTreeObserver(this);
 }
 
-void CookiesViewHandler::HandleGetCookieDetails(const base::ListValue* args) {
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  std::string callback_id = args->GetListDeprecated()[0].GetString();
-  std::string site = args->GetListDeprecated()[1].GetString();
+void CookiesViewHandler::HandleGetCookieDetails(
+    base::Value::ConstListView args) {
+  CHECK_EQ(2U, args.size());
+  std::string callback_id = args[0].GetString();
+  std::string site = args[1].GetString();
 
   AllowJavascript();
   pending_requests_.emplace(
@@ -266,11 +267,11 @@
 }
 
 void CookiesViewHandler::HandleGetNumCookiesString(
-    const base::ListValue* args) {
-  CHECK_EQ(2U, args->GetListDeprecated().size());
+    base::Value::ConstListView args) {
+  CHECK_EQ(2U, args.size());
   std::string callback_id;
-  callback_id = args->GetListDeprecated()[0].GetString();
-  int num_cookies = args->GetListDeprecated()[1].GetInt();
+  callback_id = args[0].GetString();
+  int num_cookies = args[1].GetInt();
 
   AllowJavascript();
   const std::u16string string =
@@ -281,11 +282,10 @@
   ResolveJavascriptCallback(base::Value(callback_id), base::Value(string));
 }
 
-void CookiesViewHandler::HandleGetDisplayList(const base::ListValue* args) {
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  std::string callback_id = args->GetListDeprecated()[0].GetString();
-  std::u16string filter =
-      base::UTF8ToUTF16(args->GetListDeprecated()[1].GetString());
+void CookiesViewHandler::HandleGetDisplayList(base::Value::ConstListView args) {
+  CHECK_EQ(2U, args.size());
+  std::string callback_id = args[0].GetString();
+  std::u16string filter = base::UTF8ToUTF16(args[1].GetString());
 
   AllowJavascript();
   pending_requests_.emplace(
@@ -308,9 +308,9 @@
   ReturnLocalDataList(callback_id);
 }
 
-void CookiesViewHandler::HandleReloadCookies(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  std::string callback_id = args->GetListDeprecated()[0].GetString();
+void CookiesViewHandler::HandleReloadCookies(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  std::string callback_id = args[0].GetString();
 
   // Allowing Javascript for the first time will queue a task to create a new
   // tree model. Thus the tree model only needs to be recreated if Javascript
@@ -334,11 +334,11 @@
   ProcessPendingRequests();
 }
 
-void CookiesViewHandler::HandleRemoveAll(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
+void CookiesViewHandler::HandleRemoveAll(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
   AllowJavascript();
 
-  std::string callback_id = args->GetListDeprecated()[0].GetString();
+  std::string callback_id = args[0].GetString();
 
   pending_requests_.emplace(
       Request::SYNC_BATCH,
@@ -352,8 +352,8 @@
   ResolveJavascriptCallback(base::Value(callback_id), base::Value());
 }
 
-void CookiesViewHandler::HandleRemoveItem(const base::ListValue* args) {
-  std::string node_path = args->GetListDeprecated()[0].GetString();
+void CookiesViewHandler::HandleRemoveItem(base::Value::ConstListView args) {
+  std::string node_path = args[0].GetString();
 
   AllowJavascript();
   pending_requests_.emplace(
@@ -371,9 +371,10 @@
   }
 }
 
-void CookiesViewHandler::HandleRemoveThirdParty(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  std::string callback_id = args->GetListDeprecated()[0].GetString();
+void CookiesViewHandler::HandleRemoveThirdParty(
+    base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  std::string callback_id = args[0].GetString();
 
   AllowJavascript();
   Profile* profile = Profile::FromWebUI(web_ui());
@@ -390,8 +391,9 @@
   ProcessPendingRequests();
 }
 
-void CookiesViewHandler::HandleRemoveShownItems(const base::ListValue* args) {
-  CHECK_EQ(0U, args->GetListDeprecated().size());
+void CookiesViewHandler::HandleRemoveShownItems(
+    base::Value::ConstListView args) {
+  CHECK_EQ(0U, args.size());
 
   AllowJavascript();
   pending_requests_.emplace(
@@ -407,10 +409,9 @@
     cookies_tree_model_->DeleteCookieNode(parent->children().front().get());
 }
 
-void CookiesViewHandler::HandleRemoveSite(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  std::u16string site =
-      base::UTF8ToUTF16(args->GetListDeprecated()[0].GetString());
+void CookiesViewHandler::HandleRemoveSite(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  std::u16string site = base::UTF8ToUTF16(args[0].GetString());
   AllowJavascript();
   pending_requests_.emplace(
       Request::NO_BATCH,
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h
index 1912cd4..9056d87 100644
--- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h
@@ -71,41 +71,41 @@
   void RecreateCookiesTreeModel();
 
   // Set |filter_| and get a portion (or all) of the list items.
-  void HandleGetDisplayList(const base::ListValue* args);
+  void HandleGetDisplayList(base::Value::ConstListView args);
   void GetDisplayList(std::string callback_id, const std::u16string& filter);
 
   // Remove all items matching the current |filter_|.
-  void HandleRemoveShownItems(const base::ListValue* args);
+  void HandleRemoveShownItems(base::Value::ConstListView args);
   void RemoveShownItems();
 
   // Remove selected sites data.
-  void HandleRemoveSite(const base::ListValue* args);
+  void HandleRemoveSite(base::Value::ConstListView args);
   void RemoveSite(const std::u16string& site);
 
   // Retrieve cookie details for a specific site.
-  void HandleGetCookieDetails(const base::ListValue* args);
+  void HandleGetCookieDetails(base::Value::ConstListView args);
   void GetCookieDetails(const std::string& callback_id,
                         const std::string& site);
 
   // Gets a plural string for the given number of cookies.
-  void HandleGetNumCookiesString(const base::ListValue* args);
+  void HandleGetNumCookiesString(base::Value::ConstListView args);
 
   // Remove all sites data.
-  void HandleRemoveAll(const base::ListValue* args);
+  void HandleRemoveAll(base::Value::ConstListView args);
   void RemoveAll(const std::string& callback_id);
 
   // Remove a single item.
-  void HandleRemoveItem(const base::ListValue* args);
+  void HandleRemoveItem(base::Value::ConstListView args);
   void RemoveItem(const std::string& path);
 
   // Removes cookies and site data available in third-party contexts.
-  void HandleRemoveThirdParty(const base::ListValue* args);
+  void HandleRemoveThirdParty(base::Value::ConstListView args);
 
   void ReturnLocalDataList(const std::string& callback_id);
 
   // Reloads the CookiesTreeModel and passes the nodes to
   // 'CookiesView.loadChildren' to update the WebUI.
-  void HandleReloadCookies(const base::ListValue* args);
+  void HandleReloadCookies(base::Value::ConstListView args);
 
   // Flag to indicate whether there is a batch update in progress.
   bool batch_update_;
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler_unittest.cc b/chrome/browser/ui/webui/settings/settings_cookies_view_handler_unittest.cc
index 34d7446..69b8427 100644
--- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler_unittest.cc
@@ -92,7 +92,7 @@
     SetupTreeModelForTesting();
     base::Value reload_args(base::Value::Type::LIST);
     reload_args.Append(kCallbackId);
-    handler()->HandleReloadCookies(&base::Value::AsListValue(reload_args));
+    handler()->HandleReloadCookies(reload_args.GetListDeprecated());
 
     // The handler will post a task to recreate the tree model.
     task_environment()->RunUntilIdle();
@@ -134,7 +134,7 @@
 
   base::Value reload_args(base::Value::Type::LIST);
   reload_args.Append(kReloadCallbackID);
-  handler()->HandleReloadCookies(&base::Value::AsListValue(reload_args));
+  handler()->HandleReloadCookies(reload_args.GetListDeprecated());
   task_environment()->RunUntilIdle();
 
   // At the point the handler will have recreated the model (using the provided
@@ -143,8 +143,7 @@
   base::Value get_display_list_args(base::Value::Type::LIST);
   get_display_list_args.Append(kGetDisplaylistCallbackID);
   get_display_list_args.Append("");
-  handler()->HandleGetDisplayList(
-      &base::Value::AsListValue(get_display_list_args));
+  handler()->HandleGetDisplayList(get_display_list_args.GetListDeprecated());
   task_environment()->RunUntilIdle();
 
   // Because the tree model hasn't completed the batch, no callback should
@@ -189,33 +188,33 @@
         args.Append(callback_id);
         current_filter = current_filter == kTestHost1 ? "" : kTestHost1;
         args.Append(kTestHost1);
-        handler()->HandleGetDisplayList(&base::Value::AsListValue(args));
+        handler()->HandleGetDisplayList(args.GetListDeprecated());
       });
   auto get_display_list_same_filter =
       base::BindLambdaForTesting([&](std::string callback_id) {
         base::Value args(base::Value::Type::LIST);
         args.Append(callback_id);
         args.Append(current_filter);
-        handler()->HandleGetDisplayList(&base::Value::AsListValue(args));
+        handler()->HandleGetDisplayList(args.GetListDeprecated());
       });
   auto get_cookie_details =
       base::BindLambdaForTesting([&](std::string callback_id) {
         base::Value args(base::Value::Type::LIST);
         args.Append(callback_id);
         args.Append(kTestHost1);
-        handler()->HandleGetCookieDetails(&base::Value::AsListValue(args));
+        handler()->HandleGetCookieDetails(args.GetListDeprecated());
       });
   auto reload_cookies =
       base::BindLambdaForTesting([&](std::string callback_id) {
         base::Value args(base::Value::Type::LIST);
         args.Append(callback_id);
-        handler()->HandleReloadCookies(&base::Value::AsListValue(args));
+        handler()->HandleReloadCookies(args.GetListDeprecated());
       });
   auto remove_third_party =
       base::BindLambdaForTesting([&](std::string callback_id) {
         base::Value args(base::Value::Type::LIST);
         args.Append(callback_id);
-        handler()->HandleRemoveThirdParty(&base::Value::AsListValue(args));
+        handler()->HandleRemoveThirdParty(args.GetListDeprecated());
       });
   // Include a dummy request which allows the request queue to be cleared. This
   // ensures that requests may be queued up both during, and outside of, batch
@@ -271,7 +270,7 @@
   base::Value args(base::Value::Type::LIST);
   args.Append(kCallbackId);
   args.Append(kTestHost1);
-  handler()->HandleGetCookieDetails(&base::Value::AsListValue(args));
+  handler()->HandleGetCookieDetails(args.GetListDeprecated());
   task_environment()->RunUntilIdle();
 
   // At this point the handler should have queued the creation of a tree and
@@ -302,7 +301,7 @@
     args.Append(kCallbackId);
     args.Append(kTestHost1);
 
-    handler()->HandleGetDisplayList(&base::Value::AsListValue(args));
+    handler()->HandleGetDisplayList(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -321,7 +320,7 @@
     args.Append(kCallbackId);
     args.Append("");
 
-    handler()->HandleGetDisplayList(&base::Value::AsListValue(args));
+    handler()->HandleGetDisplayList(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -346,7 +345,7 @@
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
     args.Append(kTestHost2);
-    handler()->HandleGetDisplayList(&base::Value::AsListValue(args));
+    handler()->HandleGetDisplayList(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -362,7 +361,7 @@
   // Remove displayed items.
   {
     base::Value args(base::Value::Type::LIST);
-    handler()->HandleRemoveShownItems(&base::Value::AsListValue(args));
+    handler()->HandleRemoveShownItems(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
   }
 
@@ -371,7 +370,7 @@
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
     args.Append("");
-    handler()->HandleGetDisplayList(&base::Value::AsListValue(args));
+    handler()->HandleGetDisplayList(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -391,7 +390,7 @@
   base::Value args(base::Value::Type::LIST);
   args.Append(kCallbackId);
   args.Append(kTestHost1);
-  handler()->HandleGetCookieDetails(&base::Value::AsListValue(args));
+  handler()->HandleGetCookieDetails(args.GetListDeprecated());
   task_environment()->RunUntilIdle();
 
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -411,7 +410,7 @@
   {
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
-    handler()->HandleRemoveAll(&base::Value::AsListValue(args));
+    handler()->HandleRemoveAll(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -425,7 +424,7 @@
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
     args.Append("");
-    handler()->HandleGetDisplayList(&base::Value::AsListValue(args));
+    handler()->HandleGetDisplayList(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -449,7 +448,7 @@
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
     args.Append(kTestHost1);
-    handler()->HandleGetCookieDetails(&base::Value::AsListValue(args));
+    handler()->HandleGetCookieDetails(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -466,7 +465,7 @@
   {
     base::Value args(base::Value::Type::LIST);
     args.Append(node_path_id);
-    handler()->HandleRemoveItem(&base::Value::AsListValue(args));
+    handler()->HandleRemoveItem(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
 
     // Removal should fire an update event.
@@ -481,7 +480,7 @@
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
     args.Append(kTestHost1);
-    handler()->HandleGetCookieDetails(&base::Value::AsListValue(args));
+    handler()->HandleGetCookieDetails(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -498,7 +497,7 @@
   {
     base::Value args(base::Value::Type::LIST);
     args.Append(kTestHost1);
-    handler()->HandleRemoveSite(&base::Value::AsListValue(args));
+    handler()->HandleRemoveSite(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
 
     // Removal should fire an update event.
@@ -512,7 +511,7 @@
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
     args.Append("");
-    handler()->HandleGetDisplayList(&base::Value::AsListValue(args));
+    handler()->HandleGetDisplayList(args.GetListDeprecated());
     task_environment()->RunUntilIdle();
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
diff --git a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
index ec4e24c..a20e998 100644
--- a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
@@ -33,11 +33,11 @@
 DefaultBrowserHandler::~DefaultBrowserHandler() = default;
 
 void DefaultBrowserHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "requestDefaultBrowserState",
       base::BindRepeating(&DefaultBrowserHandler::RequestDefaultBrowserState,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setAsDefaultBrowser",
       base::BindRepeating(&DefaultBrowserHandler::SetAsDefaultBrowser,
                           base::Unretained(this)));
@@ -49,7 +49,8 @@
   local_state_pref_registrar_.Add(
       prefs::kDefaultBrowserSettingEnabled,
       base::BindRepeating(&DefaultBrowserHandler::RequestDefaultBrowserState,
-                          base::Unretained(this), nullptr));
+                          base::Unretained(this),
+                          base::Value::ConstListView()));
   default_browser_worker_ = new shell_integration::DefaultBrowserWorker();
 }
 
@@ -60,18 +61,19 @@
 }
 
 void DefaultBrowserHandler::RequestDefaultBrowserState(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
-  CHECK_EQ(args->GetListDeprecated().size(), 1U);
-  check_default_callback_id_ = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(args.size(), 1U);
+  check_default_callback_id_ = args[0].GetString();
 
   default_browser_worker_->StartCheckIsDefault(
       base::BindOnce(&DefaultBrowserHandler::OnDefaultBrowserWorkerFinished,
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
-void DefaultBrowserHandler::SetAsDefaultBrowser(const base::ListValue* args) {
+void DefaultBrowserHandler::SetAsDefaultBrowser(
+    base::Value::ConstListView args) {
   CHECK(!DefaultBrowserIsDisabledByPolicy());
   AllowJavascript();
   RecordSetAsDefaultUMA();
diff --git a/chrome/browser/ui/webui/settings/settings_default_browser_handler.h b/chrome/browser/ui/webui/settings/settings_default_browser_handler.h
index b572d6e..6e91a128 100644
--- a/chrome/browser/ui/webui/settings/settings_default_browser_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_default_browser_handler.h
@@ -11,10 +11,6 @@
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "components/prefs/pref_change_registrar.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace content {
 class WebUI;
 }
@@ -46,10 +42,10 @@
   std::string check_default_callback_id_;
 
   // Called from WebUI to request the current state.
-  void RequestDefaultBrowserState(const base::ListValue* args);
+  void RequestDefaultBrowserState(base::Value::ConstListView args);
 
   // Makes this the default browser. Called from WebUI.
-  void SetAsDefaultBrowser(const base::ListValue* args);
+  void SetAsDefaultBrowser(base::Value::ConstListView args);
 
   // Called with the default browser state when the DefaultBrowserWorker is
   // done.
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 12b1c0d..dbb4585 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1114,7 +1114,11 @@
       {"searchResultsPlural", IDS_SEARCH_RESULTS_PLURAL},
       {"searchResultsSingular", IDS_SEARCH_RESULTS_SINGULAR},
       {"showPasswordLabel", IDS_SETTINGS_PASSWORD_SHOW_PASSWORD_A11Y},
-      {"hidePasswordLabel", IDS_SETTINGS_PASSWORD_HIDE_PASSWORD_A11Y}};
+      {"hidePasswordLabel", IDS_SETTINGS_PASSWORD_HIDE_PASSWORD_A11Y},
+      {"addVirtualCard", IDS_AUTOFILL_ADD_VIRTUAL_CARD},
+      {"removeVirtualCard", IDS_AUTOFILL_REMOVE_VIRTUAL_CARD},
+      {"editServerCard", IDS_AUTOFILL_EDIT_SERVER_CREDIT_CARD},
+      {"virtualCardEnabled", IDS_AUTOFILL_VIRTUAL_CARD_ENABLED_LABEL}};
 
   GURL google_password_manager_url = GetGooglePasswordManagerURL(
       password_manager::ManagePasswordsReferrer::kChromeSettings);
@@ -1222,6 +1226,14 @@
       base::FeatureList::IsEnabled(
           password_manager::features::kSupportForAddPasswordsInSettings));
 
+  html_source->AddBoolean(
+      "virtualCardEnrollmentEnabled",
+      base::FeatureList::IsEnabled(
+          autofill::features::kAutofillEnableUpdateVirtualCardEnrollment) &&
+          base::FeatureList::IsEnabled(
+              autofill::features::
+                  kAutofillEnableVirtualCardManagementInDesktopSettingsPage));
+
   html_source->AddLocalizedStrings(kLocalizedStrings);
 }
 
diff --git a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
index 7a7a7f18..e0fbbfc3 100644
--- a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
@@ -53,34 +53,34 @@
 ManageProfileHandler::~ManageProfileHandler() {}
 
 void ManageProfileHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getAvailableIcons",
       base::BindRepeating(&ManageProfileHandler::HandleGetAvailableIcons,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setProfileIconToGaiaAvatar",
       base::BindRepeating(
           &ManageProfileHandler::HandleSetProfileIconToGaiaAvatar,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setProfileIconToDefaultAvatar",
       base::BindRepeating(
           &ManageProfileHandler::HandleSetProfileIconToDefaultAvatar,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setProfileName",
       base::BindRepeating(&ManageProfileHandler::HandleSetProfileName,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "requestProfileShortcutStatus",
       base::BindRepeating(
           &ManageProfileHandler::HandleRequestProfileShortcutStatus,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "addProfileShortcut",
       base::BindRepeating(&ManageProfileHandler::HandleAddProfileShortcut,
                           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "removeProfileShortcut",
       base::BindRepeating(&ManageProfileHandler::HandleRemoveProfileShortcut,
                           base::Unretained(this)));
@@ -124,13 +124,13 @@
 }
 
 void ManageProfileHandler::HandleGetAvailableIcons(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
   profiles::UpdateGaiaProfileInfoIfNeeded(profile_);
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+  CHECK_EQ(1U, args.size());
+  const base::Value& callback_id = args[0];
 
   ResolveJavascriptCallback(callback_id, base::Value(GetAvailableIcons()));
 }
@@ -181,7 +181,7 @@
 }
 
 void ManageProfileHandler::HandleSetProfileIconToGaiaAvatar(
-    const base::ListValue* /* args */) {
+    base::Value::ConstListView args) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   PrefService* pref_service = profile_->GetPrefs();
@@ -201,13 +201,12 @@
 }
 
 void ManageProfileHandler::HandleSetProfileIconToDefaultAvatar(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  CHECK(args);
-  CHECK_EQ(1u, args->GetListDeprecated().size());
-  CHECK(args->GetListDeprecated()[0].is_int());
+  CHECK_EQ(1u, args.size());
+  CHECK(args[0].is_int());
 
-  size_t new_icon_index = args->GetListDeprecated()[0].GetInt();
+  size_t new_icon_index = args[0].GetInt();
   CHECK(profiles::IsDefaultAvatarIconIndex(new_icon_index));
 
   PrefService* pref_service = profile_->GetPrefs();
@@ -221,13 +220,12 @@
   ProfileMetrics::LogProfileUpdate(profile_->GetPath());
 }
 
-void ManageProfileHandler::HandleSetProfileName(const base::ListValue* args) {
+void ManageProfileHandler::HandleSetProfileName(
+    base::Value::ConstListView args) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  CHECK(args);
-  CHECK_EQ(1u, args->GetListDeprecated().size());
+  CHECK_EQ(1u, args.size());
 
-  std::u16string new_profile_name =
-      base::UTF8ToUTF16(args->GetListDeprecated()[0].GetString());
+  std::u16string new_profile_name = base::UTF8ToUTF16(args[0].GetString());
 
   base::TrimWhitespace(new_profile_name, base::TRIM_ALL, &new_profile_name);
   CHECK(!new_profile_name.empty());
@@ -237,13 +235,13 @@
 }
 
 void ManageProfileHandler::HandleRequestProfileShortcutStatus(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(ProfileShortcutManager::IsFeatureEnabled());
 
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const std::string& callback_id = args->GetListDeprecated()[0].GetString();
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
 
   // Don't show the add/remove desktop shortcut button in the single user case.
   ProfileAttributesStorage& storage =
@@ -273,7 +271,7 @@
 }
 
 void ManageProfileHandler::HandleAddProfileShortcut(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   DCHECK(ProfileShortcutManager::IsFeatureEnabled());
   ProfileShortcutManager* shortcut_manager =
       g_browser_process->profile_manager()->profile_shortcut_manager();
@@ -283,7 +281,7 @@
 }
 
 void ManageProfileHandler::HandleRemoveProfileShortcut(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   DCHECK(ProfileShortcutManager::IsFeatureEnabled());
   ProfileShortcutManager* shortcut_manager =
     g_browser_process->profile_manager()->profile_shortcut_manager();
diff --git a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.h b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.h
index 4a9d7aa5..50d6493f 100644
--- a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.h
@@ -59,24 +59,24 @@
 
   // Callback for the "getAvailableIcons" message.
   // Sends the array of default profile icon URLs and profile names to WebUI.
-  void HandleGetAvailableIcons(const base::ListValue* args);
+  void HandleGetAvailableIcons(base::Value::ConstListView args);
 
   // Get all the available profile icons to choose from.
   std::vector<base::Value> GetAvailableIcons();
 
   // Callback for the "setProfileIconToGaiaAvatar" message.
-  void HandleSetProfileIconToGaiaAvatar(const base::ListValue* args);
+  void HandleSetProfileIconToGaiaAvatar(base::Value::ConstListView args);
 
   // Callback for the "setProfileIconToDefaultAvatar" message.
-  void HandleSetProfileIconToDefaultAvatar(const base::ListValue* args);
+  void HandleSetProfileIconToDefaultAvatar(base::Value::ConstListView args);
 
   // Callback for the "setProfileName" message.
-  void HandleSetProfileName(const base::ListValue* args);
+  void HandleSetProfileName(base::Value::ConstListView args);
 
   // Callback for the "requestProfileShortcutStatus" message, which is called
   // when editing an existing profile. Asks the profile shortcut manager whether
   // the profile has shortcuts and gets the result in |OnHasProfileShortcuts()|.
-  void HandleRequestProfileShortcutStatus(const base::ListValue* args);
+  void HandleRequestProfileShortcutStatus(base::Value::ConstListView args);
 
   // Callback invoked from the profile manager indicating whether the profile
   // being edited has any desktop shortcuts.
@@ -86,12 +86,12 @@
   // Callback for the "addProfileShortcut" message, which is called when editing
   // an existing profile and the user clicks the "Add desktop shortcut" button.
   // Adds a desktop shortcut for the profile.
-  void HandleAddProfileShortcut(const base::ListValue* args);
+  void HandleAddProfileShortcut(base::Value::ConstListView args);
 
   // Callback for the "removeProfileShortcut" message, which is called when
   // editing an existing profile and the user clicks the "Remove desktop
   // shortcut" button. Removes the desktop shortcut for the profile.
-  void HandleRemoveProfileShortcut(const base::ListValue* args);
+  void HandleRemoveProfileShortcut(base::Value::ConstListView args);
 
   // Non-owning pointer to the associated profile.
   raw_ptr<Profile> profile_;
diff --git a/chrome/browser/ui/webui/settings/settings_manage_profile_handler_unittest.cc b/chrome/browser/ui/webui/settings/settings_manage_profile_handler_unittest.cc
index cd71b5cb..7b612c6f 100644
--- a/chrome/browser/ui/webui/settings/settings_manage_profile_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/settings_manage_profile_handler_unittest.cc
@@ -159,7 +159,7 @@
 };
 
 TEST_F(ManageProfileHandlerTest, HandleSetProfileIconToGaiaAvatar) {
-  handler()->HandleSetProfileIconToGaiaAvatar(nullptr);
+  handler()->HandleSetProfileIconToGaiaAvatar(base::Value::ConstListView());
 
   PrefService* pref_service = profile()->GetPrefs();
   EXPECT_FALSE(pref_service->GetBoolean(prefs::kProfileUsingDefaultAvatar));
@@ -169,8 +169,7 @@
 TEST_F(ManageProfileHandlerTest, HandleSetProfileIconToDefaultCustomAvatar) {
   base::Value list_args(base::Value::Type::LIST);
   list_args.Append(15);
-  handler()->HandleSetProfileIconToDefaultAvatar(
-      &base::Value::AsListValue(list_args));
+  handler()->HandleSetProfileIconToDefaultAvatar(list_args.GetListDeprecated());
 
   PrefService* pref_service = profile()->GetPrefs();
   EXPECT_EQ(15, pref_service->GetInteger(prefs::kProfileAvatarIndex));
@@ -182,8 +181,7 @@
   int generic_avatar_index = profiles::GetPlaceholderAvatarIndex();
   base::Value list_args(base::Value::Type::LIST);
   list_args.Append(generic_avatar_index);
-  handler()->HandleSetProfileIconToDefaultAvatar(
-      &base::Value::AsListValue(list_args));
+  handler()->HandleSetProfileIconToDefaultAvatar(list_args.GetListDeprecated());
 
   PrefService* pref_service = profile()->GetPrefs();
   EXPECT_EQ(generic_avatar_index,
@@ -195,7 +193,7 @@
 TEST_F(ManageProfileHandlerTest, HandleSetProfileName) {
   base::Value list_args(base::Value::Type::LIST);
   list_args.Append("New Profile Name");
-  handler()->HandleSetProfileName(&base::Value::AsListValue(list_args));
+  handler()->HandleSetProfileName(list_args.GetListDeprecated());
 
   PrefService* pref_service = profile()->GetPrefs();
   EXPECT_EQ("New Profile Name", pref_service->GetString(prefs::kProfileName));
@@ -210,7 +208,7 @@
 
   base::Value list_args_1(base::Value::Type::LIST);
   list_args_1.Append("get-icons-callback-id");
-  handler()->HandleGetAvailableIcons(&base::Value::AsListValue(list_args_1));
+  handler()->HandleGetAvailableIcons(list_args_1.GetListDeprecated());
 
   EXPECT_EQ(1U, web_ui()->call_data().size());
 
@@ -229,7 +227,7 @@
 
   base::Value list_args(base::Value::Type::LIST);
   list_args.Append("get-icons-callback-id");
-  handler()->HandleGetAvailableIcons(&base::Value::AsListValue(list_args));
+  handler()->HandleGetAvailableIcons(list_args.GetListDeprecated());
 
   EXPECT_EQ(1U, web_ui()->call_data().size());
 
@@ -248,7 +246,7 @@
 
   base::Value list_args(base::Value::Type::LIST);
   list_args.Append("get-icons-callback-id");
-  handler()->HandleGetAvailableIcons(&base::Value::AsListValue(list_args));
+  handler()->HandleGetAvailableIcons(list_args.GetListDeprecated());
 
   EXPECT_EQ(1U, web_ui()->call_data().size());
 
@@ -294,7 +292,7 @@
 
   base::Value list_args(base::Value::Type::LIST);
   list_args.Append("get-icons-callback-id");
-  handler()->HandleGetAvailableIcons(&base::Value::AsListValue(list_args));
+  handler()->HandleGetAvailableIcons(list_args.GetListDeprecated());
 
   EXPECT_EQ(1U, web_ui()->call_data().size());
 
diff --git a/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.cc b/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.cc
index deed13fa..642b75a4 100644
--- a/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.cc
@@ -44,12 +44,12 @@
 }
 
 void MediaDevicesSelectionHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getDefaultCaptureDevices",
       base::BindRepeating(
           &MediaDevicesSelectionHandler::GetDefaultCaptureDevices,
           base::Unretained(this)));
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "setDefaultCaptureDevice",
       base::BindRepeating(
           &MediaDevicesSelectionHandler::SetDefaultCaptureDevice,
@@ -67,13 +67,13 @@
 }
 
 void MediaDevicesSelectionHandler::GetDefaultCaptureDevices(
-    const base::ListValue* args) {
-  DCHECK_EQ(1U, args->GetListDeprecated().size());
-  if (!args->GetListDeprecated()[0].is_string()) {
+    base::Value::ConstListView args) {
+  DCHECK_EQ(1U, args.size());
+  if (!args[0].is_string()) {
     NOTREACHED();
     return;
   }
-  const std::string& type = args->GetListDeprecated()[0].GetString();
+  const std::string& type = args[0].GetString();
   DCHECK(!type.empty());
 
   if (type == kAudio)
@@ -83,15 +83,14 @@
 }
 
 void MediaDevicesSelectionHandler::SetDefaultCaptureDevice(
-    const base::ListValue* args) {
-  DCHECK_EQ(2U, args->GetListDeprecated().size());
-  if (!args->GetListDeprecated()[0].is_string() ||
-      !args->GetListDeprecated()[1].is_string()) {
+    base::Value::ConstListView args) {
+  DCHECK_EQ(2U, args.size());
+  if (!args[0].is_string() || !args[1].is_string()) {
     NOTREACHED();
     return;
   }
-  const std::string& type = args->GetListDeprecated()[0].GetString();
-  const std::string& device = args->GetListDeprecated()[1].GetString();
+  const std::string& type = args[0].GetString();
+  const std::string& device = args[1].GetString();
 
   DCHECK(!type.empty());
   DCHECK(!device.empty());
diff --git a/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.h b/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.h
index a54c5f0..28d5540 100644
--- a/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.h
@@ -42,12 +42,12 @@
   };
 
   // Fetches the list of default capture devices.
-  void GetDefaultCaptureDevices(const base::ListValue* args);
+  void GetDefaultCaptureDevices(base::Value::ConstListView args);
 
   // Sets the default audio/video capture device for media. |args| includes the
   // media type (kAuudio/kVideo) and the unique id of the new default device
   // that the user has chosen.
-  void SetDefaultCaptureDevice(const base::ListValue* args);
+  void SetDefaultCaptureDevice(base::Value::ConstListView args);
 
   // Helpers methods to update the device menus.
   void UpdateDevicesMenuForType(DeviceType type);
diff --git a/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc b/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc
index f56110a8..14443cb 100644
--- a/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc
@@ -62,26 +62,26 @@
 SecureDnsHandler::~SecureDnsHandler() = default;
 
 void SecureDnsHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getSecureDnsResolverList",
       base::BindRepeating(&SecureDnsHandler::HandleGetSecureDnsResolverList,
                           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getSecureDnsSetting",
       base::BindRepeating(&SecureDnsHandler::HandleGetSecureDnsSetting,
                           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "isValidConfig",
       base::BindRepeating(&SecureDnsHandler::HandleIsValidConfig,
                           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "probeConfig", base::BindRepeating(&SecureDnsHandler::HandleProbeConfig,
                                          base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "recordUserDropdownInteraction",
       base::BindRepeating(
           &SecureDnsHandler::HandleRecordUserDropdownInteraction,
@@ -156,32 +156,33 @@
 }
 
 void SecureDnsHandler::HandleGetSecureDnsResolverList(
-    const base::ListValue* args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
-  std::string callback_id = args->GetListDeprecated()[0].GetString();
+  std::string callback_id = args[0].GetString();
 
   ResolveJavascriptCallback(base::Value(callback_id),
                             GetSecureDnsResolverList());
 }
 
-void SecureDnsHandler::HandleGetSecureDnsSetting(const base::ListValue* args) {
+void SecureDnsHandler::HandleGetSecureDnsSetting(
+    base::Value::ConstListView args) {
   AllowJavascript();
-  CHECK_EQ(1u, args->GetListDeprecated().size());
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+  CHECK_EQ(1u, args.size());
+  const base::Value& callback_id = args[0];
   ResolveJavascriptCallback(callback_id, *CreateSecureDnsSettingDict());
 }
 
-void SecureDnsHandler::HandleIsValidConfig(const base::ListValue* args) {
+void SecureDnsHandler::HandleIsValidConfig(base::Value::ConstListView args) {
   AllowJavascript();
-  const base::Value& callback_id = args->GetListDeprecated()[0];
-  const std::string& custom_entry = args->GetListDeprecated()[1].GetString();
+  const base::Value& callback_id = args[0];
+  const std::string& custom_entry = args[1].GetString();
 
   bool valid = net::DnsOverHttpsConfig::FromString(custom_entry).has_value();
   secure_dns::UpdateValidationHistogram(valid);
   ResolveJavascriptCallback(callback_id, base::Value(valid));
 }
 
-void SecureDnsHandler::HandleProbeConfig(const base::ListValue* args) {
+void SecureDnsHandler::HandleProbeConfig(base::Value::ConstListView args) {
   AllowJavascript();
 
   if (!probe_callback_id_.empty()) {
@@ -193,9 +194,8 @@
                               base::Value(true));
   }
 
-  probe_callback_id_ = args->GetListDeprecated()[0].GetString();
-  const std::string& server_templates =
-      args->GetListDeprecated()[1].GetString();
+  probe_callback_id_ = args[0].GetString();
+  const std::string& server_templates = args[1].GetString();
 
   net::DnsConfigOverrides overrides;
   overrides.search = std::vector<std::string>();
@@ -210,10 +210,10 @@
 }
 
 void SecureDnsHandler::HandleRecordUserDropdownInteraction(
-    const base::ListValue* args) {
-  CHECK_EQ(2U, args->GetListDeprecated().size());
-  const std::string& old_provider = args->GetListDeprecated()[0].GetString();
-  const std::string& new_provider = args->GetListDeprecated()[1].GetString();
+    base::Value::ConstListView args) {
+  CHECK_EQ(2U, args.size());
+  const std::string& old_provider = args[0].GetString();
+  const std::string& new_provider = args[1].GetString();
 
   secure_dns::UpdateDropdownHistograms(providers_, old_provider, new_provider);
 }
diff --git a/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h b/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h
index de041fc..36dc0ba 100644
--- a/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h
@@ -50,19 +50,19 @@
 
  protected:
   // Retrieves all pre-approved secure resolvers and returns them to WebUI.
-  void HandleGetSecureDnsResolverList(const base::ListValue* args);
+  void HandleGetSecureDnsResolverList(base::Value::ConstListView args);
 
   // Intended to be called once upon creation of the secure DNS setting.
-  void HandleGetSecureDnsSetting(const base::ListValue* args);
+  void HandleGetSecureDnsSetting(base::Value::ConstListView args);
 
   // Parses a custom entry and returns true if it is a fully valid config.
-  void HandleIsValidConfig(const base::ListValue* args);
+  void HandleIsValidConfig(base::Value::ConstListView args);
 
   // Returns whether or not a test query succeeds with the provided config.
-  void HandleProbeConfig(const base::ListValue* args);
+  void HandleProbeConfig(base::Value::ConstListView args);
 
   // Records metrics on the user-initiated dropdown selection event.
-  void HandleRecordUserDropdownInteraction(const base::ListValue* args);
+  void HandleRecordUserDropdownInteraction(base::Value::ConstListView args);
 
   // Retrieves the current host resolver configuration, computes the
   // corresponding UI representation, and sends it to javascript.
diff --git a/chrome/browser/ui/webui/settings/settings_security_key_handler.cc b/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
index 0c0f3282..7e5b82ae 100644
--- a/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
@@ -423,7 +423,7 @@
   state_ = State::kDeletingCredentials;
   callback_id_ = args[0].GetString();
   std::vector<device::PublicKeyCredentialDescriptor> credential_ids;
-  for (const base::Value& el : args[1].GetList()) {
+  for (const base::Value& el : args[1].GetListDeprecated()) {
     std::vector<uint8_t> credential_id_bytes;
     if (!base::HexStringToBytes(el.GetString(), &credential_id_bytes)) {
       NOTREACHED();
diff --git a/chrome/browser/ui/webui/settings/settings_security_key_handler_unittest.cc b/chrome/browser/ui/webui/settings/settings_security_key_handler_unittest.cc
index 2124042..b7a8c699 100644
--- a/chrome/browser/ui/webui/settings/settings_security_key_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/settings_security_key_handler_unittest.cc
@@ -59,7 +59,7 @@
     constexpr char kCallbackId[] = "securityKeyCredentialManagementStart";
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
-    HandleStart(args.GetList());
+    HandleStart(args.GetListDeprecated());
     base::RunLoop().RunUntilIdle();
     return kCallbackId;
   }
@@ -71,7 +71,7 @@
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
     args.Append(kTestPIN);
-    HandlePIN(args.GetList());
+    HandlePIN(args.GetListDeprecated());
     base::RunLoop().RunUntilIdle();
     return kCallbackId;
   }
@@ -100,7 +100,7 @@
     constexpr char kCallbackId[] = "bioEnrollStart";
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
-    HandleStart(args.GetList());
+    HandleStart(args.GetListDeprecated());
     base::RunLoop().RunUntilIdle();
     return kCallbackId;
   }
@@ -112,7 +112,7 @@
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
     args.Append(kTestPIN);
-    HandleProvidePIN(args.GetList());
+    HandleProvidePIN(args.GetListDeprecated());
     base::RunLoop().RunUntilIdle();
     return kCallbackId;
   }
@@ -123,7 +123,7 @@
     constexpr char kCallbackId[] = "bioEnrollStartEnrolling";
     base::Value args(base::Value::Type::LIST);
     args.Append(kCallbackId);
-    HandleStartEnrolling(args.GetList());
+    HandleStartEnrolling(args.GetListDeprecated());
     base::RunLoop().RunUntilIdle();
     return kCallbackId;
   }
@@ -212,7 +212,7 @@
   EXPECT_TRUE(*response->FindBoolKey("supportsUpdateUserInformation"));
 
   handler_->SimulateProvidePIN();
-  handler_->HandleUpdateUserInformation(args.GetList());
+  handler_->HandleUpdateUserInformation(args.GetListDeprecated());
   base::RunLoop().RunUntilIdle();
 
   device::PublicKeyCredentialUserEntity updated_user(
@@ -241,7 +241,7 @@
   std::string callback_id("start_callback_id");
   base::Value args(base::Value::Type::LIST);
   args.Append(callback_id);
-  handler_->HandleStart(args.GetList());
+  handler_->HandleStart(args.GetListDeprecated());
   base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(web_ui_->call_data()[0]->arg1()->GetString(),
diff --git a/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc b/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc
index cf09b4b8..7f828cf 100644
--- a/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc
@@ -105,7 +105,7 @@
 }
 
 void StartupPagesHandler::HandleAddStartupPage(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   CHECK_EQ(2U, args.size());
 
   const base::Value& callback_id = args[0];
@@ -128,7 +128,7 @@
 }
 
 void StartupPagesHandler::HandleEditStartupPage(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   CHECK_EQ(args.size(), 3U);
   const base::Value& callback_id = args[0];
   int index = args[1].GetInt();
@@ -154,12 +154,12 @@
 }
 
 void StartupPagesHandler::HandleOnStartupPrefsPageLoad(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 }
 
 void StartupPagesHandler::HandleRemoveStartupPage(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   DCHECK_GE(args.size(), 1u);
   if (!args[0].is_int()) {
     NOTREACHED();
@@ -178,7 +178,7 @@
 }
 
 void StartupPagesHandler::HandleSetStartupPagesToCurrentPages(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   startup_custom_pages_table_model_.SetToCurrentlyOpenPages(
       web_ui()->GetWebContents());
   SaveStartupPagesPref();
diff --git a/chrome/browser/ui/webui/settings/settings_startup_pages_handler.h b/chrome/browser/ui/webui/settings/settings_startup_pages_handler.h
index 69a76c13..8492863 100644
--- a/chrome/browser/ui/webui/settings/settings_startup_pages_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_startup_pages_handler.h
@@ -40,20 +40,19 @@
 
  private:
   // Adds a startup page with the given URL after the given index.
-  void HandleAddStartupPage(const base::Value::ConstListView args);
+  void HandleAddStartupPage(base::Value::ConstListView args);
 
   // Changes the startup page at the given index to the given URL.
-  void HandleEditStartupPage(const base::Value::ConstListView args);
+  void HandleEditStartupPage(base::Value::ConstListView args);
 
   // Informs the code that the JS page has loaded.
-  void HandleOnStartupPrefsPageLoad(const base::Value::ConstListView args);
+  void HandleOnStartupPrefsPageLoad(base::Value::ConstListView args);
 
   // Removes the startup page at the given index.
-  void HandleRemoveStartupPage(const base::Value::ConstListView args);
+  void HandleRemoveStartupPage(base::Value::ConstListView args);
 
   // Sets the startup page set to the current pages.
-  void HandleSetStartupPagesToCurrentPages(
-      const base::Value::ConstListView args);
+  void HandleSetStartupPagesToCurrentPages(base::Value::ConstListView args);
 
   // Stores the current state of the startup page preferences.
   void SaveStartupPagesPref();
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc
index 0b49c266e..20cc078 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -782,7 +782,7 @@
 }
 
 void SiteSettingsHandler::HandleFetchUsageTotal(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   CHECK_EQ(1U, args.size());
   usage_host_ = args[0].GetString();
@@ -797,7 +797,7 @@
 }
 
 void SiteSettingsHandler::HandleClearUnpartitionedUsage(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   CHECK_EQ(1U, args.size());
   const std::string& origin_string = args[0].GetString();
   auto origin = url::Origin::Create(GURL(origin_string));
@@ -811,7 +811,7 @@
 }
 
 void SiteSettingsHandler::HandleClearPartitionedUsage(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   CHECK_EQ(2U, args.size());
   const std::string& origin = args[0].GetString();
   const std::string& etld_plus1 = args[1].GetString();
@@ -820,7 +820,7 @@
 }
 
 void SiteSettingsHandler::HandleSetDefaultValueForContentType(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   CHECK_EQ(2U, args.size());
   const std::string& content_type = args[0].GetString();
   const std::string& setting = args[1].GetString();
@@ -855,7 +855,7 @@
 }
 
 void SiteSettingsHandler::HandleGetDefaultValueForContentType(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
   CHECK_EQ(2U, args.size());
@@ -872,8 +872,7 @@
   ResolveJavascriptCallback(callback_id, category);
 }
 
-void SiteSettingsHandler::HandleGetAllSites(
-    const base::Value::ConstListView args) {
+void SiteSettingsHandler::HandleGetAllSites(base::Value::ConstListView args) {
   AllowJavascript();
 
   CHECK_EQ(1U, args.size());
@@ -942,7 +941,7 @@
 }
 
 void SiteSettingsHandler::HandleGetCategoryList(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
   CHECK_EQ(2U, args.size());
@@ -959,7 +958,7 @@
 }
 
 void SiteSettingsHandler::HandleGetCookieSettingDescription(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   CHECK_EQ(1U, args.size());
   std::string callback_id = args[0].GetString();
@@ -968,7 +967,7 @@
 }
 
 void SiteSettingsHandler::HandleGetRecentSitePermissions(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
   CHECK_EQ(2U, args.size());
@@ -1073,7 +1072,7 @@
 }
 
 void SiteSettingsHandler::HandleGetFormattedBytes(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   CHECK_EQ(2U, args.size());
   int64_t num_bytes = static_cast<int64_t>(args[1].GetDouble());
@@ -1082,7 +1081,7 @@
 }
 
 void SiteSettingsHandler::HandleGetExceptionList(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
   CHECK_EQ(2U, args.size());
@@ -1117,7 +1116,7 @@
 }
 
 void SiteSettingsHandler::HandleGetChooserExceptionList(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
   CHECK_EQ(2U, args.size());
@@ -1133,13 +1132,13 @@
 }
 
 void SiteSettingsHandler::HandleGetOriginPermissions(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
   CHECK_EQ(3U, args.size());
   const base::Value& callback_id = args[0];
   std::string origin = args[1].GetString();
-  base::Value::ConstListView types = args[2].GetList();
+  base::Value::ConstListView types = args[2].GetListDeprecated();
 
   // Note: Invalid URLs will just result in default settings being shown.
   const GURL origin_url(origin);
@@ -1181,7 +1180,7 @@
 }
 
 void SiteSettingsHandler::HandleSetOriginPermissions(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   CHECK_EQ(3U, args.size());
   std::string origin_string = args[0].GetString();
   const std::string* type_string = args[1].GetIfString();
@@ -1249,7 +1248,7 @@
 }
 
 void SiteSettingsHandler::HandleResetCategoryPermissionForPattern(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   CHECK_EQ(4U, args.size());
   const std::string& primary_pattern_string = args[0].GetString();
   const std::string& secondary_pattern_string = args[1].GetString();
@@ -1309,7 +1308,7 @@
 }
 
 void SiteSettingsHandler::HandleSetCategoryPermissionForPattern(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   CHECK_EQ(5U, args.size());
   const std::string& primary_pattern_string = args[0].GetString();
   const std::string& secondary_pattern_string = args[1].GetString();
@@ -1376,7 +1375,7 @@
 }
 
 void SiteSettingsHandler::HandleResetChooserExceptionForSite(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   CHECK_EQ(4U, args.size());
 
   const std::string& chooser_type_str = args[0].GetString();
@@ -1398,8 +1397,7 @@
                                           args[3]);
 }
 
-void SiteSettingsHandler::HandleIsOriginValid(
-    const base::Value::ConstListView args) {
+void SiteSettingsHandler::HandleIsOriginValid(base::Value::ConstListView args) {
   AllowJavascript();
   CHECK_EQ(2U, args.size());
   const base::Value& callback_id = args[0];
@@ -1410,7 +1408,7 @@
 }
 
 void SiteSettingsHandler::HandleIsPatternValidForType(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   CHECK_EQ(3U, args.size());
   const base::Value& callback_id = args[0];
@@ -1428,14 +1426,14 @@
 }
 
 void SiteSettingsHandler::HandleUpdateIncognitoStatus(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   FireWebUIListener("onIncognitoStatusChanged",
                     base::Value(profile_->HasPrimaryOTRProfile()));
 }
 
 void SiteSettingsHandler::HandleFetchZoomLevels(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   SendZoomLevels();
 }
@@ -1519,7 +1517,7 @@
 }
 
 void SiteSettingsHandler::HandleRemoveZoomLevel(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   CHECK_EQ(1U, args.size());
 
   std::string origin = args[0].GetString();
@@ -1536,7 +1534,7 @@
 }
 
 void SiteSettingsHandler::HandleFetchBlockAutoplayStatus(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
   SendBlockAutoplayStatus();
 }
@@ -1566,7 +1564,7 @@
 }
 
 void SiteSettingsHandler::HandleSetBlockAutoplayEnabled(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   AllowJavascript();
 
   if (!UnifiedAutoplayConfig::IsBlockAutoplayUserModifiable(profile_))
@@ -1728,7 +1726,7 @@
 }
 
 void SiteSettingsHandler::HandleClearEtldPlus1DataAndCookies(
-    const base::Value::ConstListView args) {
+    base::Value::ConstListView args) {
   CHECK_EQ(1U, args.size());
   const std::string& etld_plus1 = args[0].GetString();
 
@@ -1759,10 +1757,10 @@
   RemoveNonTreeModelData(affected_origins);
 }
 
-void SiteSettingsHandler::HandleRecordAction(
-    const base::Value::ConstListView args) {
-  CHECK_EQ(1U, args.size());
-  int action = args[0].GetInt();
+void SiteSettingsHandler::HandleRecordAction(base::Value::ConstListView args) {
+  const auto& list = args;
+  CHECK_EQ(1U, list.size());
+  int action = list[0].GetInt();
   DCHECK_LE(action, static_cast<int>(AllSitesAction2::kMaxValue));
   DCHECK_GE(action, static_cast<int>(AllSitesAction2::kLoadPage));
 
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.h b/chrome/browser/ui/webui/settings/site_settings_handler.h
index d9d139de..622d2a1 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler.h
+++ b/chrome/browser/ui/webui/settings/site_settings_handler.h
@@ -163,40 +163,38 @@
 
   // Asynchronously fetches the usage for a given origin. Replies back with
   // OnGetUsageInfo above.
-  void HandleFetchUsageTotal(const base::Value::ConstListView args);
+  void HandleFetchUsageTotal(base::Value::ConstListView args);
 
   // Deletes the storage being used for a given host.
-  void HandleClearUnpartitionedUsage(const base::Value::ConstListView args);
+  void HandleClearUnpartitionedUsage(base::Value::ConstListView args);
 
-  void HandleClearPartitionedUsage(const base::Value::ConstListView args);
+  void HandleClearPartitionedUsage(base::Value::ConstListView args);
 
   // Gets and sets the default value for a particular content settings type.
-  void HandleSetDefaultValueForContentType(
-      const base::Value::ConstListView args);
-  void HandleGetDefaultValueForContentType(
-      const base::Value::ConstListView args);
+  void HandleSetDefaultValueForContentType(base::Value::ConstListView args);
+  void HandleGetDefaultValueForContentType(base::Value::ConstListView args);
 
   // Returns a list of sites with permissions settings, grouped by their
   // eTLD+1. Recreates the cookies tree model to fetch the cookie and usage
   // data, which will send the list of sites with cookies or usage data to
   // the front end when fetching finished.
-  void HandleGetAllSites(const base::Value::ConstListView args);
+  void HandleGetAllSites(base::Value::ConstListView args);
 
   // Returns a list of content settings types that are controlled via a standard
   // permissions UI and should be made visible to the user. There is a single
   // nullable string argument, which represents an associated origin. See
   // `SiteSettingsPrefsBrowserProxy#getCategoryList`.
-  void HandleGetCategoryList(const base::Value::ConstListView args);
+  void HandleGetCategoryList(base::Value::ConstListView args);
 
   // Returns a string for display describing the current cookie settings.
-  void HandleGetCookieSettingDescription(const base::Value::ConstListView args);
+  void HandleGetCookieSettingDescription(base::Value::ConstListView args);
 
   // Returns a list containing the most recent permission changes for the
   // content types that are visiblein settings, grouped by origin/profile
   // (incognito, regular) combinations, limited to N origin/profile pairings.
   // This includes permission changes made by embargo, but does not include
   // permissions enforced via policy.
-  void HandleGetRecentSitePermissions(const base::Value::ConstListView args);
+  void HandleGetRecentSitePermissions(base::Value::ConstListView args);
 
   // Called when the list of origins using storage has been fetched, and sends
   // this list back to the front end.
@@ -209,69 +207,65 @@
 
   // Converts a given number of bytes into a human-readable format, with data
   // units.
-  void HandleGetFormattedBytes(const base::Value::ConstListView args);
+  void HandleGetFormattedBytes(base::Value::ConstListView args);
 
   // Returns the list of site exceptions for a given content settings type.
-  void HandleGetExceptionList(const base::Value::ConstListView args);
+  void HandleGetExceptionList(base::Value::ConstListView args);
 
   // Returns the list of chooser exceptions for a given chooser type.
-  void HandleGetChooserExceptionList(const base::Value::ConstListView args);
+  void HandleGetChooserExceptionList(base::Value::ConstListView args);
 
   // Gets and sets a list of ContentSettingTypes for an origin.
   // TODO(https://crbug.com/739241): Investigate replacing the
   // '*CategoryPermissionForPattern' equivalents below with these methods.
-  void HandleGetOriginPermissions(const base::Value::ConstListView args);
-  void HandleSetOriginPermissions(const base::Value::ConstListView args);
+  void HandleGetOriginPermissions(base::Value::ConstListView args);
+  void HandleSetOriginPermissions(base::Value::ConstListView args);
 
   // Handles setting and resetting an origin permission.
-  void HandleResetCategoryPermissionForPattern(
-      const base::Value::ConstListView args);
-  void HandleSetCategoryPermissionForPattern(
-      const base::Value::ConstListView args);
+  void HandleResetCategoryPermissionForPattern(base::Value::ConstListView args);
+  void HandleSetCategoryPermissionForPattern(base::Value::ConstListView args);
 
   // TODO(andypaicu, crbug.com/880684): Update to only expect a list of three
   // arguments, replacing the current (requesting,embedding) arguments with
   // simply (origin) and update all call sites.
   // Handles resetting a chooser exception for the given site.
-  void HandleResetChooserExceptionForSite(
-      const base::Value::ConstListView args);
+  void HandleResetChooserExceptionForSite(base::Value::ConstListView args);
 
   // Returns whether a given string is a valid origin.
-  void HandleIsOriginValid(const base::Value::ConstListView args);
+  void HandleIsOriginValid(base::Value::ConstListView args);
 
   // Returns whether the pattern is valid given the type.
-  void HandleIsPatternValidForType(const base::Value::ConstListView args);
+  void HandleIsPatternValidForType(base::Value::ConstListView args);
 
   // Looks up whether an incognito session is active.
-  void HandleUpdateIncognitoStatus(const base::Value::ConstListView args);
+  void HandleUpdateIncognitoStatus(base::Value::ConstListView args);
 
   // Notifies the JS side whether incognito is enabled.
   void SendIncognitoStatus(Profile* profile, bool was_destroyed);
 
   // Handles the request for a list of all zoom levels.
-  void HandleFetchZoomLevels(const base::Value::ConstListView args);
+  void HandleFetchZoomLevels(base::Value::ConstListView args);
 
   // Sends the zoom level list down to the web ui.
   void SendZoomLevels();
 
   // Removes a particular zoom level for a given host.
-  void HandleRemoveZoomLevel(const base::Value::ConstListView args);
+  void HandleRemoveZoomLevel(base::Value::ConstListView args);
 
   // Handles the request to send block autoplay state.
-  void HandleFetchBlockAutoplayStatus(const base::Value::ConstListView args);
+  void HandleFetchBlockAutoplayStatus(base::Value::ConstListView args);
 
   // Notifies the JS side about the state of the block autoplay toggle.
   void SendBlockAutoplayStatus();
 
   // Updates the block autoplay enabled pref when the UI is toggled.
-  void HandleSetBlockAutoplayEnabled(const base::Value::ConstListView args);
+  void HandleSetBlockAutoplayEnabled(base::Value::ConstListView args);
 
   // Clear web storage data and cookies from cookies tree model for an ETLD+1.
-  void HandleClearEtldPlus1DataAndCookies(
-      const base::Value::ConstListView args);
+  void HandleClearEtldPlus1DataAndCookies(base::Value::ConstListView args);
 
   // Record metrics for actions on All Sites Page.
-  void HandleRecordAction(const base::Value::ConstListView args);
+  void HandleRecordAction(base::Value::ConstListView args);
 
   // Provides an opportunity for site data which is not integrated into the
   // tree model to be removed when entries for |origins| are removed.
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
index 4c40624..6ff44ae4 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -578,7 +578,7 @@
   base::Value get_args(base::Value::Type::LIST);
   get_args.Append(kCallbackId);
   get_args.Append(kNotifications);
-  handler()->HandleGetDefaultValueForContentType(get_args.GetList());
+  handler()->HandleGetDefaultValueForContentType(get_args.GetListDeprecated());
   ValidateDefault(CONTENT_SETTING_ASK,
                   site_settings::SiteSettingSource::kDefault, 1U);
 
@@ -587,12 +587,12 @@
   set_args.Append(kNotifications);
   set_args.Append(
       content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK));
-  handler()->HandleSetDefaultValueForContentType(set_args.GetList());
+  handler()->HandleSetDefaultValueForContentType(set_args.GetListDeprecated());
 
   EXPECT_EQ(2U, web_ui()->call_data().size());
 
   // Verify that the default has been set to 'Blocked'.
-  handler()->HandleGetDefaultValueForContentType(get_args.GetList());
+  handler()->HandleGetDefaultValueForContentType(get_args.GetListDeprecated());
   ValidateDefault(CONTENT_SETTING_BLOCK,
                   site_settings::SiteSettingSource::kDefault, 3U);
 }
@@ -603,7 +603,7 @@
   get_all_sites_args.Append(kCallbackId);
 
   // Test all sites is empty when there are no preferences.
-  handler()->HandleGetAllSites(get_all_sites_args.GetList());
+  handler()->HandleGetAllSites(get_all_sites_args.GetListDeprecated());
   EXPECT_EQ(1U, web_ui()->call_data().size());
 
   {
@@ -625,7 +625,7 @@
       url1, url1, ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_BLOCK);
   map->SetContentSettingDefaultScope(
       url2, url2, ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_ALLOW);
-  handler()->HandleGetAllSites(get_all_sites_args.GetList());
+  handler()->HandleGetAllSites(get_all_sites_args.GetListDeprecated());
 
   {
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -653,7 +653,7 @@
   const GURL url3("https://example2.net");
   map->SetContentSettingDefaultScope(
       url3, url3, ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_BLOCK);
-  handler()->HandleGetAllSites(get_all_sites_args.GetList());
+  handler()->HandleGetAllSites(get_all_sites_args.GetListDeprecated());
 
   {
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -693,7 +693,7 @@
       CONTENT_SETTING_BLOCK,
       auto_blocker->GetEmbargoResult(url4, ContentSettingsType::NOTIFICATIONS)
           .content_setting);
-  handler()->HandleGetAllSites(get_all_sites_args.GetList());
+  handler()->HandleGetAllSites(get_all_sites_args.GetListDeprecated());
 
   {
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -707,7 +707,7 @@
 
   // Check |url4| disappears from the list when its embargo expires.
   clock.Advance(base::Days(8));
-  handler()->HandleGetAllSites(get_all_sites_args.GetList());
+  handler()->HandleGetAllSites(get_all_sites_args.GetListDeprecated());
 
   {
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -737,7 +737,7 @@
       auto_blocker->GetEmbargoResult(url3, ContentSettingsType::NOTIFICATIONS)
           .content_setting);
 
-  handler()->HandleGetAllSites(get_all_sites_args.GetList());
+  handler()->HandleGetAllSites(get_all_sites_args.GetListDeprecated());
   {
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     EXPECT_EQ("cr.webUIResponse", data.function_name());
@@ -766,7 +766,7 @@
       auto_blocker->GetEmbargoResult(url5, ContentSettingsType::NOTIFICATIONS)
           .content_setting);
 
-  handler()->HandleGetAllSites(get_all_sites_args.GetList());
+  handler()->HandleGetAllSites(get_all_sites_args.GetListDeprecated());
   {
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     EXPECT_EQ("cr.webUIResponse", data.function_name());
@@ -814,7 +814,7 @@
 
   // Test recent permissions is empty when there are no preferences.
   handler()->HandleGetRecentSitePermissions(
-      get_recent_permissions_args.GetList());
+      get_recent_permissions_args.GetListDeprecated());
   EXPECT_EQ(1U, web_ui()->call_data().size());
 
   {
@@ -852,7 +852,7 @@
         url1, ContentSettingsType::NOTIFICATIONS, false);
 
   handler()->HandleGetRecentSitePermissions(
-      get_recent_permissions_args.GetList());
+      get_recent_permissions_args.GetListDeprecated());
   {
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     EXPECT_EQ("cr.webUIResponse", data.function_name());
@@ -1112,12 +1112,14 @@
         content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK));
     set_args.Append(true);  // Incognito.
 
-    handler()->HandleSetCategoryPermissionForPattern(set_args.GetList());
+    handler()->HandleSetCategoryPermissionForPattern(
+        set_args.GetListDeprecated());
 
     base::Value get_exception_list_args(base::Value::Type::LIST);
     get_exception_list_args.Append(kCallbackId);
     get_exception_list_args.Append(kNotifications);
-    handler()->HandleGetExceptionList(get_exception_list_args.GetList());
+    handler()->HandleGetExceptionList(
+        get_exception_list_args.GetListDeprecated());
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
 
@@ -1137,12 +1139,14 @@
         content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK));
     set_args.Append(false);  // Incognito.
 
-    handler()->HandleSetCategoryPermissionForPattern(set_args.GetList());
+    handler()->HandleSetCategoryPermissionForPattern(
+        set_args.GetListDeprecated());
 
     base::Value get_exception_list_args(base::Value::Type::LIST);
     get_exception_list_args.Append(kCallbackId);
     get_exception_list_args.Append(kNotifications);
-    handler()->HandleGetExceptionList(get_exception_list_args.GetList());
+    handler()->HandleGetExceptionList(
+        get_exception_list_args.GetListDeprecated());
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
 
@@ -1171,7 +1175,8 @@
         content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK));
     set_args.Append(false);  // Incognito.
 
-    handler()->HandleSetCategoryPermissionForPattern(set_args.GetList());
+    handler()->HandleSetCategoryPermissionForPattern(
+        set_args.GetListDeprecated());
     ASSERT_EQ(1U, web_ui()->call_data().size());
   }
 
@@ -1210,7 +1215,8 @@
     reset_args.Append(std::string());
     reset_args.Append(kNotifications);
     reset_args.Append(false);  // Incognito.
-    handler()->HandleResetCategoryPermissionForPattern(reset_args.GetList());
+    handler()->HandleResetCategoryPermissionForPattern(
+        reset_args.GetListDeprecated());
 
     // Check there is 1 blocked origin.
     base::ListValue exceptions;
@@ -1228,7 +1234,8 @@
     reset_args.Append(std::string());
     reset_args.Append(kNotifications);
     reset_args.Append(false);  // Incognito.
-    handler()->HandleResetCategoryPermissionForPattern(reset_args.GetList());
+    handler()->HandleResetCategoryPermissionForPattern(
+        reset_args.GetListDeprecated());
 
     // Check that there are no blocked or embargoed origins.
     base::ListValue exceptions;
@@ -1254,7 +1261,8 @@
       content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK));
   set_args.Append(false);  // Incognito.
 
-  handler()->HandleSetCategoryPermissionForPattern(set_args.GetList());
+  handler()->HandleSetCategoryPermissionForPattern(
+      set_args.GetListDeprecated());
   ASSERT_EQ(1U, web_ui()->call_data().size());
 
   // Reset blocked origin.
@@ -1264,7 +1272,8 @@
   reset_args.Append(kNotifications);
   reset_args.Append(false);  // Incognito.
   // Check that this method is not crashing for an invalid origin.
-  handler()->HandleResetCategoryPermissionForPattern(reset_args.GetList());
+  handler()->HandleResetCategoryPermissionForPattern(
+      reset_args.GetListDeprecated());
 }
 
 TEST_F(SiteSettingsHandlerTest, Origins) {
@@ -1281,7 +1290,8 @@
         content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK));
     set_args.Append(false);  // Incognito.
     base::HistogramTester histograms;
-    handler()->HandleSetCategoryPermissionForPattern(set_args.GetList());
+    handler()->HandleSetCategoryPermissionForPattern(
+        set_args.GetListDeprecated());
     EXPECT_EQ(1U, web_ui()->call_data().size());
     histograms.ExpectTotalCount(uma_base, 1);
     histograms.ExpectTotalCount(uma_base + ".Allowed", 0);
@@ -1293,7 +1303,8 @@
   base::Value get_exception_list_args(base::Value::Type::LIST);
   get_exception_list_args.Append(kCallbackId);
   get_exception_list_args.Append(kNotifications);
-  handler()->HandleGetExceptionList(get_exception_list_args.GetList());
+  handler()->HandleGetExceptionList(
+      get_exception_list_args.GetListDeprecated());
   ValidateOrigin(google, "", google, CONTENT_SETTING_BLOCK,
                  site_settings::SiteSettingSource::kPreference, 2U);
 
@@ -1305,7 +1316,8 @@
     reset_args.Append(kNotifications);
     reset_args.Append(false);  // Incognito.
     base::HistogramTester histograms;
-    handler()->HandleResetCategoryPermissionForPattern(reset_args.GetList());
+    handler()->HandleResetCategoryPermissionForPattern(
+        reset_args.GetListDeprecated());
     EXPECT_EQ(3U, web_ui()->call_data().size());
     histograms.ExpectTotalCount(uma_base, 1);
     histograms.ExpectTotalCount(uma_base + ".Allowed", 0);
@@ -1314,7 +1326,8 @@
   }
 
   // Verify the reset was successful.
-  handler()->HandleGetExceptionList(get_exception_list_args.GetList());
+  handler()->HandleGetExceptionList(
+      get_exception_list_args.GetListDeprecated());
   ValidateNoOrigin(4U);
 }
 
@@ -1338,7 +1351,7 @@
         content_settings::ContentSettingToString(CONTENT_SETTING_ALLOW));
     set_notification_origin_args.Append(false /* incognito */);
     handler()->HandleSetCategoryPermissionForPattern(
-        set_notification_origin_args.GetList());
+        set_notification_origin_args.GetListDeprecated());
   }
 
   {
@@ -1350,7 +1363,7 @@
         content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK));
     set_notification_origin_args.Append(false /* incognito */);
     handler()->HandleSetCategoryPermissionForPattern(
-        set_notification_origin_args.GetList());
+        set_notification_origin_args.GetListDeprecated());
   }
 
   origin_queried_waiter.Run();
@@ -1394,7 +1407,8 @@
   get_origin_permissions_args.Append(std::move(category_list));
 
   // Test Chrome built-in defaults are marked as default.
-  handler()->HandleGetOriginPermissions(get_origin_permissions_args.GetList());
+  handler()->HandleGetOriginPermissions(
+      get_origin_permissions_args.GetListDeprecated());
   ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_ASK,
                  site_settings::SiteSettingSource::kDefault, 1U);
 
@@ -1402,9 +1416,11 @@
   default_value_args.Append(kNotifications);
   default_value_args.Append(
       content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK));
-  handler()->HandleSetDefaultValueForContentType(default_value_args.GetList());
+  handler()->HandleSetDefaultValueForContentType(
+      default_value_args.GetListDeprecated());
   // A user-set global default should also show up as default.
-  handler()->HandleGetOriginPermissions(get_origin_permissions_args.GetList());
+  handler()->HandleGetOriginPermissions(
+      get_origin_permissions_args.GetListDeprecated());
   ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_BLOCK,
                  site_settings::SiteSettingSource::kDefault, 3U);
 
@@ -1416,9 +1432,10 @@
       content_settings::ContentSettingToString(CONTENT_SETTING_ALLOW));
   set_notification_pattern_args.Append(false);
   handler()->HandleSetCategoryPermissionForPattern(
-      set_notification_pattern_args.GetList());
+      set_notification_pattern_args.GetListDeprecated());
   // A user-set pattern should not show up as default.
-  handler()->HandleGetOriginPermissions(get_origin_permissions_args.GetList());
+  handler()->HandleGetOriginPermissions(
+      get_origin_permissions_args.GetListDeprecated());
   ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_ALLOW,
                  site_settings::SiteSettingSource::kPreference, 5U);
 
@@ -1430,15 +1447,17 @@
       content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK));
   set_notification_origin_args.Append(false);
   handler()->HandleSetCategoryPermissionForPattern(
-      set_notification_origin_args.GetList());
+      set_notification_origin_args.GetListDeprecated());
   // A user-set per-origin permission should not show up as default.
-  handler()->HandleGetOriginPermissions(get_origin_permissions_args.GetList());
+  handler()->HandleGetOriginPermissions(
+      get_origin_permissions_args.GetListDeprecated());
   ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_BLOCK,
                  site_settings::SiteSettingSource::kPreference, 7U);
 
   // Enterprise-policy set defaults should not show up as default.
   source_setter.SetPolicyDefault(CONTENT_SETTING_ALLOW);
-  handler()->HandleGetOriginPermissions(get_origin_permissions_args.GetList());
+  handler()->HandleGetOriginPermissions(
+      get_origin_permissions_args.GetListDeprecated());
   ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_ALLOW,
                  site_settings::SiteSettingSource::kPolicy, 8U);
 }
@@ -1455,7 +1474,7 @@
     category_list.Append(kNotifications);
     get_args.Append(std::move(category_list));
   }
-  handler()->HandleGetOriginPermissions(get_args.GetList());
+  handler()->HandleGetOriginPermissions(get_args.GetListDeprecated());
   ValidateOrigin(origin_with_port, origin_with_port, origin,
                  CONTENT_SETTING_ASK,
                  site_settings::SiteSettingSource::kDefault, 1U);
@@ -1466,7 +1485,7 @@
   set_args.Append(kNotifications);
   set_args.Append(
       content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK));
-  handler()->HandleSetOriginPermissions(set_args.GetList());
+  handler()->HandleSetOriginPermissions(set_args.GetListDeprecated());
   EXPECT_EQ(2U, web_ui()->call_data().size());
 
   // Reset things back to how they were.
@@ -1476,11 +1495,11 @@
   reset_args.Append(
       content_settings::ContentSettingToString(CONTENT_SETTING_DEFAULT));
 
-  handler()->HandleSetOriginPermissions(reset_args.GetList());
+  handler()->HandleSetOriginPermissions(reset_args.GetListDeprecated());
   EXPECT_EQ(3U, web_ui()->call_data().size());
 
   // Verify the reset was successful.
-  handler()->HandleGetOriginPermissions(get_args.GetList());
+  handler()->HandleGetOriginPermissions(get_args.GetListDeprecated());
   ValidateOrigin(origin_with_port, origin_with_port, origin,
                  CONTENT_SETTING_ASK,
                  site_settings::SiteSettingSource::kDefault, 4U);
@@ -1497,7 +1516,7 @@
     category_list.Append(kNotifications);
     get_args.Append(std::move(category_list));
   }
-  handler()->HandleGetOriginPermissions(get_args.GetList());
+  handler()->HandleGetOriginPermissions(get_args.GetListDeprecated());
   // Verify that it'll return CONTENT_SETTING_BLOCK as |origin| is not a secure
   // context, a requirement for notifications. Note that the display string
   // will be blank since it's an invalid URL.
@@ -1514,10 +1533,10 @@
   }
   set_args.Append(
       content_settings::ContentSettingToString(CONTENT_SETTING_ALLOW));
-  handler()->HandleSetOriginPermissions(set_args.GetList());
+  handler()->HandleSetOriginPermissions(set_args.GetListDeprecated());
 
   // Also make sure the content setting for |origin| wasn't actually changed.
-  handler()->HandleGetOriginPermissions(get_args.GetList());
+  handler()->HandleGetOriginPermissions(get_args.GetListDeprecated());
   ValidateOrigin(origin, origin, "", CONTENT_SETTING_BLOCK,
                  site_settings::SiteSettingSource::kInsecureOrigin, 2U);
 }
@@ -1549,7 +1568,7 @@
 
   // We don't need to check the results. This is just to make sure it doesn't
   // crash on the input.
-  handler()->HandleSetCategoryPermissionForPattern(args.GetList());
+  handler()->HandleSetCategoryPermissionForPattern(args.GetListDeprecated());
 
   scoped_refptr<const extensions::Extension> extension;
   extension = extensions::ExtensionBuilder()
@@ -1574,7 +1593,7 @@
   CHECK(dictionary.FindBoolKey(site_settings::kIncognito).has_value());
 
   // Again, don't need to check the results.
-  handler()->HandleSetCategoryPermissionForPattern(args.GetList());
+  handler()->HandleSetCategoryPermissionForPattern(args.GetListDeprecated());
 }
 
 TEST_F(SiteSettingsHandlerTest, ExtensionDisplayName) {
@@ -1600,7 +1619,8 @@
     category_list.Append(kNotifications);
     get_origin_permissions_args.Append(std::move(category_list));
   }
-  handler()->HandleGetOriginPermissions(get_origin_permissions_args.GetList());
+  handler()->HandleGetOriginPermissions(
+      get_origin_permissions_args.GetListDeprecated());
   ValidateOrigin(test_extension_url, test_extension_url, kExtensionName,
                  CONTENT_SETTING_ASK,
                  site_settings::SiteSettingSource::kDefault, 1U);
@@ -1613,7 +1633,7 @@
     args.Append(kCallbackId);
     args.Append(test_case.arguments.pattern);
     args.Append(test_case.arguments.content_type);
-    handler()->HandleIsPatternValidForType(args.GetList());
+    handler()->HandleIsPatternValidForType(args.GetListDeprecated());
     ValidatePattern(test_case.expected.validity, counter,
                     test_case.expected.reason);
     ++counter;
@@ -1622,7 +1642,7 @@
 
 TEST_F(SiteSettingsHandlerTest, Incognito) {
   base::Value args(base::Value::Type::LIST);
-  handler()->HandleUpdateIncognitoStatus(args.GetList());
+  handler()->HandleUpdateIncognitoStatus(args.GetListDeprecated());
   ValidateIncognitoExists(false, 1U);
 
   CreateIncognitoProfile();
@@ -1642,11 +1662,11 @@
   ValidateZoom(host, "122%", 1U);
 
   base::Value args(base::Value::Type::LIST);
-  handler()->HandleFetchZoomLevels(args.GetList());
+  handler()->HandleFetchZoomLevels(args.GetListDeprecated());
   ValidateZoom(host, "122%", 2U);
 
   args.Append("http://www.google.com");
-  handler()->HandleRemoveZoomLevel(args.GetList());
+  handler()->HandleRemoveZoomLevel(args.GetListDeprecated());
   ValidateZoom("", "", 3U);
 
   double default_level = host_zoom_map->GetDefaultZoomLevel();
@@ -1777,7 +1797,7 @@
   set_args.Append(kNotifications);
   set_args.Append(
       content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK));
-  handler()->HandleSetOriginPermissions(set_args.GetList());
+  handler()->HandleSetOriginPermissions(set_args.GetListDeprecated());
 
   // Make sure all tabs belonging to the same origin as |origin_anchor| have an
   // infobar shown.
@@ -1827,7 +1847,7 @@
   reset_args.Append(std::move(category_list));
   reset_args.Append(
       content_settings::ContentSettingToString(CONTENT_SETTING_DEFAULT));
-  handler()->HandleSetOriginPermissions(reset_args.GetList());
+  handler()->HandleSetOriginPermissions(reset_args.GetListDeprecated());
 
   // Check the same tabs (plus the tab navigated to |origin_path|) still have
   // infobars showing.
@@ -1871,7 +1891,8 @@
       content_settings::ContentSettingToString(CONTENT_SETTING_SESSION_ONLY));
   set_args.Append(false);  // Incognito.
   base::HistogramTester histograms;
-  handler()->HandleSetCategoryPermissionForPattern(set_args.GetList());
+  handler()->HandleSetCategoryPermissionForPattern(
+      set_args.GetListDeprecated());
 
   EXPECT_EQ(kNumberContentSettingListeners, web_ui()->call_data().size());
   histograms.ExpectTotalCount(uma_base, 1);
@@ -1880,7 +1901,7 @@
 
 TEST_F(SiteSettingsHandlerTest, BlockAutoplay_SendOnRequest) {
   base::Value args(base::Value::Type::LIST);
-  handler()->HandleFetchBlockAutoplayStatus(args.GetList());
+  handler()->HandleFetchBlockAutoplayStatus(args.GetListDeprecated());
 
   // Check that we are checked and enabled.
   ValidateBlockAutoplay(true, true);
@@ -1920,7 +1941,7 @@
   base::Value data(base::Value::Type::LIST);
   data.Append(false);
 
-  handler()->HandleSetBlockAutoplayEnabled(data.GetList());
+  handler()->HandleSetBlockAutoplayEnabled(data.GetListDeprecated());
   EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kBlockAutoplayEnabled));
 }
 
@@ -1961,7 +1982,7 @@
     base::Value get_all_sites_args(base::Value::Type::LIST);
     get_all_sites_args.Append(kCallbackId);
 
-    handler()->HandleGetAllSites(get_all_sites_args.GetList());
+    handler()->HandleGetAllSites(get_all_sites_args.GetListDeprecated());
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     base::Value::ConstListView site_groups = data.arg3()->GetListDeprecated();
@@ -1982,7 +2003,8 @@
     get_exception_list_args.Append(kCallbackId);
     get_exception_list_args.Append(kNotifications);
 
-    handler()->HandleGetExceptionList(get_exception_list_args.GetList());
+    handler()->HandleGetExceptionList(
+        get_exception_list_args.GetListDeprecated());
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     base::Value::ConstListView exception_list =
@@ -1999,7 +2021,7 @@
     get_recent_permissions_args.Append(3);
 
     handler()->HandleGetRecentSitePermissions(
-        get_recent_permissions_args.GetList());
+        get_recent_permissions_args.GetListDeprecated());
 
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     base::Value::ConstListView recent_permission_list =
@@ -2037,7 +2059,7 @@
     get_origin_permissions_args.Append(std::move(category_list));
 
     handler()->HandleGetOriginPermissions(
-        get_origin_permissions_args.GetList());
+        get_origin_permissions_args.GetListDeprecated());
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     const base::Value::ConstListView exception_list =
         data.arg3()->GetListDeprecated();
@@ -2185,7 +2207,7 @@
     args.Append(kCallbackId);
     args.Append(chooser_type);
 
-    handler()->HandleGetChooserExceptionList(args.GetList());
+    handler()->HandleGetChooserExceptionList(args.GetListDeprecated());
 
     EXPECT_EQ(web_ui()->call_data().size(), expected_total_calls);
 
@@ -2351,7 +2373,7 @@
                                             ContentSettingsType::USB_GUARD),
                                         ContentSettingsType::USB_CHOOSER_DATA));
   EXPECT_CALL(observer_, OnPermissionRevoked(kGoogleOrigin));
-  handler()->HandleResetChooserExceptionForSite(args.GetList());
+  handler()->HandleResetChooserExceptionForSite(args.GetListDeprecated());
   auto* chooser_context = UsbChooserContextFactory::GetForProfile(profile());
   chooser_context->FlushScheduledSaveSettingsCalls();
 
@@ -2399,7 +2421,7 @@
                                             ContentSettingsType::USB_GUARD),
                                         ContentSettingsType::USB_CHOOSER_DATA));
   EXPECT_CALL(observer_, OnPermissionRevoked(kChromiumOrigin));
-  handler()->HandleResetChooserExceptionForSite(args.GetList());
+  handler()->HandleResetChooserExceptionForSite(args.GetListDeprecated());
   chooser_context->FlushScheduledSaveSettingsCalls();
 
   // The HandleResetChooserExceptionForSite() method should have also caused the
@@ -2445,7 +2467,7 @@
                                             ContentSettingsType::USB_GUARD),
                                         ContentSettingsType::USB_CHOOSER_DATA));
   EXPECT_CALL(observer_, OnPermissionRevoked(kAndroidOrigin));
-  handler()->HandleResetChooserExceptionForSite(args.GetList());
+  handler()->HandleResetChooserExceptionForSite(args.GetListDeprecated());
   chooser_context->FlushScheduledSaveSettingsCalls();
 
   // The HandleResetChooserExceptionForSite() method should have also caused the
@@ -2481,7 +2503,7 @@
 
   base::Value args(base::Value::Type::LIST);
   args.Append("example.com");
-  handler()->HandleClearEtldPlus1DataAndCookies(args.GetList());
+  handler()->HandleClearEtldPlus1DataAndCookies(args.GetListDeprecated());
 
   // All host nodes for non-secure example.com, and abc.example.com, which do
   // not have any unpartitioned  storage, should have been removed.
@@ -2513,7 +2535,7 @@
   args.ClearList();
   args.Append("google.com");
 
-  handler()->HandleClearEtldPlus1DataAndCookies(args.GetList());
+  handler()->HandleClearEtldPlus1DataAndCookies(args.GetListDeprecated());
 
   EXPECT_EQ(11, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount());
 
@@ -2524,7 +2546,7 @@
   args.ClearList();
   args.Append("google.com.au");
 
-  handler()->HandleClearEtldPlus1DataAndCookies(args.GetList());
+  handler()->HandleClearEtldPlus1DataAndCookies(args.GetListDeprecated());
   // No nodes representing storage partitioned on google.com.au should be
   // present.
   for (const auto& host_node :
@@ -2555,7 +2577,7 @@
 
   base::Value args(base::Value::Type::LIST);
   args.Append("https://www.example.com/");
-  handler()->HandleClearUnpartitionedUsage(args.GetList());
+  handler()->HandleClearUnpartitionedUsage(args.GetListDeprecated());
 
   // Confirm that only the unpartitioned items for example.com have been
   // cleared.
@@ -2578,7 +2600,7 @@
   // not be cleared.
   args = base::Value(base::Value::Type::LIST);
   args.Append("https://google.com.au/");
-  handler()->HandleClearUnpartitionedUsage(args.GetList());
+  handler()->HandleClearUnpartitionedUsage(args.GetListDeprecated());
 
   remaining_host_nodes = GetHostNodes(GURL("https://google.com.au"));
 
@@ -2627,7 +2649,7 @@
   // Clear at the eTLD+1 level and ensure affected origins are cleared.
   base::Value args(base::Value::Type::LIST);
   args.Append("example.com");
-  handler()->HandleClearEtldPlus1DataAndCookies(args.GetList());
+  handler()->HandleClearEtldPlus1DataAndCookies(args.GetListDeprecated());
   host_content_settings_map->GetSettingsForOneType(
       ContentSettingsType::CLIENT_HINTS, &client_hints_settings);
   EXPECT_EQ(2U, client_hints_settings.size());
@@ -2648,7 +2670,7 @@
   // origin.
   args.ClearList();
   args.Append("https://google.com/");
-  handler()->HandleClearUnpartitionedUsage(args.GetList());
+  handler()->HandleClearUnpartitionedUsage(args.GetListDeprecated());
 
   // Validate the client hint has been cleared.
   host_content_settings_map->GetSettingsForOneType(
@@ -2672,7 +2694,7 @@
   base::Value args(base::Value::Type::LIST);
   args.Append("https://www.example.com/");
   args.Append("google.com");
-  handler()->HandleClearPartitionedUsage(args.GetList());
+  handler()->HandleClearPartitionedUsage(args.GetListDeprecated());
 
   // This should have only removed cookies for embedded.com partitioned on
   // google.com, leaving other cookies and storage untouched.
@@ -2728,7 +2750,7 @@
   // Validate get method works.
   base::Value get_args(base::Value::Type::LIST);
   get_args.Append(kCallbackId);
-  handler()->HandleGetCookieSettingDescription(get_args.GetList());
+  handler()->HandleGetCookieSettingDescription(get_args.GetListDeprecated());
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
 
   EXPECT_EQ("cr.webUIResponse", data.function_name());
@@ -2800,7 +2822,7 @@
   base::Value get_args(base::Value::Type::LIST);
   get_args.Append(kCallbackId);
   get_args.Append(size);
-  handler()->HandleGetFormattedBytes(get_args.GetList());
+  handler()->HandleGetFormattedBytes(get_args.GetListDeprecated());
 
   // Validate that this method can handle large data.
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
@@ -2819,13 +2841,13 @@
 
   base::Value args(base::Value::Type::LIST);
   args.Append("www.example.com");
-  handler()->HandleFetchUsageTotal(args.GetList());
+  handler()->HandleFetchUsageTotal(args.GetListDeprecated());
   handler()->OnGetUsageInfo();
   ValidateUsageInfo("www.example.com", "2 B", "1 cookie");
 
   args.ClearList();
   args.Append("example.com");
-  handler()->HandleFetchUsageTotal(args.GetList());
+  handler()->HandleFetchUsageTotal(args.GetListDeprecated());
   handler()->OnGetUsageInfo();
   ValidateUsageInfo("example.com", "", "1 cookie");
 }
diff --git a/chrome/browser/ui/webui/settings/system_handler.cc b/chrome/browser/ui/webui/settings/system_handler.cc
index 3699eaf..1a344d697 100644
--- a/chrome/browser/ui/webui/settings/system_handler.cc
+++ b/chrome/browser/ui/webui/settings/system_handler.cc
@@ -27,13 +27,13 @@
 }
 
 void SystemHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "showProxySettings",
       base::BindRepeating(&SystemHandler::HandleShowProxySettings,
                           base::Unretained(this)));
 }
 
-void SystemHandler::HandleShowProxySettings(const base::ListValue* /*args*/) {
+void SystemHandler::HandleShowProxySettings(base::Value::ConstListView args) {
   base::RecordAction(base::UserMetricsAction("Options_ShowProxySettings"));
   settings_utils::ShowNetworkProxySettings(web_ui()->GetWebContents());
 }
diff --git a/chrome/browser/ui/webui/settings/system_handler.h b/chrome/browser/ui/webui/settings/system_handler.h
index fcbae06..a8465c3 100644
--- a/chrome/browser/ui/webui/settings/system_handler.h
+++ b/chrome/browser/ui/webui/settings/system_handler.h
@@ -7,10 +7,6 @@
 
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace content {
 class WebUIDataSource;
 }
@@ -36,7 +32,7 @@
 
  private:
   // Handler for the "showProxySettings" message. No args.
-  void HandleShowProxySettings(const base::ListValue* /*args*/);
+  void HandleShowProxySettings(base::Value::ConstListView args);
 };
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/url_handlers_handler.cc b/chrome/browser/ui/webui/settings/url_handlers_handler.cc
index a45e82b9e..93b0d6e 100644
--- a/chrome/browser/ui/webui/settings/url_handlers_handler.cc
+++ b/chrome/browser/ui/webui/settings/url_handlers_handler.cc
@@ -208,12 +208,12 @@
 }
 
 void UrlHandlersHandler::RegisterMessages() {
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "getUrlHandlers",
       base::BindRepeating(&UrlHandlersHandler::HandleGetUrlHandlers,
                           base::Unretained(this)));
 
-  web_ui()->RegisterDeprecatedMessageCallback(
+  web_ui()->RegisterMessageCallback(
       "resetUrlHandlerSavedChoice",
       base::BindRepeating(&UrlHandlersHandler::HandleResetUrlHandlerSavedChoice,
                           base::Unretained(this)));
@@ -233,9 +233,9 @@
                     disabled_handlers_list);
 }
 
-void UrlHandlersHandler::HandleGetUrlHandlers(const base::ListValue* args) {
-  CHECK_EQ(1U, args->GetListDeprecated().size());
-  const base::Value& callback_id = args->GetListDeprecated()[0];
+void UrlHandlersHandler::HandleGetUrlHandlers(base::Value::ConstListView args) {
+  CHECK_EQ(1U, args.size());
+  const base::Value& callback_id = args[0];
   AllowJavascript();
 
   base::Value result(base::Value::Type::DICTIONARY);
@@ -245,14 +245,14 @@
 }
 
 void UrlHandlersHandler::HandleResetUrlHandlerSavedChoice(
-    const base::ListValue* args) {
-  CHECK_EQ(4U, args->GetListDeprecated().size());
-  const std::string& origin = args->GetListDeprecated()[0].GetString();
-  bool has_origin_wildcard = args->GetListDeprecated()[1].GetBool();
-  const std::string& path = args->GetListDeprecated()[2].GetString();
+    base::Value::ConstListView args) {
+  CHECK_EQ(4U, args.size());
+  const std::string& origin = args[0].GetString();
+  bool has_origin_wildcard = args[1].GetBool();
+  const std::string& path = args[2].GetString();
   // If app_id is an empty string, reset saved choices for all applicable
   // entries regardless of app_id.
-  const std::string& app_id = args->GetListDeprecated()[3].GetString();
+  const std::string& app_id = args[3].GetString();
   absl::optional<std::string> app_id_opt =
       app_id.empty() ? absl::nullopt : absl::make_optional(app_id);
 
diff --git a/chrome/browser/ui/webui/settings/url_handlers_handler.h b/chrome/browser/ui/webui/settings/url_handlers_handler.h
index b59949b..9d7c6ac 100644
--- a/chrome/browser/ui/webui/settings/url_handlers_handler.h
+++ b/chrome/browser/ui/webui/settings/url_handlers_handler.h
@@ -47,13 +47,13 @@
 
   // Handles calls from WebUI to update the model data of URL handlers settings.
   // Takes no args.
-  void HandleGetUrlHandlers(const base::ListValue* args);
+  void HandleGetUrlHandlers(base::Value::ConstListView args);
 
   // Handles calls from WebUI to reset the user's saved choice for one or more
   // URL handler entries.
   // When reset, the choice becomes kNone and the timestamp is updated.
   // |args| is a list of [app_id, origin_key, has_origin_wildcard, url_path].
-  void HandleResetUrlHandlerSavedChoice(const base::ListValue* args);
+  void HandleResetUrlHandlerSavedChoice(base::Value::ConstListView args);
 
   // Reads and formats data from UrlHandlerPrefs then sends it to the WebUI
   // frontend.
diff --git a/chrome/browser/web_applications/web_app_offline_browsertest.cc b/chrome/browser/web_applications/web_app_offline_browsertest.cc
index 96651c4..eaa764c 100644
--- a/chrome/browser/web_applications/web_app_offline_browsertest.cc
+++ b/chrome/browser/web_applications/web_app_offline_browsertest.cc
@@ -13,28 +13,21 @@
 #include "content/public/test/browser_test_base.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/url_loader_interceptor.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+#include "ui/base/ui_base_switches.h"
+#include "ui/native_theme/native_theme.h"
 
 namespace web_app {
 
-enum class FlagParam {
-  kWithFlag = 0,
-  kWithoutFlag = 1,
-  kMaxValue = kWithoutFlag
+enum class PageFlagParam {
+  kWithDefaultPageFlag = 0,
+  kWithoutDefaultPageFlag = 1,
+  kMaxValue = kWithoutDefaultPageFlag
 };
 
-class WebAppOfflinePageTest : public InProcessBrowserTest,
-                              public ::testing::WithParamInterface<FlagParam> {
+class WebAppOfflineTest : public InProcessBrowserTest {
  public:
-  WebAppOfflinePageTest() {
-    if (GetParam() == FlagParam::kWithFlag) {
-      feature_list_.InitAndEnableFeature(
-          features::kDesktopPWAsDefaultOfflinePage);
-    } else {
-      feature_list_.InitAndDisableFeature(
-          features::kDesktopPWAsDefaultOfflinePage);
-    }
-  }
-
   // Start a web app without a service worker and disconnect.
   void StartWebAppAndDisconnect(content::WebContents* web_contents,
                                 std::string html) {
@@ -69,6 +62,21 @@
     web_contents->GetController().Reload(content::ReloadType::NORMAL, false);
     observer.Wait();
   }
+};
+
+class WebAppOfflinePageTest
+    : public WebAppOfflineTest,
+      public ::testing::WithParamInterface<PageFlagParam> {
+ public:
+  WebAppOfflinePageTest() {
+    if (GetParam() == PageFlagParam::kWithDefaultPageFlag) {
+      feature_list_.InitAndEnableFeature(
+          features::kDesktopPWAsDefaultOfflinePage);
+    } else {
+      feature_list_.InitAndDisableFeature(
+          features::kDesktopPWAsDefaultOfflinePage);
+    }
+  }
 
  private:
   base::test::ScopedFeatureList feature_list_;
@@ -84,7 +92,7 @@
       browser()->tab_strip_model()->GetActiveWebContents();
   StartWebAppAndDisconnect(web_contents, "/banners/no-sw-with-colors.html");
 
-  if (GetParam() == FlagParam::kWithFlag) {
+  if (GetParam() == PageFlagParam::kWithDefaultPageFlag) {
     // Expect that the default offline page is showing.
     EXPECT_TRUE(
         EvalJs(web_contents,
@@ -108,7 +116,7 @@
       browser()->tab_strip_model()->GetActiveWebContents();
   StartPwaAndDisconnect(web_contents, "/banners/background-color.html");
 
-  if (GetParam() == FlagParam::kWithFlag) {
+  if (GetParam() == PageFlagParam::kWithDefaultPageFlag) {
     // Expect that the default offline page is showing.
     EXPECT_TRUE(
         EvalJs(web_contents,
@@ -137,9 +145,124 @@
                   .ExtractBool());
 }
 
-INSTANTIATE_TEST_SUITE_P(All,
-                         WebAppOfflinePageTest,
-                         ::testing::Values(FlagParam::kWithFlag,
-                                           FlagParam::kWithoutFlag));
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    WebAppOfflinePageTest,
+    ::testing::Values(PageFlagParam::kWithDefaultPageFlag,
+                      PageFlagParam::kWithoutDefaultPageFlag));
 
+class WebAppOfflineDarkModeTest
+    : public WebAppOfflineTest,
+      public testing::WithParamInterface<blink::mojom::PreferredColorScheme> {
+ public:
+  WebAppOfflineDarkModeTest() {
+    feature_list_.InitWithFeatures({features::kDesktopPWAsDefaultOfflinePage,
+                                    blink::features::kWebAppEnableDarkMode},
+                                   {});
+  }
+
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    // ShellContentBrowserClient::OverrideWebkitPrefs() overrides the
+    // prefers-color-scheme according to switches::kForceDarkMode
+    // command line.
+    if (GetParam() == blink::mojom::PreferredColorScheme::kDark)
+      command_line->AppendSwitch(switches::kForceDarkMode);
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// Testing offline page in dark mode for a web app with a manifest and no
+// service worker.
+IN_PROC_BROWSER_TEST_P(WebAppOfflineDarkModeTest,
+                       WebAppOfflineDarkModeNoServiceWorker) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  // ui::NativeTheme::GetInstanceForNativeUi()->set_use_dark_colors(true);
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  StartWebAppAndDisconnect(
+      web_contents, "/web_apps/get_manifest.html?color_scheme_dark.json");
+
+  // Expect that the default offline page is showing with dark mode colors.
+
+  EXPECT_TRUE(
+      EvalJs(web_contents,
+             "window.matchMedia('(prefers-color-scheme: dark)').matches")
+          .ExtractBool());
+  EXPECT_EQ(
+      EvalJs(web_contents,
+             "window.getComputedStyle(document.querySelector('h2')).color")
+          .ExtractString(),
+      "rgb(255, 0, 0)");
+  EXPECT_EQ(EvalJs(web_contents,
+                   "window.getComputedStyle(document.querySelector('body'))."
+                   "backgroundColor")
+                .ExtractString(),
+            "rgb(255, 0, 0)");
+}
+
+// Testing offline page in dark mode for a web app with a manifest and service
+// worker that does not handle offline error.
+IN_PROC_BROWSER_TEST_P(WebAppOfflineDarkModeTest,
+                       WebAppOfflineDarkModeEmptyServiceWorker) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  StartWebAppAndDisconnect(web_contents,
+                           "/banners/manifest_test_page.html?manifest=../"
+                           "web_apps/color_scheme_dark.json");
+
+  // Expect that the default offline page is showing with dark mode colors.
+  EXPECT_TRUE(
+      EvalJs(web_contents,
+             "window.matchMedia('(prefers-color-scheme: dark)').matches")
+          .ExtractBool());
+  EXPECT_EQ(
+      EvalJs(web_contents,
+             "window.getComputedStyle(document.querySelector('h2')).color")
+          .ExtractString(),
+      "rgb(255, 0, 0)");
+  EXPECT_EQ(EvalJs(web_contents,
+                   "window.getComputedStyle(document.querySelector('body'))."
+                   "backgroundColor")
+                .ExtractString(),
+            "rgb(255, 0, 0)");
+}
+
+// Testing offline page in dark mode for a web app with a manifest that has not
+// provided dark mode colors.
+IN_PROC_BROWSER_TEST_P(WebAppOfflineDarkModeTest,
+                       WebAppOfflineNoDarkModeColorsProvided) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  StartWebAppAndDisconnect(web_contents, "/banners/no-sw-with-colors.html");
+
+  // Expect that the default offline page is showing with dark mode colors.
+  EXPECT_TRUE(
+      EvalJs(web_contents,
+             "window.matchMedia('(prefers-color-scheme: dark)').matches")
+          .ExtractBool());
+  EXPECT_EQ(
+      EvalJs(web_contents,
+             "window.getComputedStyle(document.querySelector('h2')).color")
+          .ExtractString(),
+      "rgb(0, 255, 0)");
+  EXPECT_EQ(EvalJs(web_contents,
+                   "window.getComputedStyle(document.querySelector('body'))."
+                   "backgroundColor")
+                .ExtractString(),
+            "rgb(255, 255, 0)");
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    /* no prefix */,
+    WebAppOfflineDarkModeTest,
+    ::testing::Values(blink::mojom::PreferredColorScheme::kDark));
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_utils.cc b/chrome/browser/web_applications/web_app_utils.cc
index 2d4b1db4..80e85de 100644
--- a/chrome/browser/web_applications/web_app_utils.cc
+++ b/chrome/browser/web_applications/web_app_utils.cc
@@ -141,20 +141,38 @@
       content::mojom::AlternativeErrorPageOverrideInfo::New();
   // TODO(crbug.com/1285128): Ensure sufficient contrast.
   base::Value dict(base::Value::Type::DICTIONARY);
-  dict.SetStringKey(
-      default_offline::kThemeColor,
-      skia::SkColorToHexString(
-          web_app_registrar.GetAppThemeColor(*app_id).value_or(SK_ColorBLACK)));
-  dict.SetStringKey(
-      default_offline::kBackgroundColor,
-      skia::SkColorToHexString(
-          web_app_registrar.GetAppBackgroundColor(*app_id).value_or(
-              SK_ColorWHITE)));
+  SkColor theme_color =
+      web_app_registrar.GetAppThemeColor(*app_id).value_or(SK_ColorBLACK);
+  SkColor background_color =
+      web_app_registrar.GetAppBackgroundColor(*app_id).value_or(SK_ColorWHITE);
+  dict.SetStringKey(default_offline::kThemeColor,
+                    skia::SkColorToHexString(theme_color));
+  dict.SetStringKey(default_offline::kBackgroundColor,
+                    skia::SkColorToHexString(background_color));
   dict.SetStringKey(default_offline::kAppShortName,
                     web_app_registrar.GetAppShortName(*app_id));
   dict.SetStringKey(
       default_offline::kMessage,
       l10n_util::GetStringUTF16(IDS_ERRORPAGES_HEADING_INTERNET_DISCONNECTED));
+  absl::optional<SkColor> dark_mode_theme_color =
+      web_app_registrar.GetAppDarkModeThemeColor(*app_id);
+  if (dark_mode_theme_color) {
+    dict.SetStringKey(default_offline::kDarkModeThemeColor,
+                      skia::SkColorToHexString(dark_mode_theme_color.value()));
+  } else {
+    dict.SetStringKey(default_offline::kDarkModeThemeColor,
+                      skia::SkColorToHexString(theme_color));
+  }
+  absl::optional<SkColor> dark_mode_background_color =
+      web_app_registrar.GetAppDarkModeThemeColor(*app_id);
+  if (dark_mode_background_color) {
+    dict.SetStringKey(
+        default_offline::kDarkModeBackgroundColor,
+        skia::SkColorToHexString(dark_mode_background_color.value()));
+  } else {
+    dict.SetStringKey(default_offline::kDarkModeBackgroundColor,
+                      skia::SkColorToHexString(background_color));
+  }
   alternative_error_page_info->alternative_error_page_params = std::move(dict);
   alternative_error_page_info->resource_id = IDR_WEBAPP_DEFAULT_OFFLINE_HTML;
   return alternative_error_page_info;
diff --git a/chrome/browser/web_applications/web_app_utils.h b/chrome/browser/web_applications/web_app_utils.h
index a895db6..62c1874 100644
--- a/chrome/browser/web_applications/web_app_utils.h
+++ b/chrome/browser/web_applications/web_app_utils.h
@@ -37,6 +37,8 @@
 const char kAppShortName[] = "app_short_name";
 const char kThemeColor[] = "theme_color";
 const char kBackgroundColor[] = "customized_background_color";
+const char kDarkModeBackgroundColor[] = "dark_mode_background_color";
+const char kDarkModeThemeColor[] = "dark_mode_theme_color";
 }  // namespace default_offline
 
 // These functions return true if the WebApp System or its subset is allowed
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index c651c6d6..b2e6fd07 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1643997497-d0b9bb949302ba9bcb3a3806499eb479335dbf19.profdata
+chrome-linux-main-1644118955-7e8d294844ae96817eadcc0770995e739334be21.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 316ba6b11..5eaa1de 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1643997497-b2d0727f6c71e3485f96539344c4963581193871.profdata
+chrome-mac-arm-main-1644163308-984567538b4fc27f0004c2fd2397b8422763b27a.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index bab979a..58b8d5d 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1643997497-c4546bc27c73f847715efef5b229989aff7c3ed7.profdata
+chrome-mac-main-1644118955-05e676f529a4efca1a9a4e08337ebec4cd214d28.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 81bbecb0..205377b 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1643997497-c2be50db48a0b1a71639f7122e0e946919b565ad.profdata
+chrome-win32-main-1644118955-0ec0e7b6d7e110de3da69c7dc253de2e0a33b817.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index aecfe05..00978614 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1644008380-a5f7527dbbdebdf9b56255d0991ef81a7359bcbd.profdata
+chrome-win64-main-1644163308-af270ed7ed4c8dbe3f2cebd5c1162801cc874a13.profdata
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 227e618f..0a36840 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -212,7 +212,6 @@
     "//components/visitedlink/common",
     "//content/public/common",
     "//extensions/buildflags",
-    "//extensions/common:common_constants",
     "//google_apis",
     "//gpu/command_buffer/service",
     "//gpu/config",
@@ -323,6 +322,7 @@
       "//chrome/common/extensions/api:extensions_features",
       "//extensions:extensions_resources",
       "//extensions/common",
+      "//extensions/common:common_constants",
       "//extensions/common:core_api_provider",
       "//extensions/common/api",
       "//extensions/strings",
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 2eac5f7..ea6b3943 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -21,6 +21,10 @@
 // comments. Imagine "This switch..." at the beginning of the phrase, and it'll
 // all work out.
 // -----------------------------------------------------------------------------
+// Specifies Accept-Language to send to servers and expose to JavaScript via the
+// navigator.language DOM property. language[-country] where language is the 2
+// letter code from ISO-639.
+const char kAcceptLang[] = "accept-lang";
 
 // Allows third-party content included on a page to prompt for a HTTP basic
 // auth username/password pair.
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index bb1953d..717c7e09 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -36,6 +36,7 @@
 
 // All switches in alphabetical order. The switches should be documented
 // alongside the definition of their values in the .cc file.
+extern const char kAcceptLang[];
 extern const char kAllowCrossOriginAuthPrompt[];
 extern const char kAllowHttpScreenCapture[];
 extern const char kAllowProfilesOutsideUserDir[];
diff --git a/chrome/common/extensions/api/autofill_private.idl b/chrome/common/extensions/api/autofill_private.idl
index 6af8f68..7272890 100644
--- a/chrome/common/extensions/api/autofill_private.idl
+++ b/chrome/common/extensions/api/autofill_private.idl
@@ -42,6 +42,14 @@
     // For credit cards, whether this is migratable (both the card number and
     // expiration date valid and does not have the duplicated server card).
     boolean? isMigratable;
+
+    // For credit cards. Indicates whether a card is eligible for virtual cards
+    // enrollment.
+    boolean? isVirtualCardEnrollmentEligible;
+
+    // For credit cards. Indicates whether a card has been enrolled in virtual
+    // cards if it is eligible.
+    boolean? isVirtualCardEnrolled;
   };
 
   // An address entry which can be saved in the autofill section of the
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 1ee3fc56..5d785b4 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -94,7 +94,6 @@
 const char kChromeUIFileiconURL[] = "chrome://fileicon/";
 const char kChromeUIFlagsHost[] = "flags";
 const char kChromeUIFlagsURL[] = "chrome://flags/";
-const char kChromeUIFlocInternalsHost[] = "floc-internals";
 const char kChromeUIGCMInternalsHost[] = "gcm-internals";
 const char kChromeUIHangUIHost[] = "uithreadhang";
 const char kChromeUIHelpHost[] = "help";
@@ -586,7 +585,6 @@
     kChromeUIFamilyLinkUserInternalsHost,
 #endif  // BUILDFLAG(ENABLE_SUPERVISED_USERS)
     kChromeUIFlagsHost,
-    kChromeUIFlocInternalsHost,
     kChromeUIGCMInternalsHost,
     kChromeUIHistoryHost,
     kChromeUIInterstitialHost,
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index 1fd300b4..d79d7547 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -95,7 +95,6 @@
 extern const char kChromeUIFileiconURL[];
 extern const char kChromeUIFlagsHost[];
 extern const char kChromeUIFlagsURL[];
-extern const char kChromeUIFlocInternalsHost[];
 extern const char kChromeUIGCMInternalsHost[];
 extern const char kChromeUIHangUIHost[];
 extern const char kChromeUIHelpHost[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index a416c87..0e00154e 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -248,7 +248,6 @@
     "//components/content_settings/core/browser",
     "//components/custom_handlers/",
     "//components/domain_reliability",
-    "//components/federated_learning",
     "//components/find_in_page",
     "//components/gcm_driver:test_support",
     "//components/gcm_driver/crypto:test_support",
@@ -1142,7 +1141,6 @@
       "//chrome/browser/safe_browsing:verdict_cache_manager_factory",
       "//chrome/browser/sharing/proto",
       "//chrome/browser/ui/tabs:tab_enums",
-      "//chrome/browser/ui/webui/federated_learning:mojo_bindings",
       "//chrome/browser/ui/webui/history_clusters:mojo_bindings",
       "//chrome/browser/web_applications:browser_tests",
       "//chrome/browser/web_applications:web_applications_test_support",
@@ -1593,10 +1591,6 @@
       "../browser/enterprise/util/managed_browser_utils_browsertest.cc",
       "../browser/fast_shutdown_browsertest.cc",
       "../browser/favicon/content_favicon_driver_browsertest.cc",
-      "../browser/federated_learning/floc_eligibility_browsertest.cc",
-      "../browser/federated_learning/floc_id_provider_browsertest.cc",
-      "../browser/federated_learning/floc_internals_browsertest.cc",
-      "../browser/federated_learning/floc_origin_trial_browsertest.cc",
       "../browser/file_system_access/chrome_file_system_access_permission_context_browsertest.cc",
       "../browser/file_system_access/file_system_access_tab_helper_browsertest.cc",
       "../browser/first_party_sets/first_party_sets_policy_browsertest.cc",
@@ -4550,7 +4544,6 @@
     "../browser/component_updater/chrome_component_updater_configurator_unittest.cc",
     "../browser/component_updater/crl_set_component_installer_unittest.cc",
     "../browser/component_updater/first_party_sets_component_installer_unittest.cc",
-    "../browser/component_updater/floc_component_installer_unittest.cc",
     "../browser/component_updater/origin_trials_component_installer_unittest.cc",
     "../browser/component_updater/subresource_filter_component_installer_unittest.cc",
     "../browser/component_updater/trust_token_key_commitments_component_installer_unittest.cc",
@@ -4594,10 +4587,6 @@
     "../browser/enterprise/util/managed_browser_utils_unittest.cc",
     "../browser/external_protocol/external_protocol_handler_unittest.cc",
     "../browser/favicon/large_icon_service_factory_unittest.cc",
-    "../browser/federated_learning/floc_eligibility_unittest.cc",
-    "../browser/federated_learning/floc_event_logger_unittest.cc",
-    "../browser/federated_learning/floc_id_provider_unittest.cc",
-    "../browser/federated_learning/floc_remote_permission_service_unittest.cc",
     "../browser/file_select_helper_unittest.cc",
     "../browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc",
     "../browser/first_party_sets/first_party_sets_util_unittest.cc",
@@ -5258,7 +5247,6 @@
     "//chrome/browser/ui:test_support",
     "//chrome/browser/ui/commander:fuzzy_finder",
     "//chrome/browser/ui/webui/downloads:mojo_bindings",
-    "//chrome/browser/ui/webui/federated_learning:mojo_bindings",
     "//chrome/browser/ui/webui/new_tab_page:mojo_bindings",
     "//chrome/browser/updates/announcement_notification:unit_tests",
     "//chrome/browser/video_tutorials:unit_tests",
diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc
index 10011cc9..66023194 100644
--- a/chrome/test/base/testing_browser_process.cc
+++ b/chrome/test/base/testing_browser_process.cc
@@ -28,7 +28,6 @@
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/testing_browser_process_platform_part.h"
-#include "components/federated_learning/floc_sorting_lsh_clusters_service.h"
 #include "components/network_time/network_time_tracker.h"
 #include "components/permissions/permissions_client.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
@@ -281,11 +280,6 @@
   return subresource_filter_ruleset_service_.get();
 }
 
-federated_learning::FlocSortingLshClustersService*
-TestingBrowserProcess::floc_sorting_lsh_clusters_service() {
-  return floc_sorting_lsh_clusters_service_.get();
-}
-
 BrowserProcessPlatformPart* TestingBrowserProcess::platform_part() {
   return platform_part_.get();
 }
@@ -524,12 +518,6 @@
   subresource_filter_ruleset_service_.swap(ruleset_service);
 }
 
-void TestingBrowserProcess::SetFlocSortingLshClustersService(
-    std::unique_ptr<federated_learning::FlocSortingLshClustersService>
-        service) {
-  floc_sorting_lsh_clusters_service_.swap(service);
-}
-
 void TestingBrowserProcess::SetShuttingDown(bool is_shutting_down) {
   is_shutting_down_ = is_shutting_down;
 }
diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h
index d0834440..ecada662 100644
--- a/chrome/test/base/testing_browser_process.h
+++ b/chrome/test/base/testing_browser_process.h
@@ -102,8 +102,6 @@
   safe_browsing::SafeBrowsingService* safe_browsing_service() override;
   subresource_filter::RulesetService* subresource_filter_ruleset_service()
       override;
-  federated_learning::FlocSortingLshClustersService*
-  floc_sorting_lsh_clusters_service() override;
   BrowserProcessPlatformPart* platform_part() override;
 
   extensions::EventRouterForwarder* extension_event_router_forwarder() override;
@@ -158,9 +156,6 @@
   void SetSafeBrowsingService(safe_browsing::SafeBrowsingService* sb_service);
   void SetRulesetService(
       std::unique_ptr<subresource_filter::RulesetService> ruleset_service);
-  void SetFlocSortingLshClustersService(
-      std::unique_ptr<federated_learning::FlocSortingLshClustersService>
-          service);
   void SetSharedURLLoaderFactory(
       scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory);
 #if BUILDFLAG(ENABLE_CHROME_NOTIFICATIONS)
@@ -213,8 +208,6 @@
   scoped_refptr<safe_browsing::SafeBrowsingService> sb_service_;
   std::unique_ptr<subresource_filter::RulesetService>
       subresource_filter_ruleset_service_;
-  std::unique_ptr<federated_learning::FlocSortingLshClustersService>
-      floc_sorting_lsh_clusters_service_;
 
   std::unique_ptr<network_time::NetworkTimeTracker> network_time_tracker_;
 
diff --git a/chrome/test/data/federated_learning/interest_cohort_api_in_detached_document.html b/chrome/test/data/federated_learning/interest_cohort_api_in_detached_document.html
deleted file mode 100644
index 28a5e55..0000000
--- a/chrome/test/data/federated_learning/interest_cohort_api_in_detached_document.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<iframe srcdoc="
-<script>
-  savedTop = top;
-  frameElement.remove();
-
-  document.interestCohort()
-    .catch(error => savedTop.document.body.appendChild(document.createElement('div')).appendChild(document.createTextNode('[error from subframe document] ' + error)));
-</script>"></iframe>
\ No newline at end of file
diff --git a/chrome/test/data/federated_learning/interest_cohort_api_origin_trial.html b/chrome/test/data/federated_learning/interest_cohort_api_origin_trial.html
deleted file mode 100644
index d87fafe..0000000
--- a/chrome/test/data/federated_learning/interest_cohort_api_origin_trial.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html>
-<!-- Generate this token with the command:
-generate_token.py https://example.test InterestCohortAPI --expire-timestamp=2000000000 -->
-<meta http-equiv="origin-trial" content="A9oBaKunexGq3fPd6P0cPXicqbLxccMCXZcXlVICMaBk61Jl0yBoCSxfwDdbDFh0n+XevlYAvTMEt2IYV+na2QUAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLnRlc3Q6NDQzIiwgImZlYXR1cmUiOiAiSW50ZXJlc3RDb2hvcnRBUEkiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=" />
-<iframe id="test"></iframe>
-</html>
diff --git a/chrome/test/data/federated_learning/maybe_ad_script.js b/chrome/test/data/federated_learning/maybe_ad_script.js
deleted file mode 100644
index e69de29..0000000
--- a/chrome/test/data/federated_learning/maybe_ad_script.js
+++ /dev/null
diff --git a/chrome/test/data/federated_learning/page_with_script_and_iframe.html b/chrome/test/data/federated_learning/page_with_script_and_iframe.html
deleted file mode 100644
index f7b2963..0000000
--- a/chrome/test/data/federated_learning/page_with_script_and_iframe.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html>
-<body>
-<script src="maybe_ad_script.js"></script>
-<iframe src="../title1.html" id="test"></iframe>
-</body>
-</html>
\ No newline at end of file
diff --git a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none.html b/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none.html
deleted file mode 100644
index f7b2963..0000000
--- a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html>
-<body>
-<script src="maybe_ad_script.js"></script>
-<iframe src="../title1.html" id="test"></iframe>
-</body>
-</html>
\ No newline at end of file
diff --git a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none.html.mock-http-headers b/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none.html.mock-http-headers
deleted file mode 100644
index e53ae084..0000000
--- a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none.html.mock-http-headers
+++ /dev/null
@@ -1,2 +0,0 @@
-HTTP/1.1 200 OK
-Permissions-Policy: interest-cohort=()
\ No newline at end of file
diff --git a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none_legacy.html b/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none_legacy.html
deleted file mode 100644
index f7b2963..0000000
--- a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none_legacy.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html>
-<body>
-<script src="maybe_ad_script.js"></script>
-<iframe src="../title1.html" id="test"></iframe>
-</body>
-</html>
\ No newline at end of file
diff --git a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none_legacy.html.mock-http-headers b/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none_legacy.html.mock-http-headers
deleted file mode 100644
index aefa9fe6..0000000
--- a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_none_legacy.html.mock-http-headers
+++ /dev/null
@@ -1,2 +0,0 @@
-HTTP/1.1 200 OK
-Feature-Policy: interest-cohort 'none'
\ No newline at end of file
diff --git a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_self_legacy.html b/chrome/test/data/federated_learning/permissions_policy_interest_cohort_self_legacy.html
deleted file mode 100644
index f7b2963..0000000
--- a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_self_legacy.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html>
-<body>
-<script src="maybe_ad_script.js"></script>
-<iframe src="../title1.html" id="test"></iframe>
-</body>
-</html>
\ No newline at end of file
diff --git a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_self_legacy.html.mock-http-headers b/chrome/test/data/federated_learning/permissions_policy_interest_cohort_self_legacy.html.mock-http-headers
deleted file mode 100644
index aeb5e83b..0000000
--- a/chrome/test/data/federated_learning/permissions_policy_interest_cohort_self_legacy.html.mock-http-headers
+++ /dev/null
@@ -1,2 +0,0 @@
-HTTP/1.1 200 OK
-Permissions-Policy: interest-cohort=self
\ No newline at end of file
diff --git a/chrome/test/data/webui/new_tab_page/realbox/realbox_test.js b/chrome/test/data/webui/new_tab_page/realbox/realbox_test.js
index 1a124d59..fecff83 100644
--- a/chrome/test/data/webui/new_tab_page/realbox/realbox_test.js
+++ b/chrome/test/data/webui/new_tab_page/realbox/realbox_test.js
@@ -355,14 +355,14 @@
   test('realbox default Google G icon', async () => {
     // Arrange.
     loadTimeData.overrideValues({
-      realboxDefaultIcon: 'google_g.png',
+      realboxDefaultIcon: 'realbox/icons/google_g.svg',
     });
     PolymerTest.clearBody();
     realbox = document.createElement('ntp-realbox');
     document.body.appendChild(realbox);
 
     // Assert.
-    assertIconBackgroundImageUrl(realbox.$.icon, 'google_g.png');
+    assertIconBackgroundImageUrl(realbox.$.icon, 'realbox/icons/google_g.svg');
 
     // Restore.
     loadTimeData.overrideValues({
diff --git a/chrome/test/data/webui/settings/chromeos/internet_page_tests.js b/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
index daff475..47599635 100644
--- a/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
@@ -311,6 +311,31 @@
       }
 
       test(
+          'should show add VPN button when allow only policy WiFi networks ' +
+              'to connect is enabled',
+          async function() {
+            await init();
+            internetPage.globalPolicy_ = {
+              allowOnlyPolicyWifiNetworksToConnect: true,
+            };
+            clickAddConnectionsButton();
+
+            const mojom = chromeos.networkConfig.mojom;
+            setNetworksForTest([
+              OncMojo.getDefaultNetworkState(mojom.NetworkType.kVPN, 'vpn'),
+            ]);
+            mojoApi_.setDeviceStateForTest({
+              type: mojom.NetworkType.kVPN,
+              deviceState: mojom.DeviceStateType.kEnabled
+            });
+
+            return flushAsync().then(() => {
+              assertTrue(
+                  test_util.isVisible(internetPage.$$('#add-vpn-label')));
+            });
+          });
+
+      test(
           'should show VPN policy indicator when VPN is disabled',
           async function() {
             await init();
diff --git a/chrome/test/data/webui/settings/payments_section_test.ts b/chrome/test/data/webui/settings/payments_section_test.ts
index 71189eb..98503fa 100644
--- a/chrome/test/data/webui/settings/payments_section_test.ts
+++ b/chrome/test/data/webui/settings/payments_section_test.ts
@@ -42,6 +42,7 @@
     document.body.innerHTML = '';
     loadTimeData.overrideValues({
       migrationEnabled: true,
+      virtualCardEnrollmentEnabled: true,
     });
   });
 
@@ -265,6 +266,23 @@
     assertTrue(!!outlinkButton);
   });
 
+  test(
+      'verifyCreditCardRowButtonIsDropdownWhenVirtualCardEnrollEligible',
+      function() {
+        const creditCard = createCreditCardEntry();
+        creditCard.metadata!.isLocal = false;
+        creditCard.metadata!.isVirtualCardEnrollmentEligible = true;
+        creditCard.metadata!.isVirtualCardEnrolled = false;
+        const section = createPaymentsSection(
+            [creditCard], /*upiIds=*/[], /*prefValues=*/ {});
+        const rowShadowRoot = getCardRowShadowRoot(section.$.paymentsList);
+        const menuButton = rowShadowRoot.querySelector('#creditCardMenu');
+        assertTrue(!!menuButton);
+        const outlinkButton =
+            rowShadowRoot.querySelector('cr-icon-button.icon-external');
+        assertFalse(!!outlinkButton);
+      });
+
   test('verifyAddVsEditCreditCardTitle', function() {
     const newCreditCard = createEmptyCreditCardEntry();
     const newCreditCardDialog = createCreditCardDialog(newCreditCard);
@@ -420,6 +438,8 @@
     // When credit card is local, |isCached| will be undefined.
     creditCard.metadata!.isLocal = true;
     creditCard.metadata!.isCached = undefined;
+    creditCard.metadata!.isVirtualCardEnrollmentEligible = false;
+    creditCard.metadata!.isVirtualCardEnrolled = false;
 
     const section =
         createPaymentsSection([creditCard], /*upiIds=*/[], /*prefValues=*/ {});
@@ -432,13 +452,15 @@
         rowShadowRoot.querySelector<HTMLElement>('#creditCardMenu');
     assertTrue(!!menuButton);
 
-    menuButton!.click();
+    menuButton.click();
     flush();
 
     // Menu should have 2 options.
     assertFalse(section.$.menuEditCreditCard.hidden);
     assertFalse(section.$.menuRemoveCreditCard.hidden);
     assertTrue(section.$.menuClearCreditCard.hidden);
+    assertTrue(section.$.menuAddVirtualCard.hidden);
+    assertTrue(section.$.menuRemoveVirtualCard.hidden);
 
     section.$.creditCardSharedMenu.close();
     flush();
@@ -449,6 +471,8 @@
 
     creditCard.metadata!.isLocal = false;
     creditCard.metadata!.isCached = true;
+    creditCard.metadata!.isVirtualCardEnrollmentEligible = false;
+    creditCard.metadata!.isVirtualCardEnrolled = false;
 
     const section =
         createPaymentsSection([creditCard], /*upiIds=*/[], /*prefValues=*/ {});
@@ -461,13 +485,15 @@
         rowShadowRoot.querySelector<HTMLElement>('#creditCardMenu');
     assertTrue(!!menuButton);
 
-    menuButton!.click();
+    menuButton.click();
     flush();
 
     // Menu should have 2 options.
     assertFalse(section.$.menuEditCreditCard.hidden);
     assertTrue(section.$.menuRemoveCreditCard.hidden);
     assertFalse(section.$.menuClearCreditCard.hidden);
+    assertTrue(section.$.menuAddVirtualCard.hidden);
+    assertTrue(section.$.menuRemoveVirtualCard.hidden);
 
     section.$.creditCardSharedMenu.close();
     flush();
@@ -478,6 +504,8 @@
 
     creditCard.metadata!.isLocal = false;
     creditCard.metadata!.isCached = false;
+    creditCard.metadata!.isVirtualCardEnrollmentEligible = false;
+    creditCard.metadata!.isVirtualCardEnrolled = false;
 
     const section =
         createPaymentsSection([creditCard], /*upiIds=*/[], /*prefValues=*/ {});
@@ -489,6 +517,74 @@
     assertFalse(!!rowShadowRoot.querySelector('#creditCardMenu'));
   });
 
+  test('verifyVirtualCardEligibleCreditCardMenu', function() {
+    const creditCard = createCreditCardEntry();
+
+    creditCard.metadata!.isLocal = false;
+    creditCard.metadata!.isCached = false;
+    creditCard.metadata!.isVirtualCardEnrollmentEligible = true;
+    creditCard.metadata!.isVirtualCardEnrolled = false;
+
+    const section =
+        createPaymentsSection([creditCard], /*upiIds=*/[], /*prefValues=*/ {});
+    assertEquals(1, getLocalAndServerCreditCardListItems().length);
+
+    // Server cards that are eligible for virtual card enrollment should show
+    // the overflow menu.
+    const rowShadowRoot = getCardRowShadowRoot(section.$.paymentsList);
+    assertFalse(!!rowShadowRoot.querySelector('#remoteCreditCardLink'));
+    const menuButton =
+        rowShadowRoot.querySelector<HTMLElement>('#creditCardMenu');
+    assertTrue(!!menuButton);
+
+    menuButton.click();
+    flush();
+
+    // Menu should have 2 options.
+    assertFalse(section.$.menuEditCreditCard.hidden);
+    assertTrue(section.$.menuRemoveCreditCard.hidden);
+    assertTrue(section.$.menuClearCreditCard.hidden);
+    assertFalse(section.$.menuAddVirtualCard.hidden);
+    assertTrue(section.$.menuRemoveVirtualCard.hidden);
+
+    section.$.creditCardSharedMenu.close();
+    flush();
+  });
+
+  test('verifyVirtualCardEnrolledCreditCardMenu', function() {
+    const creditCard = createCreditCardEntry();
+
+    creditCard.metadata!.isLocal = false;
+    creditCard.metadata!.isCached = false;
+    creditCard.metadata!.isVirtualCardEnrollmentEligible = true;
+    creditCard.metadata!.isVirtualCardEnrolled = true;
+
+    const section =
+        createPaymentsSection([creditCard], /*upiIds=*/[], /*prefValues=*/ {});
+    assertEquals(1, getLocalAndServerCreditCardListItems().length);
+
+    // Server cards that are eligible for virtual card enrollment should show
+    // the overflow menu.
+    const rowShadowRoot = getCardRowShadowRoot(section.$.paymentsList);
+    assertFalse(!!rowShadowRoot.querySelector('#remoteCreditCardLink'));
+    const menuButton =
+        rowShadowRoot.querySelector<HTMLElement>('#creditCardMenu');
+    assertTrue(!!menuButton);
+
+    menuButton.click();
+    flush();
+
+    // Menu should have 2 options.
+    assertFalse(section.$.menuEditCreditCard.hidden);
+    assertTrue(section.$.menuRemoveCreditCard.hidden);
+    assertTrue(section.$.menuClearCreditCard.hidden);
+    assertTrue(section.$.menuAddVirtualCard.hidden);
+    assertFalse(section.$.menuRemoveVirtualCard.hidden);
+
+    section.$.creditCardSharedMenu.close();
+    flush();
+  });
+
   test('verifyMigrationButtonNotShownIfMigrationNotEnabled', function() {
     // Mock prerequisites are not met.
     loadTimeData.overrideValues({migrationEnabled: false});
diff --git a/chrome/updater/updater.cc b/chrome/updater/updater.cc
index 56e4394f..2630699 100644
--- a/chrome/updater/updater.cc
+++ b/chrome/updater/updater.cc
@@ -207,6 +207,24 @@
                                                               : "";
 }
 
+constexpr const char* BuildFlavor() {
+#if defined(NBEDUG)
+  return "opt";
+#else
+  return "debug";
+#endif
+}
+
+constexpr const char* BuildArch() {
+#if defined(ARCH_CPU_64_BITS)
+  return "64 bits";
+#elif defined(ARCH_CPU_32_BITS)
+  return "32 bits";
+#else
+#error CPU architecture is unknown.
+#endif
+}
+
 }  // namespace
 
 int UpdaterMain(int argc, const char* const* argv) {
@@ -220,7 +238,8 @@
   const UpdaterScope updater_scope = GetUpdaterScope();
   InitLogging(updater_scope);
 
-  VLOG(1) << "Version " << kUpdaterVersion
+  VLOG(1) << "Version " << kUpdaterVersion << ", " << BuildFlavor() << ", "
+          << BuildArch()
           << ", command line: " << command_line->GetCommandLineString();
   const int retval = HandleUpdaterCommands(updater_scope, command_line);
   VLOG(1) << __func__ << " (--" << GetUpdaterCommand(command_line) << ")"
diff --git a/chrome/updater/win/BUILD.gn b/chrome/updater/win/BUILD.gn
index a72ba503..bb76ea2 100644
--- a/chrome/updater/win/BUILD.gn
+++ b/chrome/updater/win/BUILD.gn
@@ -105,8 +105,16 @@
 }
 
 process_version_rc_template("version_resources") {
+  _product_fullname = "$updater_product_full_name " + "($current_cpu)"
+  if (is_debug) {
+    _product_fullname += " (debug)"
+  }
   sources = [ "updater.ver" ]
   output = "$target_gen_dir/updater_exe.rc"
+  extra_args = [
+    "-e",
+    "PRODUCT_FULLNAME=\"$_product_fullname\"",
+  ]
 }
 
 source_set("tag_extractor") {
diff --git a/chromecast/cast_core/runtime/browser/runtime_application.cc b/chromecast/cast_core/runtime/browser/runtime_application.cc
index 2ca046c..2dbd636c 100644
--- a/chromecast/cast_core/runtime/browser/runtime_application.cc
+++ b/chromecast/cast_core/runtime/browser/runtime_application.cc
@@ -6,18 +6,12 @@
 
 namespace chromecast {
 
-RuntimeApplication::RuntimeApplication(
-    std::string cast_session_id,
-    cast::common::ApplicationConfig app_config)
-    : cast_session_id_(std::move(cast_session_id)),
-      app_config_(std::move(app_config)) {}
-
 RuntimeApplication::~RuntimeApplication() = default;
 
 std::ostream& operator<<(std::ostream& os, const RuntimeApplication& app) {
-  return os << "app_id=" << app.app_config().app_id() << " ("
-            << app.app_config().display_name()
-            << "), session_id=" << app.cast_session_id()
+  return os << "app_id=" << app.GetAppConfig().app_id() << " ("
+            << app.GetAppConfig().display_name()
+            << "), session_id=" << app.GetCastSessionId()
             << ", url=" << app.GetApplicationUrl();
 }
 
diff --git a/chromecast/cast_core/runtime/browser/runtime_application.h b/chromecast/cast_core/runtime/browser/runtime_application.h
index 78c83e2e..120c2a5 100644
--- a/chromecast/cast_core/runtime/browser/runtime_application.h
+++ b/chromecast/cast_core/runtime/browser/runtime_application.h
@@ -24,17 +24,14 @@
  public:
   using StatusCallback = base::OnceCallback<void(grpc::Status)>;
 
-  RuntimeApplication(std::string cast_session_id,
-                     cast::common::ApplicationConfig app_config);
+  RuntimeApplication() = default;
   virtual ~RuntimeApplication() = 0;
 
   // NOTE: These fields are the empty string until after Load().
-  const cast::common::ApplicationConfig& app_config() const {
-    return app_config_;
-  }
+  virtual const cast::common::ApplicationConfig& GetAppConfig() const = 0;
 
   // NOTE: These fields are the empty string until after Load().
-  const std::string& cast_session_id() const { return cast_session_id_; }
+  virtual const std::string& GetCastSessionId() const = 0;
 
   // Returns the Cast application URL.
   virtual const GURL& GetApplicationUrl() const = 0;
@@ -62,10 +59,6 @@
 
   // Returns whether this instance is associated with cast streaming.
   virtual bool IsStreamingApplication() const = 0;
-
- private:
-  const std::string cast_session_id_;
-  const cast::common::ApplicationConfig app_config_;
 };
 
 std::ostream& operator<<(std::ostream& os, const RuntimeApplication& app);
diff --git a/chromecast/cast_core/runtime/browser/runtime_application_base.cc b/chromecast/cast_core/runtime/browser/runtime_application_base.cc
index 7cd0419..91921ad 100644
--- a/chromecast/cast_core/runtime/browser/runtime_application_base.cc
+++ b/chromecast/cast_core/runtime/browser/runtime_application_base.cc
@@ -19,7 +19,8 @@
     mojom::RendererType renderer_type_used,
     CastWebService* web_service,
     scoped_refptr<base::SequencedTaskRunner> task_runner)
-    : RuntimeApplication(std::move(cast_session_id), std::move(app_config)),
+    : cast_session_id_(std::move(cast_session_id)),
+      app_config_(std::move(app_config)),
       web_service_(web_service),
       task_runner_(std::move(task_runner)),
       renderer_type_(renderer_type_used) {
@@ -42,6 +43,15 @@
   return *cast_media_service_grpc_endpoint_;
 }
 
+const cast::common::ApplicationConfig& RuntimeApplicationBase::GetAppConfig()
+    const {
+  return app_config_;
+}
+
+const std::string& RuntimeApplicationBase::GetCastSessionId() const {
+  return cast_session_id_;
+}
+
 void RuntimeApplicationBase::Load(cast::runtime::LoadApplicationRequest request,
                                   StatusCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -136,7 +146,7 @@
   const std::vector<std::string> additional_feature_permission_origins;
   // TODO(b/203580094): Currently we assume the app is not audio only.
   GetCastWebContents()->SetAppProperties(
-      app_config().app_id(), cast_session_id(), false /*is_audio_app*/,
+      GetAppConfig().app_id(), GetCastSessionId(), false /*is_audio_app*/,
       GetApplicationUrl(), false /*enforce_feature_permissions*/,
       feature_permissions, additional_feature_permission_origins);
   GetCastWebContents()->LoadUrl(GetApplicationUrl());
@@ -196,7 +206,7 @@
 
   auto call = core_app_stub_->CreateCall<
       cast::v2::CoreApplicationServiceStub::SetApplicationStatus>();
-  call.request().set_cast_session_id(cast_session_id());
+  call.request().set_cast_session_id(GetCastSessionId());
   call.request().set_state(state);
   if (state == cast::v2::ApplicationStatusRequest::STOPPED) {
     call.request().set_stop_reason(
@@ -214,7 +224,7 @@
   mojom::CastWebViewParamsPtr params = mojom::CastWebViewParams::New();
   params->renderer_type = renderer_type_;
   params->handle_inner_contents = true;
-  params->session_id = cast_session_id();
+  params->session_id = GetCastSessionId();
 #if DCHECK_IS_ON()
   params->enabled_for_dev = true;
 #endif
diff --git a/chromecast/cast_core/runtime/browser/runtime_application_base.h b/chromecast/cast_core/runtime/browser/runtime_application_base.h
index 53d2f6e..63cdf94 100644
--- a/chromecast/cast_core/runtime/browser/runtime_application_base.h
+++ b/chromecast/cast_core/runtime/browser/runtime_application_base.h
@@ -75,13 +75,15 @@
   virtual cast::utils::GrpcStatusOr<cast::web::MessagePortStatus>
   HandlePortMessage(cast::web::Message message) = 0;
 
- private:
   // RuntimeApplication implementation:
+  const cast::common::ApplicationConfig& GetAppConfig() const override;
+  const std::string& GetCastSessionId() const override;
   void Load(cast::runtime::LoadApplicationRequest request,
             StatusCallback callback) final;
   void Launch(cast::runtime::LaunchApplicationRequest request,
               StatusCallback callback) final;
 
+ private:
   // RuntimeApplicationService handlers:
   void HandleSetUrlRewriteRules(
       cast::v2::SetUrlRewriteRulesRequest request,
@@ -99,6 +101,9 @@
   // Notifies that the application has been initialized.
   void OnApplicationInitialized();
 
+  const std::string cast_session_id_;
+  const cast::common::ApplicationConfig app_config_;
+
   // The |web_service_| used to create |cast_web_view_|.
   CastWebService* const web_service_;
   // The WebView associated with the window in which the Cast application is
diff --git a/chromecast/cast_core/runtime/browser/runtime_application_dispatcher.cc b/chromecast/cast_core/runtime/browser/runtime_application_dispatcher.cc
index 0c7d70c..3cd9c08 100644
--- a/chromecast/cast_core/runtime/browser/runtime_application_dispatcher.cc
+++ b/chromecast/cast_core/runtime/browser/runtime_application_dispatcher.cc
@@ -189,8 +189,8 @@
 
   // Reset the app only after the response is constructed.
   cast::runtime::StopApplicationResponse response;
-  response.set_app_id(app_->app_config().app_id());
-  response.set_cast_session_id(app_->cast_session_id());
+  response.set_app_id(app_->GetAppConfig().app_id());
+  response.set_cast_session_id(app_->GetCastSessionId());
 
   ResetApp();
   reactor->Write(std::move(response));
diff --git a/chromecast/cast_core/runtime/browser/streaming_runtime_application.cc b/chromecast/cast_core/runtime/browser/streaming_runtime_application.cc
index 43c04520..4710f0a8 100644
--- a/chromecast/cast_core/runtime/browser/streaming_runtime_application.cc
+++ b/chromecast/cast_core/runtime/browser/streaming_runtime_application.cc
@@ -119,7 +119,7 @@
   receiver_session_client_ = std::make_unique<StreamingReceiverSessionClient>(
       task_runner(), network_context_getter_, std::move(server_port),
       GetCastWebContents(), this,
-      /* supports_audio= */ app_config().app_id() !=
+      /* supports_audio= */ GetAppConfig().app_id() !=
           openscreen::cast::GetIosAppStreamingAudioVideoAppId(),
       /* supports_video= */ true);
   receiver_session_client_->LaunchStreamingReceiverAsync();
diff --git a/chromecast/cast_core/runtime/browser/web_runtime_application.cc b/chromecast/cast_core/runtime/browser/web_runtime_application.cc
index 597dc5e9..722738c5 100644
--- a/chromecast/cast_core/runtime/browser/web_runtime_application.cc
+++ b/chromecast/cast_core/runtime/browser/web_runtime_application.cc
@@ -25,7 +25,7 @@
                              mojom::RendererType::MOJO_RENDERER,
                              web_service,
                              std::move(task_runner)),
-      app_url_(app_config().cast_web_app_config().url()) {}
+      app_url_(GetAppConfig().cast_web_app_config().url()) {}
 
 WebRuntimeApplication::~WebRuntimeApplication() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -92,7 +92,7 @@
   // Bind inner CastWebContents with the same session id and app id as the
   // root CastWebContents so that the same url rewrites are applied.
   inner_contents->SetAppProperties(
-      app_config().app_id(), cast_session_id(), false /*is_audio_app*/,
+      GetAppConfig().app_id(), GetCastSessionId(), false /*is_audio_app*/,
       GetApplicationUrl(), false /*enforce_feature_permissions*/,
       feature_permissions, additional_feature_permission_origins);
 
diff --git a/chromeos/components/quick_answers/search_result_parsers/definition_result_parser_unittest.cc b/chromeos/components/quick_answers/search_result_parsers/definition_result_parser_unittest.cc
index 357d174a..da7e57d 100644
--- a/chromeos/components/quick_answers/search_result_parsers/definition_result_parser_unittest.cc
+++ b/chromeos/components/quick_answers/search_result_parsers/definition_result_parser_unittest.cc
@@ -70,7 +70,7 @@
 
   void SetHeadWord(Value* result, const std::string& headword) {
     result->FindListPath("dictionaryResult.entries")
-        ->GetList()[0]
+        ->GetListDeprecated()[0]
         .SetStringPath("headword", headword);
   }
 
diff --git a/chromeos/network/cellular_policy_handler.cc b/chromeos/network/cellular_policy_handler.cc
index 762c0075..15a6281 100644
--- a/chromeos/network/cellular_policy_handler.cc
+++ b/chromeos/network/cellular_policy_handler.cc
@@ -35,13 +35,14 @@
 CellularPolicyHandler::InstallPolicyESimRequest::InstallPolicyESimRequest(
     const std::string& smdp_address,
     const base::Value& onc_config)
-    : smdp_address(smdp_address), onc_config(onc_config.Clone()) {}
+    : smdp_address(smdp_address),
+      onc_config(onc_config.Clone()),
+      retry_backoff(&kRetryBackoffPolicy) {}
 
 CellularPolicyHandler::InstallPolicyESimRequest::~InstallPolicyESimRequest() =
     default;
 
-CellularPolicyHandler::CellularPolicyHandler()
-    : retry_backoff_(&kRetryBackoffPolicy) {}
+CellularPolicyHandler::CellularPolicyHandler() = default;
 
 CellularPolicyHandler::~CellularPolicyHandler() = default;
 
@@ -57,19 +58,8 @@
 
 void CellularPolicyHandler::InstallESim(const std::string& smdp_address,
                                         const base::Value& onc_config) {
-  const std::string* guid =
-      onc_config.FindStringKey(::onc::network_config::kGUID);
-  DCHECK(guid);
-  // Invalidate current request if a new install request for the same policy is
-  // received. This prevents retry requests for bad SMDP address from
-  // unnecessarily blocking the queue.
-  if (retry_backoff_.failure_count() >= 1 && GetCurrentPolicyGuid() == *guid) {
-    InvalidateCurrentRequest();
-  }
-
-  remaining_install_requests_.push_back(
+  PushRequestAndProcess(
       std::make_unique<InstallPolicyESimRequest>(smdp_address, onc_config));
-  ProcessRequests();
 }
 
 void CellularPolicyHandler::ProcessRequests() {
@@ -81,10 +71,6 @@
   if (is_installing_)
     return;
 
-  // Reset the state of the backoff so that the next backoff retry starts at
-  // the default initial delay.
-  retry_backoff_.Reset();
-
   is_installing_ = true;
   NET_LOG(EVENT)
       << "Starting installing policy eSIM profile with SMDP address: "
@@ -99,7 +85,8 @@
   if (!euicc_path) {
     NET_LOG(ERROR) << "Error installing policy eSIM profile for SMDP address: "
                    << GetCurrentSmdpAddress() << ": euicc is not found.";
-    PopRequestAndProcessNext();
+    PopRequest();
+    ProcessRequests();
     return;
   }
 
@@ -137,48 +124,54 @@
   return remaining_install_requests_.front()->smdp_address;
 }
 
-std::string CellularPolicyHandler::GetCurrentPolicyGuid() const {
-  DCHECK(is_installing_);
-
-  const std::string* guid =
-      remaining_install_requests_.front()->onc_config.FindStringKey(
-          ::onc::network_config::kGUID);
-  return guid ? *guid : std::string();
-}
-
 void CellularPolicyHandler::OnESimProfileInstallAttemptComplete(
     HermesResponseStatus hermes_status,
     absl::optional<dbus::ObjectPath> profile_path,
     absl::optional<std::string> service_path) {
   DCHECK(is_installing_);
 
+  auto current_request = std::move(remaining_install_requests_.front());
+  PopRequest();
   if (hermes_status == HermesResponseStatus::kSuccess) {
     NET_LOG(EVENT) << "Successfully installed eSIM profile with SMDP address: "
-                   << GetCurrentSmdpAddress();
-    retry_backoff_.InformOfRequest(/*succeeded=*/true);
+                   << current_request->smdp_address;
+    current_request->retry_backoff.InformOfRequest(/*succeeded=*/true);
     managed_network_configuration_handler_->NotifyPolicyAppliedToNetwork(
         *service_path);
-    PopRequestAndProcessNext();
+
+    ProcessRequests();
     return;
   }
 
-  if (retry_backoff_.failure_count() >= kInstallRetryLimit) {
+  if (current_request->retry_backoff.failure_count() >= kInstallRetryLimit) {
     NET_LOG(ERROR) << "Install policy eSIM profile with SMDP address: "
-                   << GetCurrentSmdpAddress() << " failed three times.";
-    PopRequestAndProcessNext();
+                   << current_request->smdp_address << " failed "
+                   << kInstallRetryLimit << " times.";
+    ProcessRequests();
     return;
   }
 
-  retry_backoff_.InformOfRequest(/*succeeded=*/false);
+  current_request->retry_backoff.InformOfRequest(/*succeeded=*/false);
+  base::TimeDelta retry_delay =
+      current_request->retry_backoff.GetTimeUntilRelease();
   NET_LOG(ERROR) << "Install policy eSIM profile failed. Retrying in "
-                 << retry_backoff_.GetTimeUntilRelease();
-  retry_timer_.Start(FROM_HERE, retry_backoff_.GetTimeUntilRelease(),
-                     base::BindOnce(&CellularPolicyHandler::AttemptInstallESim,
-                                    weak_ptr_factory_.GetWeakPtr()));
+                 << retry_delay;
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&CellularPolicyHandler::PushRequestAndProcess,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     std::move(current_request)),
+      retry_delay);
+  ProcessRequests();
 }
 
-void CellularPolicyHandler::PopRequestAndProcessNext() {
-  // Pop out the completed request and process next request.
+void CellularPolicyHandler::PushRequestAndProcess(
+    std::unique_ptr<InstallPolicyESimRequest> request) {
+  remaining_install_requests_.push_back(std::move(request));
+  ProcessRequests();
+}
+
+void CellularPolicyHandler::PopRequest() {
   remaining_install_requests_.pop_front();
   is_installing_ = false;
   if (remaining_install_requests_.empty()) {
@@ -188,18 +181,7 @@
     DCHECK(profile);
 
     managed_network_configuration_handler_->OnCellularPoliciesApplied(*profile);
-    return;
   }
-  ProcessRequests();
-}
-
-void CellularPolicyHandler::InvalidateCurrentRequest() {
-  NET_LOG(EVENT) << "Invalidate current request with SMDP address: "
-                 << GetCurrentSmdpAddress();
-  if (retry_timer_.IsRunning())
-    retry_timer_.Stop();
-  remaining_install_requests_.pop_front();
-  is_installing_ = false;
 }
 
 }  // namespace chromeos
diff --git a/chromeos/network/cellular_policy_handler.h b/chromeos/network/cellular_policy_handler.h
index 808745d..f4e2e4b 100644
--- a/chromeos/network/cellular_policy_handler.h
+++ b/chromeos/network/cellular_policy_handler.h
@@ -30,7 +30,8 @@
 // When installing policy eSIM profiles, the activation code is constructed from
 // the SM-DP+ address in the policy configuration. Install requests are queued
 // and installation is performed one by one. Install attempts are retried for
-// fixed number of tries.
+// fixed number of tries and the request queue doesn't get blocked by the
+// requests that are waiting for retry attempt.
 class COMPONENT_EXPORT(CHROMEOS_NETWORK) CellularPolicyHandler {
  public:
   CellularPolicyHandler();
@@ -69,6 +70,7 @@
 
     const std::string smdp_address;
     base::Value onc_config;
+    net::BackoffEntry retry_backoff;
   };
 
   void ProcessRequests();
@@ -79,8 +81,8 @@
       HermesResponseStatus hermes_status,
       absl::optional<dbus::ObjectPath> profile_path,
       absl::optional<std::string> service_path);
-  void PopRequestAndProcessNext();
-  void InvalidateCurrentRequest();
+  void PushRequestAndProcess(std::unique_ptr<InstallPolicyESimRequest> request);
+  void PopRequest();
 
   CellularESimInstaller* cellular_esim_installer_ = nullptr;
   NetworkProfileHandler* network_profile_handler_ = nullptr;
@@ -90,10 +92,6 @@
   bool is_installing_ = false;
   base::circular_deque<std::unique_ptr<InstallPolicyESimRequest>>
       remaining_install_requests_;
-  base::OneShotTimer retry_timer_;
-
-  // Provides us the backoff timers for AttemptInstallESim().
-  net::BackoffEntry retry_backoff_;
 
   base::WeakPtrFactory<CellularPolicyHandler> weak_ptr_factory_{this};
 };
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt
index 2b3a454..7dbd775 100644
--- a/chromeos/profiles/atom.afdo.newest.txt
+++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-atom-99-4827.0-1643629123-benchmark-99.0.4844.20-r1-redacted.afdo.xz
+chromeos-chrome-amd64-atom-99-4827.0-1643629123-benchmark-99.0.4844.22-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index 720014b..094db9b7 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-99-4827.0-1643628001-benchmark-99.0.4844.20-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-99-4827.0-1643628001-benchmark-99.0.4844.22-r1-redacted.afdo.xz
diff --git a/components/BUILD.gn b/components/BUILD.gn
index a22845f5..4c3fea05 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -308,7 +308,6 @@
       "//components/embedder_support:unit_tests",
       "//components/enterprise/content:unit_tests",
       "//components/favicon/content:unit_tests",
-      "//components/federated_learning:unit_tests",
       "//components/feed:unit_tests",
       "//components/gcm_driver/instance_id:unit_tests",
       "//components/heavy_ad_intervention:unit_tests",
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager.cc b/components/autofill/core/browser/payments/credit_card_save_manager.cc
index 3b6a1b7f..3c7e7797 100644
--- a/components/autofill/core/browser/payments/credit_card_save_manager.cc
+++ b/components/autofill/core/browser/payments/credit_card_save_manager.cc
@@ -339,11 +339,10 @@
 
     if (base::FeatureList::IsEnabled(
             features::kAutofillEnableUpdateVirtualCardEnrollment)) {
-      // After a card is successfully saved to the server, we can now offer
-      // the user to enroll it as a virtual card. |upload_card_response_details|
-      // has fields in the response that will be required for server requests in
-      // the virtual card enrollment flow, so we set them here and start the
-      // flow.
+      // After a card is successfully saved to the server, offer virtual card
+      // enrollment if the card is eligible. |upload_card_response_details| has
+      // fields in the response that will be required for server requests in the
+      // virtual card enrollment flow, so we set them here and start the flow.
       if (upload_card_response_details.virtual_card_enrollment_state ==
           CreditCard::VirtualCardEnrollmentState::UNENROLLED_AND_ELIGIBLE) {
         DCHECK(!upload_card_response_details.card_art_url.is_empty());
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
index eb12f8e..ae0ecf8 100644
--- a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
@@ -5212,7 +5212,7 @@
           upload_card_response_details;
       upload_card_response_details.card_art_url =
           GURL("https://www.example.com/");
-      upload_card_response_details.instrument_id = 3;
+      upload_card_response_details.instrument_id = 9223372036854775807;
       upload_card_response_details.virtual_card_enrollment_state =
           enrollment_state;
 
diff --git a/components/autofill/core/browser/payments/payments_client.cc b/components/autofill/core/browser/payments/payments_client.cc
index 72813c8..0ff1d0e 100644
--- a/components/autofill/core/browser/payments/payments_client.cc
+++ b/components/autofill/core/browser/payments/payments_client.cc
@@ -699,11 +699,14 @@
     upload_card_response_details_.server_id =
         credit_card_id ? *credit_card_id : std::string();
 
-    const absl::optional<int> instrument_id =
-        response.FindIntKey("instrument_id");
-    if (instrument_id.has_value()) {
-      upload_card_response_details_.instrument_id =
-          static_cast<int64_t>(instrument_id.value());
+    const std::string* response_instrument_id =
+        response.FindStringKey("instrument_id");
+    if (response_instrument_id) {
+      int64_t instrument_id;
+      if (base::StringToInt64(base::StringPiece(*response_instrument_id),
+                              &instrument_id)) {
+        upload_card_response_details_.instrument_id = instrument_id;
+      }
     }
 
     const auto* virtual_card_metadata = response.FindKeyOfType(
diff --git a/components/autofill/core/browser/payments/payments_client.h b/components/autofill/core/browser/payments/payments_client.h
index 3070434..2e45a46 100644
--- a/components/autofill/core/browser/payments/payments_client.h
+++ b/components/autofill/core/browser/payments/payments_client.h
@@ -287,8 +287,9 @@
     // |instrument_id| is used by the server as an identifier for the card that
     // was uploaded. Currently, we have it in the UploadCardResponseDetails so
     // that we can send it in the GetDetailsForEnrollRequest in the virtual card
-    // enrollment flow. Should never be empty, if using this field use DCHECKs
-    // to ensure it is populated.
+    // enrollment flow. Will only not be populated in the case of an imperfect
+    // conversion from string to int64_t, or if the server does not return an
+    // instrument id.
     absl::optional<int64_t> instrument_id;
     // |virtual_card_enrollment_state| is used to determine whether we want to
     // pursue further action with the credit card that was uploaded regarding
diff --git a/components/autofill/core/browser/payments/payments_client_unittest.cc b/components/autofill/core/browser/payments/payments_client_unittest.cc
index c61e1b57..e916c84 100644
--- a/components/autofill/core/browser/payments/payments_client_unittest.cc
+++ b/components/autofill/core/browser/payments/payments_client_unittest.cc
@@ -1176,9 +1176,13 @@
 TEST_F(PaymentsClientTest, UploadSuccessInstrumentIdPresent) {
   StartUploading(/*include_cvc=*/true);
   IssueOAuthToken();
-  ReturnResponse(net::HTTP_OK, "{ \"instrument_id\": 3 }");
+  upload_card_response_details_.instrument_id = absl::nullopt;
+
+  // Test the conversion from string to int64_t using the max value for int64_t.
+  ReturnResponse(net::HTTP_OK,
+                 "{ \"instrument_id\": \"9223372036854775807\" }");
   EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_);
-  EXPECT_EQ(upload_card_response_details_.instrument_id, 3);
+  EXPECT_EQ(upload_card_response_details_.instrument_id, 9223372036854775807);
 }
 
 TEST_F(PaymentsClientTest, UploadSuccessVirtualCardEnrollmentStatePresent) {
diff --git a/components/browser_ui/widget/android/BUILD.gn b/components/browser_ui/widget/android/BUILD.gn
index 1d2ad99..99548de2 100644
--- a/components/browser_ui/widget/android/BUILD.gn
+++ b/components/browser_ui/widget/android/BUILD.gn
@@ -18,6 +18,7 @@
     "java/src/org/chromium/components/browser_ui/widget/FadingShadow.java",
     "java/src/org/chromium/components/browser_ui/widget/FadingShadowView.java",
     "java/src/org/chromium/components/browser_ui/widget/InsetObserverView.java",
+    "java/src/org/chromium/components/browser_ui/widget/InsetObserverViewSupplier.java",
     "java/src/org/chromium/components/browser_ui/widget/MaterialCardViewNoShadow.java",
     "java/src/org/chromium/components/browser_ui/widget/MaterialProgressBar.java",
     "java/src/org/chromium/components/browser_ui/widget/MenuOrKeyboardActionController.java",
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/InsetObserverViewSupplier.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/InsetObserverViewSupplier.java
new file mode 100644
index 0000000..60b172a7
--- /dev/null
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/InsetObserverViewSupplier.java
@@ -0,0 +1,56 @@
+// Copyright 2022 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.components.browser_ui.widget;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.UnownedUserDataKey;
+import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.base.supplier.ObservableSupplierImpl;
+import org.chromium.base.supplier.UnownedUserDataSupplier;
+import org.chromium.ui.base.WindowAndroid;
+
+/**
+ * A {@link UnownedUserDataSupplier} which manages the supplier and UnownedUserData for a
+ * {@link InsetObserverView}.
+ */
+public class InsetObserverViewSupplier extends UnownedUserDataSupplier<InsetObserverView> {
+    private static final UnownedUserDataKey<InsetObserverViewSupplier> KEY =
+            new UnownedUserDataKey<InsetObserverViewSupplier>(InsetObserverViewSupplier.class);
+    private static ObservableSupplierImpl<InsetObserverView> sInstanceForTesting;
+
+    /**
+     * Returns {@link InsetObserverView} supplier associated with the given {@link
+     * WindowAndroid}.
+     */
+    public static ObservableSupplier<InsetObserverView> from(
+            @Nullable WindowAndroid windowAndroid) {
+        if (windowAndroid == null) return null;
+        if (sInstanceForTesting != null) return sInstanceForTesting;
+        return KEY.retrieveDataFromHost(windowAndroid.getUnownedUserDataHost());
+    }
+
+    /** Retrieves a {@link InsetObserverView} from {@link WindowAndroid}.  */
+    public static @Nullable InsetObserverView getValueOrNullFrom(
+            @Nullable WindowAndroid windowAndroid) {
+        ObservableSupplier<InsetObserverView> supplier = from(windowAndroid);
+        return supplier == null ? null : supplier.get();
+    }
+
+    /** Sets an instance for testing. */
+    @VisibleForTesting
+    public static void setInstanceForTesting(InsetObserverView insetObserverView) {
+        if (sInstanceForTesting == null) {
+            sInstanceForTesting = new ObservableSupplierImpl<>();
+        }
+        sInstanceForTesting.set(insetObserverView);
+    }
+
+    /** Constructor. */
+    public InsetObserverViewSupplier() {
+        super(KEY);
+    }
+}
diff --git a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/EventConstants.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/EventConstants.java
index 1432c992..0fc00b4 100644
--- a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/EventConstants.java
+++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/EventConstants.java
@@ -192,6 +192,8 @@
 
     public static final String TAB_SWITCHER_BUTTON_CLICKED = "tab_switcher_button_clicked";
 
+    public static final String FOREGROUND_SESSION_DESTROYED = "foreground_session_destroyed";
+
     /** Read later related events. */
     public static final String APP_MENU_BOOKMARK_STAR_ICON_PRESSED =
             "app_menu_bookmark_star_icon_pressed";
diff --git a/components/feature_engagement/public/feature_configurations.cc b/components/feature_engagement/public/feature_configurations.cc
index 518f8d4..297374b 100644
--- a/components/feature_engagement/public/feature_configurations.cc
+++ b/components/feature_engagement/public/feature_configurations.cc
@@ -400,6 +400,24 @@
     return config;
   }
 
+  if (kIPHLowUserEngagementDetectorFeature.name == feature->name) {
+    absl::optional<FeatureConfig> config = FeatureConfig();
+    config->valid = true;
+    config->availability = Comparator(GREATER_THAN_OR_EQUAL, 14);
+    config->session_rate = Comparator(ANY, 0);
+    config->session_rate_impact.type = SessionRateImpact::Type::NONE;
+    config->blocked_by.type = BlockedBy::Type::NONE;
+    config->blocking.type = Blocking::Type::NONE;
+    config->trigger = EventConfig("low_user_engagement_detector_trigger",
+                                  Comparator(ANY, 0), 90, 90);
+    config->used = EventConfig("low_user_engagement_detector_used",
+                               Comparator(ANY, 0), 90, 90);
+    config->event_configs.insert(EventConfig("foreground_session_destroyed",
+                                             Comparator(LESS_THAN_OR_EQUAL, 3),
+                                             14, 14));
+    return config;
+  }
+
   if (kIPHFeedHeaderMenuFeature.name == feature->name) {
     // A config that allows the feed header menu IPH to be shown only once when
     // the user starts using a version of the feed that uploads click and view
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc
index a04726a..2bc9b6f1 100644
--- a/components/feature_engagement/public/feature_constants.cc
+++ b/components/feature_engagement/public/feature_constants.cc
@@ -195,6 +195,8 @@
     "IPH_KeyboardAccessoryPaymentFilling", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kIPHKeyboardAccessoryPaymentOfferFeature{
     "IPH_KeyboardAccessoryPaymentOffer", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kIPHLowUserEngagementDetectorFeature{
+    "IPH_LowUserEngagementDetector", base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kIPHNewTabPageHomeButtonFeature{
     "IPH_NewTabPageHomeButton", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kIPHMicToolbarFeature{"IPH_MicToolbar",
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h
index 2b4e37c..ffc1827b 100644
--- a/components/feature_engagement/public/feature_constants.h
+++ b/components/feature_engagement/public/feature_constants.h
@@ -120,6 +120,7 @@
 extern const base::Feature kIPHKeyboardAccessoryPasswordFillingFeature;
 extern const base::Feature kIPHKeyboardAccessoryPaymentFillingFeature;
 extern const base::Feature kIPHKeyboardAccessoryPaymentOfferFeature;
+extern const base::Feature kIPHLowUserEngagementDetectorFeature;
 extern const base::Feature kIPHMicToolbarFeature;
 extern const base::Feature kIPHNewTabPageHomeButtonFeature;
 extern const base::Feature kIPHPageInfoFeature;
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc
index 6d15ad10..69c9ec1a 100644
--- a/components/feature_engagement/public/feature_list.cc
+++ b/components/feature_engagement/public/feature_list.cc
@@ -70,6 +70,7 @@
     &kIPHKeyboardAccessoryPasswordFillingFeature,
     &kIPHKeyboardAccessoryPaymentFillingFeature,
     &kIPHKeyboardAccessoryPaymentOfferFeature,
+    &kIPHLowUserEngagementDetectorFeature,
     &kIPHMicToolbarFeature,
     &kIPHNewTabPageHomeButtonFeature,
     &kIPHPageInfoFeature,
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h
index 222d2b5e..255ee516 100644
--- a/components/feature_engagement/public/feature_list.h
+++ b/components/feature_engagement/public/feature_list.h
@@ -338,6 +338,7 @@
         VARIATION_ENTRY(kIPHVideoTutorialTryNowFeature),
         VARIATION_ENTRY(kIPHExploreSitesTileFeature),
         VARIATION_ENTRY(kIPHFeedHeaderMenuFeature),
+        VARIATION_ENTRY(kIPHFeedSwipeRefresh),
         VARIATION_ENTRY(kIPHShareScreenshotFeature),
         VARIATION_ENTRY(kIPHSharingHubLinkToggleFeature),
         VARIATION_ENTRY(kIPHWebFeedFollowFeature),
diff --git a/components/federated_learning/BUILD.gn b/components/federated_learning/BUILD.gn
deleted file mode 100644
index fb66edb..0000000
--- a/components/federated_learning/BUILD.gn
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2020 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.
-
-static_library("federated_learning") {
-  sources = [
-    "features/features.cc",
-    "features/features.h",
-    "floc_constants.cc",
-    "floc_constants.h",
-    "floc_id.cc",
-    "floc_id.h",
-    "floc_sorting_lsh_clusters_service.cc",
-    "floc_sorting_lsh_clusters_service.h",
-    "sim_hash.cc",
-    "sim_hash.h",
-  ]
-
-  public_deps = [
-    "//content/public/common:common",
-    "//third_party/protobuf:protobuf_lite",
-  ]
-
-  deps = [
-    "//base",
-    "//components/prefs:prefs",
-  ]
-}
-
-source_set("unit_tests") {
-  testonly = true
-  sources = [
-    "floc_id_unittest.cc",
-    "floc_sorting_lsh_clusters_service_unittest.cc",
-    "sim_hash_unittest.cc",
-  ]
-
-  deps = [
-    ":federated_learning",
-    "//base",
-    "//base/test:test_support",
-    "//components/prefs:test_support",
-    "//testing/gtest",
-  ]
-}
diff --git a/components/federated_learning/COMMON_METADATA b/components/federated_learning/COMMON_METADATA
deleted file mode 100644
index 0e6c0305..0000000
--- a/components/federated_learning/COMMON_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-team_email: "privacy-sandbox-dev@chromium.org"
diff --git a/components/federated_learning/DEPS b/components/federated_learning/DEPS
deleted file mode 100644
index 9a49fbd..0000000
--- a/components/federated_learning/DEPS
+++ /dev/null
@@ -1,6 +0,0 @@
-include_rules = [
-  "+third_party/protobuf",
-  "+content/public/common",
-  "+components/prefs",
-  "+third_party/blink/public",
-]
diff --git a/components/federated_learning/DIR_METADATA b/components/federated_learning/DIR_METADATA
deleted file mode 100644
index ea6a8e2..0000000
--- a/components/federated_learning/DIR_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-mixins: "//components/federated_learning/COMMON_METADATA"
diff --git a/components/federated_learning/OWNERS b/components/federated_learning/OWNERS
deleted file mode 100644
index 424ff9bd..0000000
--- a/components/federated_learning/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jkarlin@chromium.org
-yaoxia@chromium.org
-
-# TODO(yaoxia): Add a crbug component for FloC.
diff --git a/components/federated_learning/README.md b/components/federated_learning/README.md
deleted file mode 100644
index 63c2c19..0000000
--- a/components/federated_learning/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Federated Learning Component
-The FLoC (Federated Learning of Cohorts) project aims to group users based on
-their browsing habits in a privacy preserving way, that would allow
-interest-based advertising without exposing a user’s browsing history.
-
-This component contains data types (e.g. FlocID) that other layers could access
-(e.g. chrome/browser, services/network).
diff --git a/components/federated_learning/features/features.cc b/components/federated_learning/features/features.cc
deleted file mode 100644
index cd05f26..0000000
--- a/components/federated_learning/features/features.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2020 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/federated_learning/features/features.h"
-
-#include "base/feature_list.h"
-
-namespace federated_learning {
-
-// If enabled, the check for whether the IP address is publicly routable will be
-// bypassed when determining the eligibility for a page to be included in floc
-// computation. This is useful for developers to test FLoC in local environment.
-const base::Feature kFlocBypassIPIsPubliclyRoutableCheck{
-    "FlocBypassIPIsPubliclyRoutableCheck", base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Enables or disables the FlocIdComputed event logging, which happens when a
-// floc id is first computed for a browsing session or is refreshed due to a
-// long period of time has passed since the last computation.
-const base::Feature kFlocIdComputedEventLogging{
-    "FlocIdComputedEventLogging", base::FEATURE_ENABLED_BY_DEFAULT};
-
-// If enabled, pages that had ad resources will be included in floc computation;
-// otherwise, only pages that used the document.interestCohort API will be
-// included. This flag affects a bit to be stored at page viewing time, so it
-// may take a full computation cycle for the floc to meet the configured
-// criteria.
-const base::Feature kFlocPagesWithAdResourcesDefaultIncludedInFlocComputation{
-    "FlocPagesWithAdResourcesDefaultIncludedInFlocComputation",
-    base::FEATURE_DISABLED_BY_DEFAULT};
-
-// The main floc feature for all the subsidiary control and setting params. It's
-// controlling the floc update rate, and the minimum history domain size
-// required.
-// TODO(yaoxia): merge other floc features into this one.
-const base::Feature kFederatedLearningOfCohorts{
-    "FederatedLearningOfCohorts", base::FEATURE_DISABLED_BY_DEFAULT};
-constexpr base::FeatureParam<base::TimeDelta> kFlocIdScheduledUpdateInterval{
-    &kFederatedLearningOfCohorts, "update_interval", base::Days(7)};
-constexpr base::FeatureParam<int> kFlocIdMinimumHistoryDomainSizeRequired{
-    &kFederatedLearningOfCohorts, "minimum_history_domain_size_required", 3};
-constexpr base::FeatureParam<int> kFlocIdFinchConfigVersion{
-    &kFederatedLearningOfCohorts, "finch_config_version", 1};
-
-}  // namespace federated_learning
diff --git a/components/federated_learning/features/features.h b/components/federated_learning/features/features.h
deleted file mode 100644
index 2de1234c..0000000
--- a/components/federated_learning/features/features.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2020 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_FEDERATED_LEARNING_FEATURES_FEATURES_H_
-#define COMPONENTS_FEDERATED_LEARNING_FEATURES_FEATURES_H_
-
-#include "base/feature_list.h"
-#include "base/metrics/field_trial_params.h"
-
-namespace federated_learning {
-
-extern const base::Feature kFlocBypassIPIsPubliclyRoutableCheck;
-extern const base::Feature kFlocIdComputedEventLogging;
-extern const base::Feature
-    kFlocPagesWithAdResourcesDefaultIncludedInFlocComputation;
-
-extern const base::Feature kFederatedLearningOfCohorts;
-extern const base::FeatureParam<base::TimeDelta> kFlocIdScheduledUpdateInterval;
-extern const base::FeatureParam<int> kFlocIdMinimumHistoryDomainSizeRequired;
-extern const base::FeatureParam<int> kFlocIdFinchConfigVersion;
-
-}  // namespace federated_learning
-
-#endif  // COMPONENTS_FEDERATED_LEARNING_FEATURES_FEATURES_H_
diff --git a/components/federated_learning/floc_constants.cc b/components/federated_learning/floc_constants.cc
deleted file mode 100644
index 9974c4f..0000000
--- a/components/federated_learning/floc_constants.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_constants.h"
-
-#include <limits>
-
-namespace federated_learning {
-
-// This is only for experimentation and won't be served to websites.
-const uint8_t kMaxNumberOfBitsInFloc = 50;
-static_assert(kMaxNumberOfBitsInFloc > 0 &&
-                  kMaxNumberOfBitsInFloc <=
-                      std::numeric_limits<uint64_t>::digits,
-              "Number of bits in the floc id must be greater than 0 and no "
-              "greater than 64.");
-
-const char kFlocIdValuePrefKey[] = "federated_learning.floc_id.value";
-
-const char kFlocIdStatusPrefKey[] = "federated_learning.floc_id.status";
-
-const char kFlocIdHistoryBeginTimePrefKey[] =
-    "federated_learning.floc_id.history_begin_time";
-
-const char kFlocIdHistoryEndTimePrefKey[] =
-    "federated_learning.floc_id.history_end_time";
-
-const char kFlocIdFinchConfigVersionPrefKey[] =
-    "federated_learning.floc_id.finch_config_version";
-
-const char kFlocIdSortingLshVersionPrefKey[] =
-    "federated_learning.floc_id.sorting_lsh_version";
-
-const char kFlocIdComputeTimePrefKey[] =
-    "federated_learning.floc_id.compute_time";
-
-const char kManifestFlocComponentFormatKey[] = "floc_component_format";
-
-const int kCurrentFlocComponentFormatVersion = 3;
-
-const uint8_t kSortingLshMaxBits = 7;
-
-const uint32_t kSortingLshBlockedMask = 0b1000000;
-
-const uint32_t kSortingLshSizeMask = 0b0111111;
-
-const base::FilePath::CharType kTopLevelDirectoryName[] =
-    FILE_PATH_LITERAL("Floc");
-
-const base::FilePath::CharType kSortingLshClustersFileName[] =
-    FILE_PATH_LITERAL("SortingLshClusters");
-
-}  // namespace federated_learning
diff --git a/components/federated_learning/floc_constants.h b/components/federated_learning/floc_constants.h
deleted file mode 100644
index 0c5627c3..0000000
--- a/components/federated_learning/floc_constants.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2020 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_FEDERATED_LEARNING_FLOC_CONSTANTS_H_
-#define COMPONENTS_FEDERATED_LEARNING_FLOC_CONSTANTS_H_
-
-#include "base/files/file_path.h"
-
-namespace federated_learning {
-
-extern const uint8_t kMaxNumberOfBitsInFloc;
-
-// ---------------------------
-// For the preferences storage
-// ---------------------------
-extern const char kFlocIdValuePrefKey[];
-extern const char kFlocIdStatusPrefKey[];
-extern const char kFlocIdHistoryBeginTimePrefKey[];
-extern const char kFlocIdHistoryEndTimePrefKey[];
-extern const char kFlocIdFinchConfigVersionPrefKey[];
-extern const char kFlocIdSortingLshVersionPrefKey[];
-extern const char kFlocIdComputeTimePrefKey[];
-extern const char kManifestFlocComponentFormatKey[];
-
-// -----------------------------
-// For the sorting-lsh algorithm
-// -----------------------------
-extern const uint8_t kSortingLshMaxBits;
-extern const uint32_t kSortingLshBlockedMask;
-extern const uint32_t kSortingLshSizeMask;
-
-// ------------------------------
-// For the floc component updater
-// ------------------------------
-extern const int kCurrentFlocComponentFormatVersion;
-
-// The name of the top-level directory under the user data directory that
-// contains all files and subdirectories related to the floc.
-extern const base::FilePath::CharType kTopLevelDirectoryName[];
-
-// The name of the file that stores the sorting-lsh clusters. The file lives
-// under under |kTopLevelDirectoryName|
-extern const base::FilePath::CharType kSortingLshClustersFileName[];
-
-}  // namespace federated_learning
-
-#endif  // COMPONENTS_FEDERATED_LEARNING_FLOC_CONSTANTS_H_
\ No newline at end of file
diff --git a/components/federated_learning/floc_id.cc b/components/federated_learning/floc_id.cc
deleted file mode 100644
index e282b2f..0000000
--- a/components/federated_learning/floc_id.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_id.h"
-
-#include "base/strings/strcat.h"
-#include "base/strings/string_number_conversions.h"
-#include "components/federated_learning/features/features.h"
-#include "components/federated_learning/floc_constants.h"
-#include "components/federated_learning/sim_hash.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
-
-namespace federated_learning {
-
-// static
-uint64_t FlocId::SimHashHistory(
-    const std::unordered_set<std::string>& domains) {
-  return SimHashStrings(domains, kMaxNumberOfBitsInFloc);
-}
-
-// static
-FlocId FlocId::CreateInvalid(Status status) {
-  DCHECK_NE(Status::kValid, status);
-  DCHECK_NE(Status::kInvalidNoStatusPrefs, status);
-  return FlocId(/*id=*/0, status,
-                /*history_begin_time=*/base::Time(),
-                /*history_end_time=*/base::Time(),
-                kFlocIdFinchConfigVersion.Get(),
-                /*sorting_lsh_version=*/0,
-                /*compute_time=*/base::Time::Now());
-}
-
-// static
-FlocId FlocId::CreateValid(uint64_t id,
-                           base::Time history_begin_time,
-                           base::Time history_end_time,
-                           uint32_t sorting_lsh_version) {
-  return FlocId(id, Status::kValid, history_begin_time, history_end_time,
-                kFlocIdFinchConfigVersion.Get(), sorting_lsh_version,
-                /*compute_time=*/base::Time::Now());
-}
-
-FlocId::FlocId(const FlocId& id) = default;
-
-FlocId::~FlocId() = default;
-
-FlocId& FlocId::operator=(const FlocId& id) = default;
-
-FlocId& FlocId::operator=(FlocId&& id) = default;
-
-bool FlocId::IsValid() const {
-  return status_ == Status::kValid;
-}
-
-bool FlocId::operator==(const FlocId& other) const {
-  return id_ == other.id_ && status_ == other.status_ &&
-         history_begin_time_ == other.history_begin_time_ &&
-         history_end_time_ == other.history_end_time_ &&
-         finch_config_version_ == other.finch_config_version_ &&
-         sorting_lsh_version_ == other.sorting_lsh_version_ &&
-         compute_time_ == other.compute_time_;
-}
-
-bool FlocId::operator!=(const FlocId& other) const {
-  return !(*this == other);
-}
-
-blink::mojom::InterestCohortPtr FlocId::ToInterestCohortForJsApi() const {
-  // TODO(yaoxia): consider returning the version part even when floc is
-  // invalid.
-
-  DCHECK_EQ(Status::kValid, status_);
-
-  blink::mojom::InterestCohortPtr result = blink::mojom::InterestCohort::New();
-  result->id = base::NumberToString(id_);
-  result->version =
-      base::StrCat({"chrome.", base::NumberToString(finch_config_version_), ".",
-                    base::NumberToString(sorting_lsh_version_)});
-  return result;
-}
-
-uint64_t FlocId::ToUint64() const {
-  DCHECK_EQ(Status::kValid, status_);
-  return id_;
-}
-
-// static
-void FlocId::RegisterPrefs(PrefRegistrySimple* registry) {
-  registry->RegisterUint64Pref(kFlocIdValuePrefKey, 0);
-  registry->RegisterIntegerPref(
-      kFlocIdStatusPrefKey, static_cast<int>(Status::kInvalidNoStatusPrefs));
-  registry->RegisterTimePref(kFlocIdHistoryBeginTimePrefKey, base::Time());
-  registry->RegisterTimePref(kFlocIdHistoryEndTimePrefKey, base::Time());
-  registry->RegisterUint64Pref(kFlocIdFinchConfigVersionPrefKey, 0);
-  registry->RegisterUint64Pref(kFlocIdSortingLshVersionPrefKey, 0);
-  registry->RegisterTimePref(kFlocIdComputeTimePrefKey, base::Time());
-}
-
-void FlocId::SaveToPrefs(PrefService* prefs) {
-  DCHECK_NE(status_, Status::kInvalidNoStatusPrefs);
-
-  prefs->SetUint64(kFlocIdValuePrefKey, id_);
-  prefs->SetInteger(kFlocIdStatusPrefKey, static_cast<int>(status_));
-  prefs->SetTime(kFlocIdHistoryBeginTimePrefKey, history_begin_time_);
-  prefs->SetTime(kFlocIdHistoryEndTimePrefKey, history_end_time_);
-  prefs->SetUint64(kFlocIdFinchConfigVersionPrefKey, finch_config_version_);
-  prefs->SetUint64(kFlocIdSortingLshVersionPrefKey, sorting_lsh_version_);
-  prefs->SetTime(kFlocIdComputeTimePrefKey, compute_time_);
-}
-
-void FlocId::UpdateStatusAndSaveToPrefs(PrefService* prefs, Status status) {
-  DCHECK_NE(status, Status::kValid);
-  DCHECK_NE(status, Status::kInvalidNoStatusPrefs);
-  status_ = status;
-  prefs->SetInteger(kFlocIdStatusPrefKey, static_cast<int>(status_));
-}
-
-void FlocId::ResetComputeTimeAndSaveToPrefs(base::Time compute_time,
-                                            PrefService* prefs) {
-  compute_time_ = compute_time;
-  prefs->SetTime(kFlocIdComputeTimePrefKey, compute_time_);
-}
-
-// static
-FlocId FlocId::ReadFromPrefs(PrefService* prefs) {
-  Status status = Status::kInvalidNoStatusPrefs;
-
-  // We rely on the time to tell whether it's a fresh profile.
-  if (!prefs->GetTime(kFlocIdComputeTimePrefKey).is_null()) {
-    // In some previous pref version before the status field is introduced, we
-    // used to use null path to represent invalid floc. After the status field
-    // is introduced, that state is represented in status.
-    if (prefs->HasPrefPath(kFlocIdValuePrefKey)) {
-      if (prefs->HasPrefPath(kFlocIdStatusPrefKey)) {
-        status = static_cast<Status>(prefs->GetInteger(kFlocIdStatusPrefKey));
-        DCHECK_NE(status, Status::kInvalidNoStatusPrefs);
-      } else {
-        status = Status::kValid;
-      }
-    }
-  }
-
-  return FlocId(prefs->GetUint64(kFlocIdValuePrefKey), status,
-                prefs->GetTime(kFlocIdHistoryBeginTimePrefKey),
-                prefs->GetTime(kFlocIdHistoryEndTimePrefKey),
-                prefs->GetUint64(kFlocIdFinchConfigVersionPrefKey),
-                prefs->GetUint64(kFlocIdSortingLshVersionPrefKey),
-                prefs->GetTime(kFlocIdComputeTimePrefKey));
-}
-
-FlocId::FlocId(uint64_t id,
-               Status status,
-               base::Time history_begin_time,
-               base::Time history_end_time,
-               uint32_t finch_config_version,
-               uint32_t sorting_lsh_version,
-               base::Time compute_time)
-    : id_(id),
-      status_(status),
-      history_begin_time_(history_begin_time),
-      history_end_time_(history_end_time),
-      finch_config_version_(finch_config_version),
-      sorting_lsh_version_(sorting_lsh_version),
-      compute_time_(compute_time) {}
-
-}  // namespace federated_learning
diff --git a/components/federated_learning/floc_id.h b/components/federated_learning/floc_id.h
deleted file mode 100644
index 39d50be..0000000
--- a/components/federated_learning/floc_id.h
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2020 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_FEDERATED_LEARNING_FLOC_ID_H_
-#define COMPONENTS_FEDERATED_LEARNING_FLOC_ID_H_
-
-#include "base/time/time.h"
-#include "base/version.h"
-#include "components/prefs/prefs_export.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom-forward.h"
-
-#include <stdint.h>
-
-#include <string>
-#include <unordered_set>
-
-class PrefRegistrySimple;
-class PrefService;
-
-namespace federated_learning {
-
-// ID used to represent a cohort of people with similar browsing habits. For
-// more context, see the explainer at
-// https://github.com/jkarlin/floc/blob/master/README.md
-class FlocId {
- public:
-  enum class Status {
-    kValid = 0,
-
-    // The default invalid reason that a fresh profile comes with. An
-    // outstanding cohort can also have this state after a prefs update where
-    // the previous reason is unknown or ambiguous.
-    kInvalidNoStatusPrefs = 1,
-
-    // The cohort computation is ready to run, but is waiting for other signals
-    // to start (e.g. sorting-lsh file is ready).
-    kInvalidWaitingToStart = 2,
-
-    kInvalidDisallowedByUserSettings = 3,
-    kInvalidNotEnoughElgibleHistoryDomains = 4,
-
-    // Set if the sorting-lsh process returns an empty hash value. This often
-    // implies that the cohort is blocked, but in principle can also be due to
-    // file sanitization errors.
-    // TODO(yaoxia): consider distinguishing between the underlying reasons.
-    kInvalidBlocked = 5,
-
-    kInvalidHistoryDeleted = 6,
-
-    // This reason is set when the user deletes cookies or resets cohort through
-    // a dedicated FLoC settings page until it's time to calculate at the next
-    // epoch.
-    kInvalidReset = 7,
-  };
-
-  static uint64_t SimHashHistory(
-      const std::unordered_set<std::string>& domains);
-
-  // Create an invalid floc. The `finch_config_version_` and the `compute_time_`
-  // will be set to the current.
-  static FlocId CreateInvalid(Status status);
-
-  // Create a newly computed and valid floc. The `finch_config_version_` and
-  // the `compute_time_` will be set to the current.
-  static FlocId CreateValid(uint64_t id,
-                            base::Time history_begin_time,
-                            base::Time history_end_time,
-                            uint32_t sorting_lsh_version);
-
-  FlocId(const FlocId& id);
-  ~FlocId();
-  FlocId& operator=(const FlocId& id);
-  FlocId& operator=(FlocId&& id);
-
-  bool operator==(const FlocId& other) const;
-  bool operator!=(const FlocId& other) const;
-
-  // True if the floc is successfully computed and hasn't been invalidated
-  // since the last computation. Note that an invalid FlocId still often has a
-  // legitimate compute time and finch config version, unless it's read from a
-  // fresh profile prefs.
-  bool IsValid() const;
-
-  // Get the blink::mojom::InterestCohort representation of this floc, with
-  // interest_cohort.id being "<id>" and interest_cohort.version being
-  // "chrome.<finch_config_version>.<sorting_lsh_version>". This is the format
-  // to be exposed to the JS API. Precondition: the floc must be valid.
-  blink::mojom::InterestCohortPtr ToInterestCohortForJsApi() const;
-
-  // Returns the internal uint64_t number. Precondition: the floc must be valid.
-  uint64_t ToUint64() const;
-
-  Status status() const { return status_; }
-
-  base::Time history_begin_time() const { return history_begin_time_; }
-
-  base::Time history_end_time() const { return history_end_time_; }
-
-  uint32_t finch_config_version() const { return finch_config_version_; }
-
-  uint32_t sorting_lsh_version() const { return sorting_lsh_version_; }
-
-  base::Time compute_time() const { return compute_time_; }
-
-  static void RegisterPrefs(PrefRegistrySimple* registry);
-
-  void SaveToPrefs(PrefService* prefs);
-  static FlocId ReadFromPrefs(PrefService* prefs);
-
-  // Update `status_` and the corresponding prefs entry. This can be used to
-  // invalidate the floc or to assign a new invalid reason.
-  void UpdateStatusAndSaveToPrefs(PrefService* prefs, Status status);
-
-  // Resets `compute_time_` to provided `compute_time` and saves it to prefs.
-  // This should at least be called if the floc compute timer is reset, to
-  // ensure that the compute cycle continues at the expected frequency.
-  void ResetComputeTimeAndSaveToPrefs(base::Time compute_time,
-                                      PrefService* prefs);
-
- private:
-  friend class FlocIdTester;
-
-  // Create a floc with stated params. This will only be used to create a floc
-  // read from prefs.
-  explicit FlocId(uint64_t id,
-                  Status status,
-                  base::Time history_begin_time,
-                  base::Time history_end_time,
-                  uint32_t finch_config_version,
-                  uint32_t sorting_lsh_version,
-                  base::Time compute_time);
-
-  uint64_t id_ = 0;
-
-  Status status_;
-
-  // The time range of the actual history used to compute the floc. This should
-  // always be within the time range of each history query.
-  base::Time history_begin_time_;
-  base::Time history_end_time_;
-
-  // The kFlocIdFinchConfigVersion feature param. When floc is loaded from
-  // prefs, this could be different from the current feature param state.
-  uint32_t finch_config_version_ = 0;
-
-  // The main version (i.e. 1st int) of the sorting lsh component version.
-  uint32_t sorting_lsh_version_ = 0;
-
-  // The time when the floc was computed. compute_time_.is_null() means the
-  // floc has never been computed before, and implies that the floc is also
-  // invalid.
-  base::Time compute_time_;
-};
-
-}  // namespace federated_learning
-
-#endif  // COMPONENTS_FEDERATED_LEARNING_FLOC_ID_H_
diff --git a/components/federated_learning/floc_id_unittest.cc b/components/federated_learning/floc_id_unittest.cc
deleted file mode 100644
index 70ce5c94..0000000
--- a/components/federated_learning/floc_id_unittest.cc
+++ /dev/null
@@ -1,304 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_id.h"
-
-#include "base/test/scoped_feature_list.h"
-#include "base/test/task_environment.h"
-#include "components/federated_learning/features/features.h"
-#include "components/federated_learning/floc_constants.h"
-#include "components/prefs/testing_pref_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
-
-namespace federated_learning {
-
-namespace {
-
-blink::mojom::InterestCohortPtr InterestCohortResult(
-    const std::string& id,
-    const std::string& version) {
-  blink::mojom::InterestCohortPtr result = blink::mojom::InterestCohort::New();
-  result->id = id;
-  result->version = version;
-  return result;
-}
-
-const base::Time kTime0 = base::Time();
-const base::Time kTime1 = base::Time::FromTimeT(1);
-const base::Time kTime2 = base::Time::FromTimeT(2);
-
-}  // namespace
-
-class FlocIdUnitTest : public testing::Test {
- public:
-  FlocIdUnitTest()
-      : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
-
-  ~FlocIdUnitTest() override = default;
-
- protected:
-  base::test::SingleThreadTaskEnvironment task_environment_;
-};
-
-TEST_F(FlocIdUnitTest, IsValid) {
-  EXPECT_FALSE(
-      FlocId::CreateInvalid(FlocId::Status::kInvalidWaitingToStart).IsValid());
-  EXPECT_TRUE(FlocId::CreateValid(0, kTime0, kTime0, 0).IsValid());
-  EXPECT_TRUE(FlocId::CreateValid(0, kTime1, kTime2, 1).IsValid());
-}
-
-TEST_F(FlocIdUnitTest, Comparison) {
-  EXPECT_EQ(FlocId::CreateInvalid(FlocId::Status::kInvalidWaitingToStart),
-            FlocId::CreateInvalid(FlocId::Status::kInvalidWaitingToStart));
-
-  EXPECT_NE(FlocId::CreateInvalid(FlocId::Status::kInvalidWaitingToStart),
-            FlocId::CreateInvalid(FlocId::Status::kInvalidBlocked));
-
-  EXPECT_EQ(FlocId::CreateValid(0, kTime0, kTime0, 0),
-            FlocId::CreateValid(0, kTime0, kTime0, 0));
-  EXPECT_EQ(FlocId::CreateValid(0, kTime1, kTime1, 1),
-            FlocId::CreateValid(0, kTime1, kTime1, 1));
-  EXPECT_EQ(FlocId::CreateValid(0, kTime1, kTime2, 1),
-            FlocId::CreateValid(0, kTime1, kTime2, 1));
-
-  EXPECT_NE(FlocId::CreateInvalid(FlocId::Status::kInvalidWaitingToStart),
-            FlocId::CreateValid(0, kTime0, kTime0, 0));
-  EXPECT_NE(FlocId::CreateValid(0, kTime0, kTime0, 0),
-            FlocId::CreateValid(1, kTime0, kTime0, 0));
-  EXPECT_NE(FlocId::CreateValid(0, kTime0, kTime1, 0),
-            FlocId::CreateValid(0, kTime1, kTime1, 0));
-  EXPECT_NE(FlocId::CreateValid(0, kTime0, kTime0, 0),
-            FlocId::CreateValid(0, kTime0, kTime0, 1));
-}
-
-TEST_F(FlocIdUnitTest, ToInterestCohortForJsApi) {
-  EXPECT_EQ(
-      InterestCohortResult("0", "chrome.1.0"),
-      FlocId::CreateValid(0, kTime0, kTime0, 0).ToInterestCohortForJsApi());
-  EXPECT_EQ(
-      InterestCohortResult("12345", "chrome.1.0"),
-      FlocId::CreateValid(12345, kTime0, kTime0, 0).ToInterestCohortForJsApi());
-  EXPECT_EQ(
-      InterestCohortResult("12345", "chrome.1.2"),
-      FlocId::CreateValid(12345, kTime1, kTime1, 2).ToInterestCohortForJsApi());
-
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeatureWithParameters(
-      kFederatedLearningOfCohorts, {{"finch_config_version", "99"}});
-
-  EXPECT_EQ(
-      InterestCohortResult("0", "chrome.99.0"),
-      FlocId::CreateValid(0, kTime0, kTime0, 0).ToInterestCohortForJsApi());
-  EXPECT_EQ(
-      InterestCohortResult("12345", "chrome.99.0"),
-      FlocId::CreateValid(12345, kTime0, kTime0, 0).ToInterestCohortForJsApi());
-  EXPECT_EQ(
-      InterestCohortResult("12345", "chrome.99.2"),
-      FlocId::CreateValid(12345, kTime1, kTime1, 2).ToInterestCohortForJsApi());
-}
-
-TEST_F(FlocIdUnitTest, ReadFromPrefs_DefaultInvalid) {
-  TestingPrefServiceSimple prefs;
-  FlocId::RegisterPrefs(prefs.registry());
-
-  FlocId floc_id = FlocId::ReadFromPrefs(&prefs);
-
-  EXPECT_FALSE(floc_id.IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidNoStatusPrefs, floc_id.status());
-  EXPECT_TRUE(floc_id.history_begin_time().is_null());
-  EXPECT_TRUE(floc_id.history_end_time().is_null());
-  EXPECT_EQ(0u, floc_id.finch_config_version());
-  EXPECT_EQ(0u, floc_id.sorting_lsh_version());
-  EXPECT_TRUE(floc_id.compute_time().is_null());
-}
-
-TEST_F(FlocIdUnitTest, ReadFromPrefs_SavedInvalidNoIdPrefs_NoStatusPref) {
-  TestingPrefServiceSimple prefs;
-  FlocId::RegisterPrefs(prefs.registry());
-
-  prefs.SetTime(kFlocIdHistoryBeginTimePrefKey, base::Time::FromTimeT(1));
-  prefs.SetTime(kFlocIdHistoryEndTimePrefKey, base::Time::FromTimeT(2));
-  prefs.SetUint64(kFlocIdFinchConfigVersionPrefKey, 3);
-  prefs.SetUint64(kFlocIdSortingLshVersionPrefKey, 4);
-  prefs.SetTime(kFlocIdComputeTimePrefKey, base::Time::FromTimeT(5));
-
-  FlocId floc_id = FlocId::ReadFromPrefs(&prefs);
-  EXPECT_FALSE(floc_id.IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidNoStatusPrefs, floc_id.status());
-  EXPECT_EQ(base::Time::FromTimeT(1), floc_id.history_begin_time());
-  EXPECT_EQ(base::Time::FromTimeT(2), floc_id.history_end_time());
-  EXPECT_EQ(3u, floc_id.finch_config_version());
-  EXPECT_EQ(4u, floc_id.sorting_lsh_version());
-  EXPECT_EQ(base::Time::FromTimeT(5), floc_id.compute_time());
-}
-
-TEST_F(FlocIdUnitTest, ReadFromPrefs_SavedValid_NoStatusPref) {
-  TestingPrefServiceSimple prefs;
-  FlocId::RegisterPrefs(prefs.registry());
-
-  prefs.SetUint64(kFlocIdValuePrefKey, 123);
-  prefs.SetTime(kFlocIdHistoryBeginTimePrefKey, base::Time::FromTimeT(1));
-  prefs.SetTime(kFlocIdHistoryEndTimePrefKey, base::Time::FromTimeT(2));
-  prefs.SetUint64(kFlocIdFinchConfigVersionPrefKey, 3);
-  prefs.SetUint64(kFlocIdSortingLshVersionPrefKey, 4);
-  prefs.SetTime(kFlocIdComputeTimePrefKey, base::Time::FromTimeT(5));
-
-  FlocId floc_id = FlocId::ReadFromPrefs(&prefs);
-  EXPECT_TRUE(floc_id.IsValid());
-  EXPECT_EQ(FlocId::Status::kValid, floc_id.status());
-  EXPECT_EQ(base::Time::FromTimeT(1), floc_id.history_begin_time());
-  EXPECT_EQ(base::Time::FromTimeT(2), floc_id.history_end_time());
-  EXPECT_EQ(3u, floc_id.finch_config_version());
-  EXPECT_EQ(4u, floc_id.sorting_lsh_version());
-  EXPECT_EQ(base::Time::FromTimeT(5), floc_id.compute_time());
-  EXPECT_EQ(InterestCohortResult("123", "chrome.3.4"),
-            floc_id.ToInterestCohortForJsApi());
-}
-
-TEST_F(FlocIdUnitTest, ReadFromPrefs_SavedInvalid) {
-  TestingPrefServiceSimple prefs;
-  FlocId::RegisterPrefs(prefs.registry());
-
-  prefs.SetUint64(kFlocIdValuePrefKey, 0);
-  prefs.SetInteger(
-      kFlocIdStatusPrefKey,
-      static_cast<int>(FlocId::Status::kInvalidDisallowedByUserSettings));
-  prefs.SetTime(kFlocIdHistoryBeginTimePrefKey, base::Time::FromTimeT(1));
-  prefs.SetTime(kFlocIdHistoryEndTimePrefKey, base::Time::FromTimeT(2));
-  prefs.SetUint64(kFlocIdFinchConfigVersionPrefKey, 3);
-  prefs.SetUint64(kFlocIdSortingLshVersionPrefKey, 4);
-  prefs.SetTime(kFlocIdComputeTimePrefKey, base::Time::FromTimeT(5));
-
-  FlocId floc_id = FlocId::ReadFromPrefs(&prefs);
-  EXPECT_FALSE(floc_id.IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidDisallowedByUserSettings, floc_id.status());
-  EXPECT_EQ(base::Time::FromTimeT(1), floc_id.history_begin_time());
-  EXPECT_EQ(base::Time::FromTimeT(2), floc_id.history_end_time());
-  EXPECT_EQ(3u, floc_id.finch_config_version());
-  EXPECT_EQ(4u, floc_id.sorting_lsh_version());
-  EXPECT_EQ(base::Time::FromTimeT(5), floc_id.compute_time());
-}
-
-TEST_F(FlocIdUnitTest, ReadFromPrefs_SavedValid) {
-  TestingPrefServiceSimple prefs;
-  FlocId::RegisterPrefs(prefs.registry());
-
-  prefs.SetUint64(kFlocIdValuePrefKey, 123);
-  prefs.SetInteger(kFlocIdStatusPrefKey,
-                   static_cast<int>(FlocId::Status::kValid));
-  prefs.SetTime(kFlocIdHistoryBeginTimePrefKey, base::Time::FromTimeT(1));
-  prefs.SetTime(kFlocIdHistoryEndTimePrefKey, base::Time::FromTimeT(2));
-  prefs.SetUint64(kFlocIdFinchConfigVersionPrefKey, 3);
-  prefs.SetUint64(kFlocIdSortingLshVersionPrefKey, 4);
-  prefs.SetTime(kFlocIdComputeTimePrefKey, base::Time::FromTimeT(5));
-
-  FlocId floc_id = FlocId::ReadFromPrefs(&prefs);
-  EXPECT_TRUE(floc_id.IsValid());
-  EXPECT_EQ(FlocId::Status::kValid, floc_id.status());
-  EXPECT_EQ(base::Time::FromTimeT(1), floc_id.history_begin_time());
-  EXPECT_EQ(base::Time::FromTimeT(2), floc_id.history_end_time());
-  EXPECT_EQ(3u, floc_id.finch_config_version());
-  EXPECT_EQ(4u, floc_id.sorting_lsh_version());
-  EXPECT_EQ(base::Time::FromTimeT(5), floc_id.compute_time());
-  EXPECT_EQ(InterestCohortResult("123", "chrome.3.4"),
-            floc_id.ToInterestCohortForJsApi());
-}
-
-TEST_F(FlocIdUnitTest, SaveToPrefs_InvalidFloc) {
-  TestingPrefServiceSimple prefs;
-  FlocId::RegisterPrefs(prefs.registry());
-
-  FlocId floc_id =
-      FlocId::CreateInvalid(FlocId::Status::kInvalidWaitingToStart);
-  floc_id.SaveToPrefs(&prefs);
-
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdValuePrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdStatusPrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdHistoryBeginTimePrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdHistoryEndTimePrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdFinchConfigVersionPrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdSortingLshVersionPrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdComputeTimePrefKey));
-
-  EXPECT_EQ(0u, prefs.GetUint64(kFlocIdValuePrefKey));
-  EXPECT_EQ(
-      FlocId::Status::kInvalidWaitingToStart,
-      static_cast<FlocId::Status>(prefs.GetInteger(kFlocIdStatusPrefKey)));
-  EXPECT_TRUE(prefs.GetTime(kFlocIdHistoryBeginTimePrefKey).is_null());
-  EXPECT_TRUE(prefs.GetTime(kFlocIdHistoryEndTimePrefKey).is_null());
-  EXPECT_EQ(1u, prefs.GetUint64(kFlocIdFinchConfigVersionPrefKey));
-  EXPECT_EQ(0u, prefs.GetUint64(kFlocIdSortingLshVersionPrefKey));
-  EXPECT_EQ(base::Time::Now(), prefs.GetTime(kFlocIdComputeTimePrefKey));
-}
-
-TEST_F(FlocIdUnitTest, SaveToPrefs_ValidFloc) {
-  TestingPrefServiceSimple prefs;
-  FlocId::RegisterPrefs(prefs.registry());
-
-  FlocId floc_id = FlocId::CreateValid(123, base::Time::FromTimeT(1),
-                                       base::Time::FromTimeT(2), 3);
-  floc_id.SaveToPrefs(&prefs);
-
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdValuePrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdStatusPrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdHistoryBeginTimePrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdHistoryEndTimePrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdFinchConfigVersionPrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdSortingLshVersionPrefKey));
-  EXPECT_TRUE(prefs.HasPrefPath(kFlocIdComputeTimePrefKey));
-
-  EXPECT_EQ(123u, prefs.GetUint64(kFlocIdValuePrefKey));
-  EXPECT_EQ(
-      FlocId::Status::kValid,
-      static_cast<FlocId::Status>(prefs.GetInteger(kFlocIdStatusPrefKey)));
-  EXPECT_EQ(base::Time::FromTimeT(1),
-            prefs.GetTime(kFlocIdHistoryBeginTimePrefKey));
-  EXPECT_EQ(base::Time::FromTimeT(2),
-            prefs.GetTime(kFlocIdHistoryEndTimePrefKey));
-  EXPECT_EQ(1u, prefs.GetUint64(kFlocIdFinchConfigVersionPrefKey));
-  EXPECT_EQ(3u, prefs.GetUint64(kFlocIdSortingLshVersionPrefKey));
-  EXPECT_EQ(base::Time::Now(), prefs.GetTime(kFlocIdComputeTimePrefKey));
-}
-
-TEST_F(FlocIdUnitTest, UpdateStatusAndSaveToPrefs) {
-  TestingPrefServiceSimple prefs;
-  FlocId::RegisterPrefs(prefs.registry());
-
-  FlocId floc_id = FlocId::CreateValid(123, base::Time::FromTimeT(1),
-                                       base::Time::FromTimeT(2), 3);
-  floc_id.SaveToPrefs(&prefs);
-
-  floc_id.UpdateStatusAndSaveToPrefs(&prefs,
-                                     FlocId::Status::kInvalidHistoryDeleted);
-  EXPECT_FALSE(floc_id.IsValid());
-  EXPECT_EQ(FlocId::Status::kInvalidHistoryDeleted, floc_id.status());
-
-  EXPECT_EQ(123u, prefs.GetUint64(kFlocIdValuePrefKey));
-  EXPECT_EQ(
-      FlocId::Status::kInvalidHistoryDeleted,
-      static_cast<FlocId::Status>(prefs.GetInteger(kFlocIdStatusPrefKey)));
-  EXPECT_EQ(base::Time::FromTimeT(1),
-            prefs.GetTime(kFlocIdHistoryBeginTimePrefKey));
-  EXPECT_EQ(base::Time::FromTimeT(2),
-            prefs.GetTime(kFlocIdHistoryEndTimePrefKey));
-  EXPECT_EQ(1u, prefs.GetUint64(kFlocIdFinchConfigVersionPrefKey));
-  EXPECT_EQ(3u, prefs.GetUint64(kFlocIdSortingLshVersionPrefKey));
-  EXPECT_EQ(base::Time::Now(), prefs.GetTime(kFlocIdComputeTimePrefKey));
-}
-
-TEST_F(FlocIdUnitTest, ResetComputeTimeAndSaveToPrefs) {
-  TestingPrefServiceSimple prefs;
-  FlocId::RegisterPrefs(prefs.registry());
-
-  FlocId floc_id = FlocId::CreateValid(123, base::Time::FromTimeT(1),
-                                       base::Time::FromTimeT(2), 3);
-  floc_id.SaveToPrefs(&prefs);
-  EXPECT_EQ(base::Time::Now(), prefs.GetTime(kFlocIdComputeTimePrefKey));
-
-  floc_id.ResetComputeTimeAndSaveToPrefs(base::Time::FromTimeT(4), &prefs);
-  EXPECT_EQ(base::Time::FromTimeT(4), prefs.GetTime(kFlocIdComputeTimePrefKey));
-}
-
-}  // namespace federated_learning
diff --git a/components/federated_learning/floc_sorting_lsh_clusters_service.cc b/components/federated_learning/floc_sorting_lsh_clusters_service.cc
deleted file mode 100644
index f179581..0000000
--- a/components/federated_learning/floc_sorting_lsh_clusters_service.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_sorting_lsh_clusters_service.h"
-
-#include <utility>
-
-#include "base/files/file.h"
-#include "base/files/file_util.h"
-#include "base/task/post_task.h"
-#include "base/task/task_runner_util.h"
-#include "base/task/thread_pool.h"
-#include "components/federated_learning/floc_constants.h"
-#include "third_party/protobuf/src/google/protobuf/io/coded_stream.h"
-#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h"
-
-namespace federated_learning {
-
-namespace {
-
-class CopyingFileInputStream : public google::protobuf::io::CopyingInputStream {
- public:
-  explicit CopyingFileInputStream(base::File file) : file_(std::move(file)) {}
-
-  CopyingFileInputStream(const CopyingFileInputStream&) = delete;
-  CopyingFileInputStream& operator=(const CopyingFileInputStream&) = delete;
-
-  ~CopyingFileInputStream() override = default;
-
-  // google::protobuf::io::CopyingInputStream:
-  int Read(void* buffer, int size) override {
-    return file_.ReadAtCurrentPosNoBestEffort(static_cast<char*>(buffer), size);
-  }
-
- private:
-  base::File file_;
-};
-
-absl::optional<uint64_t> ApplySortingLshOnBackgroundThread(
-    uint64_t sim_hash,
-    const base::FilePath& file_path) {
-  base::File sorting_lsh_clusters_file(
-      file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
-  if (!sorting_lsh_clusters_file.IsValid())
-    return absl::nullopt;
-
-  CopyingFileInputStream copying_stream(std::move(sorting_lsh_clusters_file));
-  google::protobuf::io::CopyingInputStreamAdaptor zero_copy_stream_adaptor(
-      &copying_stream);
-
-  google::protobuf::io::CodedInputStream input_stream(
-      &zero_copy_stream_adaptor);
-
-  // The file should contain a list of integers. The 7th-order bit represents
-  // whether the cohort should be blocked. The number represented by the 1st-6th
-  // bits should be within the range [0, MaxNumberOfBitsInFloc]. Suppose the
-  // list is l, then S(i) = 2^(l[i] & 0b111111) represents the the number of
-  // hashes that can be associated with this floc id. The cumulative sum of S(i)
-  // represents the boundary sim_hash values. We will use the higher index to
-  // encode |sim_hash|, i.e. if sim_hash is within range
-  // [CumSum(S(i-1)), CumSum(S(i))), |i| will be output floc.
-  //
-  // 0 is always an implicit CumSum boundary, i.e. if
-  // 0 <= |sim_hash| < 2^(l[0]), then the index 0 will be the output floc.
-  //
-  // However, if the is_blocked bit (i.e. l[i] & 0b1000000) indicates that the
-  // cohort should be blocked, we will output an invalid floc id.
-
-  // Input sanitization: As we compute on the fly, we will check to make sure
-  // each encountered entry, after dropping the is_blocked bit, is within
-  // [0, MaxNumberOfBitsInFloc]. Besides, the cumulative sum should be no
-  // greater than 2^MaxNumberOfBitsInFloc at any given time. If we cannot find
-  // an index i, it means the the final cumulative sum is less than
-  // 2^MaxNumberOfBitsInFloc, while we expect it to be exactly
-  // 2^MaxNumberOfBitsInFloc, and we should also fail in this case. When some
-  // check fails, we will also output an invalid floc id.
-  //
-  // A stricter sanitization would be to always stream all numbers and check
-  // properties. We skip doing this to save some computation cost.
-  const uint64_t kExpectedFinalCumulativeSum = (1ULL << kMaxNumberOfBitsInFloc);
-  DCHECK_LT(sim_hash, kExpectedFinalCumulativeSum);
-
-  uint64_t cumulative_sum = 0;
-  uint32_t next_combined;
-
-  // TODO(yaoxia): Add metrics for when the file has unexpected format.
-
-  for (uint64_t index = 0; input_stream.ReadVarint32(&next_combined); ++index) {
-    // Sanitizing error: the entry used more than |kSortingLshMaxBits| bits.
-    if ((next_combined >> kSortingLshMaxBits) > 0)
-      return absl::nullopt;
-
-    bool is_blocked = next_combined & kSortingLshBlockedMask;
-    uint32_t next = next_combined & kSortingLshSizeMask;
-
-    // Sanitizing error
-    if (next > kMaxNumberOfBitsInFloc)
-      return absl::nullopt;
-
-    cumulative_sum += (1ULL << next);
-
-    // Sanitizing error
-    if (cumulative_sum > kExpectedFinalCumulativeSum)
-      return absl::nullopt;
-
-    // Found the sim-hash upper bound. Use the index as the new floc.
-    if (cumulative_sum > sim_hash) {
-      if (is_blocked)
-        return absl::nullopt;
-
-      return index;
-    }
-  }
-
-  // Sanitizing error: we didn't find a sim-hash upper bound, but we expect to
-  // always find it after finish iterating through the list.
-  return absl::nullopt;
-}
-
-}  // namespace
-
-FlocSortingLshClustersService::FlocSortingLshClustersService()
-    : background_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
-      weak_ptr_factory_(this) {}
-
-FlocSortingLshClustersService::~FlocSortingLshClustersService() = default;
-
-void FlocSortingLshClustersService::AddObserver(Observer* observer) {
-  observers_.AddObserver(observer);
-}
-
-void FlocSortingLshClustersService::RemoveObserver(Observer* observer) {
-  observers_.RemoveObserver(observer);
-}
-
-bool FlocSortingLshClustersService::IsSortingLshClustersFileReady() const {
-  return first_file_ready_seen_;
-}
-
-void FlocSortingLshClustersService::OnSortingLshClustersFileReady(
-    const base::FilePath& file_path,
-    const base::Version& version) {
-  sorting_lsh_clusters_file_path_ = file_path;
-  sorting_lsh_clusters_version_ = version;
-  first_file_ready_seen_ = true;
-
-  for (auto& observer : observers_)
-    observer.OnSortingLshClustersFileReady();
-}
-
-void FlocSortingLshClustersService::ApplySortingLsh(
-    uint64_t sim_hash,
-    ApplySortingLshCallback callback) {
-  DCHECK(first_file_ready_seen_);
-
-  base::PostTaskAndReplyWithResult(
-      background_task_runner_.get(), FROM_HERE,
-      base::BindOnce(&ApplySortingLshOnBackgroundThread, sim_hash,
-                     sorting_lsh_clusters_file_path_),
-      base::BindOnce(&FlocSortingLshClustersService::DidApplySortingLsh,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback),
-                     sorting_lsh_clusters_version_));
-}
-
-void FlocSortingLshClustersService::SetBackgroundTaskRunnerForTesting(
-    scoped_refptr<base::SequencedTaskRunner> background_task_runner) {
-  background_task_runner_ = background_task_runner;
-}
-
-void FlocSortingLshClustersService::DidApplySortingLsh(
-    ApplySortingLshCallback callback,
-    base::Version version,
-    absl::optional<uint64_t> final_hash) {
-  std::move(callback).Run(std::move(final_hash), std::move(version));
-}
-
-}  // namespace federated_learning
diff --git a/components/federated_learning/floc_sorting_lsh_clusters_service.h b/components/federated_learning/floc_sorting_lsh_clusters_service.h
deleted file mode 100644
index 443b77c2..0000000
--- a/components/federated_learning/floc_sorting_lsh_clusters_service.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2020 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_FEDERATED_LEARNING_FLOC_SORTING_LSH_CLUSTERS_SERVICE_H_
-#define COMPONENTS_FEDERATED_LEARNING_FLOC_SORTING_LSH_CLUSTERS_SERVICE_H_
-
-#include <stdint.h>
-
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "base/version.h"
-#include "components/federated_learning/floc_id.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-
-namespace base {
-class FilePath;
-class SequencedTaskRunner;
-}  // namespace base
-
-namespace federated_learning {
-
-// Responsible for loading the sorting-lsh clusters with custom encoding and
-// and calculating the sorting-lsh based floc.
-//
-// File reading and parsing is posted to |background_task_runner_|.
-class FlocSortingLshClustersService {
- public:
-  using ApplySortingLshCallback =
-      base::OnceCallback<void(absl::optional<uint64_t>, base::Version)>;
-
-  class Observer {
-   public:
-    virtual void OnSortingLshClustersFileReady() = 0;
-  };
-
-  FlocSortingLshClustersService();
-  virtual ~FlocSortingLshClustersService();
-
-  FlocSortingLshClustersService(const FlocSortingLshClustersService&) = delete;
-  FlocSortingLshClustersService& operator=(
-      const FlocSortingLshClustersService&) = delete;
-
-  // Adds/Removes an Observer.
-  void AddObserver(Observer* observer);
-  void RemoveObserver(Observer* observer);
-
-  bool IsSortingLshClustersFileReady() const;
-
-  // Virtual for testing.
-  virtual void OnSortingLshClustersFileReady(const base::FilePath& file_path,
-                                             const base::Version& version);
-
-  // Virtual for testing.
-  virtual void ApplySortingLsh(uint64_t sim_hash,
-                               ApplySortingLshCallback callback);
-
-  void SetBackgroundTaskRunnerForTesting(
-      scoped_refptr<base::SequencedTaskRunner> background_task_runner);
-
- private:
-  friend class FlocSortingLshClustersServiceTest;
-
-  void DidApplySortingLsh(ApplySortingLshCallback callback,
-                          base::Version version,
-                          absl::optional<uint64_t> final_hash);
-
-  // Runner for tasks that do not influence user experience.
-  scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
-
-  base::ObserverList<Observer>::Unchecked observers_;
-
-  bool first_file_ready_seen_ = false;
-  base::FilePath sorting_lsh_clusters_file_path_;
-  base::Version sorting_lsh_clusters_version_;
-
-  base::WeakPtrFactory<FlocSortingLshClustersService> weak_ptr_factory_;
-};
-
-}  // namespace federated_learning
-
-#endif  // COMPONENTS_FEDERATED_LEARNING_FLOC_SORTING_LSH_CLUSTERS_SERVICE_H_
diff --git a/components/federated_learning/floc_sorting_lsh_clusters_service_unittest.cc b/components/federated_learning/floc_sorting_lsh_clusters_service_unittest.cc
deleted file mode 100644
index 9e9de36..0000000
--- a/components/federated_learning/floc_sorting_lsh_clusters_service_unittest.cc
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright 2020 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/federated_learning/floc_sorting_lsh_clusters_service.h"
-
-#include <string>
-#include <vector>
-
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/test/bind.h"
-#include "base/test/task_environment.h"
-#include "base/test/test_simple_task_runner.h"
-#include "components/federated_learning/floc_constants.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/protobuf/src/google/protobuf/io/coded_stream.h"
-#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h"
-
-namespace federated_learning {
-
-namespace {
-
-const uint64_t kMaxSimHash = (1ULL << kMaxNumberOfBitsInFloc) - 1;
-
-class CopyingFileOutputStream
-    : public google::protobuf::io::CopyingOutputStream {
- public:
-  explicit CopyingFileOutputStream(base::File file) : file_(std::move(file)) {}
-
-  CopyingFileOutputStream(const CopyingFileOutputStream&) = delete;
-  CopyingFileOutputStream& operator=(const CopyingFileOutputStream&) = delete;
-
-  ~CopyingFileOutputStream() override = default;
-
-  // google::protobuf::io::CopyingOutputStream:
-  bool Write(const void* buffer, int size) override {
-    return file_.WriteAtCurrentPos(static_cast<const char*>(buffer), size) ==
-           size;
-  }
-
- private:
-  base::File file_;
-};
-
-struct ApplySortingLshResult {
-  absl::optional<uint64_t> final_hash;
-  base::Version version;
-};
-
-}  // namespace
-
-class FlocSortingLshClustersServiceTest : public ::testing::Test {
- public:
-  FlocSortingLshClustersServiceTest()
-      : background_task_runner_(
-            base::MakeRefCounted<base::TestSimpleTaskRunner>()) {}
-
-  FlocSortingLshClustersServiceTest(const FlocSortingLshClustersServiceTest&) =
-      delete;
-  FlocSortingLshClustersServiceTest& operator=(
-      const FlocSortingLshClustersServiceTest&) = delete;
-
- protected:
-  void SetUp() override {
-    service_ = std::make_unique<FlocSortingLshClustersService>();
-    service_->SetBackgroundTaskRunnerForTesting(background_task_runner_);
-  }
-
-  base::FilePath GetUniqueTemporaryPath() {
-    CHECK(scoped_temp_dir_.IsValid() || scoped_temp_dir_.CreateUniqueTempDir());
-    return scoped_temp_dir_.GetPath().AppendASCII(
-        base::NumberToString(next_unique_file_suffix_++));
-  }
-
-  base::FilePath CreateTestSortingLshClustersFile(
-      const std::vector<std::pair<uint32_t, bool>>& sorting_lsh_clusters) {
-    base::FilePath file_path = GetUniqueTemporaryPath();
-    base::File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ |
-                                   base::File::FLAG_WRITE);
-    CHECK(file.IsValid());
-
-    CopyingFileOutputStream copying_stream(std::move(file));
-    google::protobuf::io::CopyingOutputStreamAdaptor zero_copy_stream_adaptor(
-        &copying_stream);
-
-    google::protobuf::io::CodedOutputStream output_stream(
-        &zero_copy_stream_adaptor);
-
-    for (const auto& p : sorting_lsh_clusters) {
-      uint32_t next = p.first;
-      bool is_blocked = p.second;
-      if (is_blocked) {
-        next |= kSortingLshBlockedMask;
-      }
-      output_stream.WriteVarint32(next);
-    }
-
-    CHECK(!output_stream.HadError());
-
-    return file_path;
-  }
-
-  base::FilePath InitializeSortingLshClustersFile(
-      const std::vector<std::pair<uint32_t, bool>>& sorting_lsh_clusters,
-      const base::Version& version) {
-    base::FilePath file_path =
-        CreateTestSortingLshClustersFile(sorting_lsh_clusters);
-    service()->OnSortingLshClustersFileReady(file_path, version);
-    EXPECT_TRUE(sorting_lsh_clusters_file_path().has_value());
-    return file_path;
-  }
-
-  FlocSortingLshClustersService* service() { return service_.get(); }
-
-  absl::optional<base::FilePath> sorting_lsh_clusters_file_path() {
-    if (!service()->first_file_ready_seen_)
-      return absl::nullopt;
-
-    return service()->sorting_lsh_clusters_file_path_;
-  }
-
-  ApplySortingLshResult ApplySortingLsh(uint64_t sim_hash) {
-    ApplySortingLshResult result;
-
-    base::RunLoop run_loop;
-    auto cb = base::BindLambdaForTesting(
-        [&](absl::optional<uint64_t> final_hash, base::Version version) {
-          result.final_hash = final_hash;
-          result.version = version;
-          run_loop.Quit();
-        });
-
-    service()->ApplySortingLsh(sim_hash, std::move(cb));
-    background_task_runner_->RunPendingTasks();
-    run_loop.Run();
-
-    return result;
-  }
-
- protected:
-  base::test::TaskEnvironment task_environment_;
-  base::ScopedTempDir scoped_temp_dir_;
-  int next_unique_file_suffix_ = 1;
-
-  scoped_refptr<base::TestSimpleTaskRunner> background_task_runner_;
-
-  std::unique_ptr<FlocSortingLshClustersService> service_;
-};
-
-TEST_F(FlocSortingLshClustersServiceTest, NoFilePath) {
-  EXPECT_FALSE(sorting_lsh_clusters_file_path().has_value());
-}
-
-TEST_F(FlocSortingLshClustersServiceTest, EmptyList) {
-  InitializeSortingLshClustersFile({}, base::Version("2.3.4"));
-
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(0).final_hash);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(1).final_hash);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
-}
-
-TEST_F(FlocSortingLshClustersServiceTest, List_0) {
-  InitializeSortingLshClustersFile({{0, false}}, base::Version("2.3.4"));
-
-  EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
-  EXPECT_EQ(base::Version("2.3.4"), ApplySortingLsh(0).version);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(1).final_hash);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
-}
-
-TEST_F(FlocSortingLshClustersServiceTest, List_0_Blocked) {
-  InitializeSortingLshClustersFile({{0, true}}, base::Version("2.3.4"));
-
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(0).final_hash);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(1).final_hash);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
-}
-
-TEST_F(FlocSortingLshClustersServiceTest, List_UnexpectedNumber) {
-  InitializeSortingLshClustersFile({{1 << 8, false}}, base::Version("2.3.4"));
-
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(0).final_hash);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(1).final_hash);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
-}
-
-TEST_F(FlocSortingLshClustersServiceTest, List_1) {
-  InitializeSortingLshClustersFile({{1, false}}, base::Version("2.3.4"));
-
-  EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
-  EXPECT_EQ(0u, ApplySortingLsh(1).final_hash.value());
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(2).final_hash);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
-}
-
-TEST_F(FlocSortingLshClustersServiceTest, List_0_0) {
-  InitializeSortingLshClustersFile({{0, false}, {0, false}},
-                                   base::Version("2.3.4"));
-
-  EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
-  EXPECT_EQ(1u, ApplySortingLsh(1).final_hash.value());
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(2).final_hash);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
-}
-
-TEST_F(FlocSortingLshClustersServiceTest, List_0_1) {
-  InitializeSortingLshClustersFile({{0, false}, {1, false}},
-                                   base::Version("2.3.4"));
-
-  EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
-  EXPECT_EQ(1u, ApplySortingLsh(1).final_hash.value());
-  EXPECT_EQ(1u, ApplySortingLsh(2).final_hash.value());
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(3).final_hash);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
-}
-
-TEST_F(FlocSortingLshClustersServiceTest, List_1_0) {
-  InitializeSortingLshClustersFile({{1, false}, {0, false}},
-                                   base::Version("2.3.4"));
-
-  EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
-  EXPECT_EQ(0u, ApplySortingLsh(1).final_hash.value());
-  EXPECT_EQ(1u, ApplySortingLsh(2).final_hash.value());
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(3).final_hash);
-  EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
-}
-
-TEST_F(FlocSortingLshClustersServiceTest, List_SingleCluster) {
-  InitializeSortingLshClustersFile({{kMaxNumberOfBitsInFloc, false}},
-                                   base::Version("2.3.4"));
-
-  EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
-  EXPECT_EQ(0u, ApplySortingLsh(1).final_hash.value());
-  EXPECT_EQ(0u, ApplySortingLsh(12345).final_hash.value());
-  EXPECT_EQ(0u, ApplySortingLsh(kMaxSimHash).final_hash.value());
-}
-
-TEST_F(FlocSortingLshClustersServiceTest, List_TwoClustersEqualSize) {
-  InitializeSortingLshClustersFile({{kMaxNumberOfBitsInFloc - 1, false},
-                                    {kMaxNumberOfBitsInFloc - 1, false}},
-                                   base::Version("2.3.4"));
-
-  uint64_t middle_value = (1ULL << (kMaxNumberOfBitsInFloc - 1));
-  EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
-  EXPECT_EQ(0u, ApplySortingLsh(1).final_hash.value());
-  EXPECT_EQ(0u, ApplySortingLsh(middle_value - 1).final_hash.value());
-  EXPECT_EQ(1u, ApplySortingLsh(middle_value).final_hash.value());
-  EXPECT_EQ(1u, ApplySortingLsh(middle_value + 1).final_hash.value());
-  EXPECT_EQ(1u, ApplySortingLsh(kMaxSimHash).final_hash.value());
-}
-
-TEST_F(FlocSortingLshClustersServiceTest,
-       FileDeletedAfterSortingLshTaskScheduled) {
-  base::FilePath file_path =
-      InitializeSortingLshClustersFile({{0, false}}, base::Version("2.3.4"));
-
-  base::RunLoop run_loop;
-  auto cb = base::BindLambdaForTesting(
-      [&](absl::optional<uint64_t> final_hash, base::Version version) {
-        // Since the file has been deleted, expect an invalid final_hash.
-        EXPECT_EQ(absl::nullopt, final_hash);
-        EXPECT_EQ(base::Version("2.3.4"), version);
-        run_loop.Quit();
-      });
-
-  service()->ApplySortingLsh(/*sim_hash=*/0, std::move(cb));
-  base::DeleteFile(file_path);
-
-  background_task_runner_->RunPendingTasks();
-  run_loop.Run();
-}
-
-TEST_F(FlocSortingLshClustersServiceTest, MultipleUpdate_LatestOneUsed) {
-  InitializeSortingLshClustersFile({}, base::Version("2.3.4"));
-  InitializeSortingLshClustersFile({{0, false}}, base::Version("6.7.8.9"));
-
-  EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
-  EXPECT_EQ(base::Version("6.7.8.9"), ApplySortingLsh(0).version);
-}
-
-}  // namespace federated_learning
diff --git a/components/federated_learning/sim_hash.cc b/components/federated_learning/sim_hash.cc
deleted file mode 100644
index 36f0ba5..0000000
--- a/components/federated_learning/sim_hash.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2020 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/federated_learning/sim_hash.h"
-
-#include "base/hash/legacy_hash.h"
-
-#include <algorithm>
-#include <cmath>
-
-namespace federated_learning {
-
-namespace {
-
-uint64_t g_seed1 = 1ULL;
-uint64_t g_seed2 = 2ULL;
-constexpr double kTwoPi = 2.0 * 3.141592653589793;
-
-// Hashes i and j to create a uniform RV in [0,1].
-double RandomUniform(uint64_t i, uint64_t j, uint64_t seed) {
-  uint64_t arr[2] = {i, j};
-  uint64_t hashed = base::legacy::CityHash64WithSeed(
-      base::as_bytes(
-          base::make_span(reinterpret_cast<const char*>(arr), sizeof(arr))),
-      seed);
-
-  return static_cast<double>(hashed) /
-         static_cast<double>(std::numeric_limits<uint64_t>::max());
-}
-
-// Uses the Box-Muller transform to generate a Gaussian from two uniform RVs in
-// [0,1] derived from i and j.
-double RandomGaussian(uint64_t i, uint64_t j) {
-  double rv1 = RandomUniform(i, j, g_seed1);
-  double rv2 = RandomUniform(j, i, g_seed2);
-
-  DCHECK_LE(rv1, 1);
-  DCHECK_GE(rv1, 0);
-  DCHECK_LE(rv2, 1);
-  DCHECK_GE(rv2, 0);
-
-  // BoxMuller
-  return std::sqrt(-2.0 * std::log(rv1)) * std::cos(kTwoPi * rv2);
-}
-
-}  // namespace
-
-void SetSeedsForTesting(uint64_t seed1, uint64_t seed2) {
-  g_seed1 = seed1;
-  g_seed2 = seed2;
-}
-
-uint64_t SimHashWeightedFeatures(const WeightedFeatures& features,
-                                 uint8_t output_dimensions) {
-  DCHECK_LT(0u, output_dimensions);
-  DCHECK_LE(output_dimensions, 64u);
-
-  uint64_t result = 0;
-  for (uint8_t d = 0; d < output_dimensions; ++d) {
-    double acc = 0;
-
-    for (const auto& feature_weight_pair : features) {
-      acc += RandomGaussian(d, feature_weight_pair.first) *
-             feature_weight_pair.second;
-    }
-
-    if (acc > 0)
-      result |= (1ULL << d);
-  }
-
-  return result;
-}
-
-uint64_t SimHashStrings(const std::unordered_set<std::string>& input,
-                        uint8_t output_dimensions) {
-  DCHECK_LT(0u, output_dimensions);
-  DCHECK_LE(output_dimensions, 64u);
-
-  WeightedFeatures features;
-
-  for (const std::string& s : input) {
-    FeatureEncoding string_hash =
-        base::legacy::CityHash64(base::as_bytes(base::make_span(s)));
-    features.emplace(string_hash, FeatureWeight(1));
-  }
-
-  return SimHashWeightedFeatures(features, output_dimensions);
-}
-
-}  // namespace federated_learning
diff --git a/components/federated_learning/sim_hash.h b/components/federated_learning/sim_hash.h
deleted file mode 100644
index 18987887..0000000
--- a/components/federated_learning/sim_hash.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2020 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_FEDERATED_LEARNING_SIM_HASH_H_
-#define COMPONENTS_FEDERATED_LEARNING_SIM_HASH_H_
-
-#include <stdint.h>
-#include <map>
-#include <string>
-#include <unordered_set>
-
-namespace federated_learning {
-
-using FeatureEncoding = uint64_t;
-using FeatureWeight = int;
-using WeightedFeatures = std::map<FeatureEncoding, FeatureWeight>;
-
-// Set the two seeds used for generating the random gaussian.
-void SetSeedsForTesting(uint64_t seed1, uint64_t seed2);
-
-// SimHash a set of weighted features to an |output_dimensions| bit number.
-// |output_dimensions| must be greater than 0 and no greater than 64.
-uint64_t SimHashWeightedFeatures(const WeightedFeatures& features,
-                                 uint8_t output_dimensions);
-
-// SimHash a set of strings to an |output_dimensions| bit number.
-// |output_dimensions| must be greater than 0 and no greater than 64.
-uint64_t SimHashStrings(const std::unordered_set<std::string>& input,
-                        uint8_t output_dimensions);
-
-}  // namespace federated_learning
-
-#endif  // COMPONENTS_FEDERATED_LEARNING_SIM_HASH_H_
diff --git a/components/federated_learning/sim_hash_unittest.cc b/components/federated_learning/sim_hash_unittest.cc
deleted file mode 100644
index 9a99990..0000000
--- a/components/federated_learning/sim_hash_unittest.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 2020 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/federated_learning/sim_hash.h"
-
-#include <cmath>
-
-#include "base/check_op.h"
-#include "base/hash/legacy_hash.h"
-#include "base/rand_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace federated_learning {
-
-namespace {
-
-// Sparse representation of a 2^64 bit vector. Each number in the set represents
-// the position of a bit that is being set.
-using LargeBitVector = std::set<uint64_t>;
-
-// Roll our own random uint64_t generator as we want deterministic outcome
-// across different test runs.
-uint64_t RandUint64() {
-  static uint64_t seed = 0;
-  ++seed;
-  uint64_t arr[2] = {1234ULL, 4321ULL};
-  return base::legacy::CityHash64WithSeed(
-      base::as_bytes(
-          base::make_span(reinterpret_cast<const char*>(arr), sizeof(arr))),
-      seed);
-}
-
-// Inclusive [min, max]
-uint64_t RandUint64InRange(uint64_t min, uint64_t max) {
-  DCHECK_LE(min, max);
-  if (min == 0ULL && max == std::numeric_limits<uint64_t>::max())
-    return RandUint64();
-
-  uint64_t range = max - min + 1;
-  DCHECK_LE(2ULL, range);
-
-  // We must discard random results above this number, as they would
-  // make the random generator non-uniform.
-  uint64_t max_acceptable_value =
-      (std::numeric_limits<uint64_t>::max() / range) * range - 1;
-
-  uint64_t rand_value;
-  do {
-    rand_value = RandUint64();
-  } while (rand_value > max_acceptable_value);
-
-  uint64_t result = (rand_value % range) + min;
-
-  DCHECK_GE(result, min);
-  DCHECK_LE(result, max);
-  return result;
-}
-
-LargeBitVector RandLargeBitVector(
-    size_t number_of_bits_set,
-    uint64_t max_bit_position = std::numeric_limits<uint64_t>::max()) {
-  LargeBitVector result;
-  while (result.size() < number_of_bits_set) {
-    result.insert(RandUint64InRange(0ULL, max_bit_position));
-  }
-  return result;
-}
-
-float DotProduct(const LargeBitVector& v1, const LargeBitVector& v2) {
-  float result = 0;
-  for (uint64_t pos : v1) {
-    if (v2.count(pos))
-      result += 1;
-  }
-  return result;
-}
-
-float Norm(const LargeBitVector& v) {
-  return std::sqrt(DotProduct(v, v));
-}
-
-WeightedFeatures ToWeightedFeatures(const LargeBitVector& v) {
-  WeightedFeatures result;
-  for (FeatureEncoding feature : v) {
-    result.emplace(feature, FeatureWeight(1));
-  }
-  return result;
-}
-
-size_t MultipleSimHashGetNumOutputBitsEqual(size_t repeat_times,
-                                            uint8_t dimensions,
-                                            const WeightedFeatures& f1,
-                                            const WeightedFeatures& f2) {
-  uint64_t seed1 = 1;
-  uint64_t seed2 = 100000;
-
-  uint64_t num_output_bits_equal = 0;
-  for (size_t i = 0; i < repeat_times; ++i) {
-    SetSeedsForTesting(seed1++, seed2++);
-
-    uint64_t o1 = SimHashWeightedFeatures(f1, dimensions);
-    uint64_t o2 = SimHashWeightedFeatures(f2, dimensions);
-    for (uint8_t j = 0; j < dimensions; ++j) {
-      if ((o1 & 1) == (o2 & 1))
-        ++num_output_bits_equal;
-      o1 >>= 1;
-      o2 >>= 1;
-    }
-  }
-  return num_output_bits_equal;
-}
-
-TEST(SimHashTest, HashValue) {
-  WeightedFeatures empty;
-  EXPECT_EQ(SimHashWeightedFeatures(empty, 1u), 0ULL);
-  EXPECT_EQ(SimHashWeightedFeatures(empty, 16u), 0ULL);
-
-  WeightedFeatures f0;
-  f0.emplace(FeatureEncoding(0), FeatureWeight(1));
-  EXPECT_EQ(SimHashWeightedFeatures(f0, 1u), 0ULL);
-  EXPECT_EQ(SimHashWeightedFeatures(f0, 16u), 8632ULL);
-
-  WeightedFeatures f1;
-  f1.emplace(FeatureEncoding(0), FeatureWeight(123));
-  EXPECT_EQ(SimHashWeightedFeatures(f1, 1u), 0ULL);
-  EXPECT_EQ(SimHashWeightedFeatures(f1, 16u), 8632ULL);
-
-  WeightedFeatures f2;
-  f2.emplace(FeatureEncoding(999999), FeatureWeight(1));
-  EXPECT_EQ(SimHashWeightedFeatures(f2, 1u), 1ULL);
-  EXPECT_EQ(SimHashWeightedFeatures(f2, 16u), 28603ULL);
-
-  WeightedFeatures f3;
-  f3.emplace(FeatureEncoding(0), FeatureWeight(1));
-  f3.emplace(FeatureEncoding(1), FeatureWeight(1));
-  EXPECT_EQ(SimHashWeightedFeatures(f3, 1u), 0ULL);
-  EXPECT_EQ(SimHashWeightedFeatures(f3, 16u), 10682ULL);
-
-  WeightedFeatures f4;
-  f4.emplace(FeatureEncoding(0), FeatureWeight(2));
-  f4.emplace(FeatureEncoding(1), FeatureWeight(3));
-  EXPECT_EQ(SimHashWeightedFeatures(f4, 1u), 0ULL);
-  EXPECT_EQ(SimHashWeightedFeatures(f4, 16u), 2490ULL);
-}
-
-// Test that given random equally weighted input features, the chances of each
-// bit in the SimHash result to be 0 and 1 are equally likely.
-TEST(SimHashTest, ExpectationOnRandomUniformInput) {
-  const uint8_t dimensions = 16u;
-  const size_t repeat_times = 10000u;
-
-  uint64_t totals[dimensions] = {0};
-
-  for (size_t i = 0; i < repeat_times; ++i) {
-    LargeBitVector v = RandLargeBitVector(RandUint64InRange(1u, 10u));
-    uint64_t hash_result =
-        SimHashWeightedFeatures(ToWeightedFeatures(v), dimensions);
-
-    for (uint8_t j = 0; j < dimensions; ++j) {
-      totals[j] += (hash_result & 1);
-      hash_result >>= 1;
-    }
-  }
-
-  const double expectation = 0.5;
-  const double err_tolerance = 0.03;
-
-  for (uint8_t j = 0; j < dimensions; ++j) {
-    double avg = 1.0 * totals[j] / repeat_times;
-    EXPECT_LT(avg, expectation + err_tolerance);
-    EXPECT_GT(avg, expectation - err_tolerance);
-  }
-}
-
-// Test that the cosine similarity is preserved.
-TEST(SimHashTest, CosineSimilarity_NonOrthogonalInput) {
-  const float kPi = 3.141592653589793;
-  const uint8_t dimensions = 50u;
-  const size_t repeat_times = 100u;
-
-  // Generate v1 and v2 that are likely non-orthogonal.
-  LargeBitVector v1 = RandLargeBitVector(4000u, 10000);
-  LargeBitVector v2 = RandLargeBitVector(5000u, 10000);
-
-  size_t num_output_bits_equal = MultipleSimHashGetNumOutputBitsEqual(
-      repeat_times, dimensions, ToWeightedFeatures(v1), ToWeightedFeatures(v2));
-  float avg = 1.0 * num_output_bits_equal / dimensions / repeat_times;
-  float expectation =
-      1.0 - std::acos(DotProduct(v1, v2) / (Norm(v1) * Norm(v2))) / kPi;
-
-  // Verify that the expectation is different from 0.5 and 1 to make sure the
-  // test is non-trivial.
-  EXPECT_LT(expectation, 0.7);
-  EXPECT_GT(expectation, 0.6);
-
-  // Verify that SimHash(v1) and SimHash(v2) have approximately |expectation|
-  // fraction of their bits in common.
-  const double err_tolerance = 0.03;
-  EXPECT_LT(avg, expectation + err_tolerance);
-  EXPECT_GT(avg, expectation - err_tolerance);
-}
-
-// Test that when input v1 and v2 are orthogonal, SimHash(v1) and SimHash(v2)
-// have approximately half their bits in common.
-TEST(SimHashTest, CosineSimilarity_OrthogonalInput) {
-  const uint8_t dimensions = 50u;
-  const size_t repeat_times = 100u;
-
-  // Generate v1 and v2 that are likely orthogonal
-  LargeBitVector v1 = RandLargeBitVector(1u);
-  LargeBitVector v2 = RandLargeBitVector(1u);
-
-  size_t num_output_bits_equal = MultipleSimHashGetNumOutputBitsEqual(
-      repeat_times, dimensions, ToWeightedFeatures(v1), ToWeightedFeatures(v2));
-  float avg = 1.0 * num_output_bits_equal / dimensions / repeat_times;
-  float expectation = 0.5;
-
-  // Verify that SimHash(v1) and SimHash(v2) have approximately half their bits
-  // in common.
-  const double err_tolerance = 0.03;
-  EXPECT_LT(avg, expectation + err_tolerance);
-  EXPECT_GT(avg, expectation - err_tolerance);
-}
-
-}  // namespace
-
-}  // namespace federated_learning
diff --git a/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
index 2c38258..1d1c4fbd 100644
--- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc
+++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -32,6 +32,47 @@
 
 namespace network_session_configurator {
 
+namespace {
+
+// TODO(haoyuewang) Move this method to third_party/quic/core/quic_versions.h.
+// Compare two sets of QUIC versions, considering versions with identical ALPN
+// string to be equal, ignoring duplicates and ordering.
+bool QuicVersionVectorsEqual(const quic::ParsedQuicVersionVector& versions1,
+                             const quic::ParsedQuicVersionVector& versions2) {
+  // Collect ALPN tokens.
+  std::vector<std::string> alpn1;
+  for (const auto& version : versions1) {
+    alpn1.push_back(quic::AlpnForVersion(version));
+  }
+  // Sort and deduplicate.
+  std::sort(alpn1.begin(), alpn1.end());
+  auto last = std::unique(alpn1.begin(), alpn1.end());
+  if (last != alpn1.end()) {
+    alpn1.erase(last, alpn1.end());
+  }
+
+  // Collect ALPN tokens.
+  std::vector<std::string> alpn2;
+  for (const auto& version : versions2) {
+    alpn2.push_back(quic::AlpnForVersion(version));
+  }
+  // Sort and deduplicate.
+  std::sort(alpn2.begin(), alpn2.end());
+  last = std::unique(alpn2.begin(), alpn2.end());
+  if (last != alpn2.end()) {
+    alpn2.erase(last, alpn2.end());
+  }
+
+  // Compare.
+  if (alpn1.size() != alpn2.size()) {
+    return false;
+  }
+
+  return std::equal(alpn1.begin(), alpn1.end(), alpn2.begin());
+}
+
+}  // namespace
+
 class NetworkSessionConfiguratorTest : public testing::Test {
  public:
   NetworkSessionConfiguratorTest()
@@ -563,7 +604,8 @@
   ParseFieldTrials();
 
   quic::ParsedQuicVersionVector supported_versions = {version1, version2};
-  EXPECT_EQ(supported_versions, quic_params_.supported_versions);
+  EXPECT_TRUE(QuicVersionVectorsEqual(supported_versions,
+                                      quic_params_.supported_versions));
 }
 
 TEST_F(NetworkSessionConfiguratorTest,
@@ -940,7 +982,8 @@
                                  quic::AlpnForVersion(version_));
   ParseCommandLineAndFieldTrials(command_line);
   quic::ParsedQuicVersionVector expected_versions = {version_};
-  EXPECT_EQ(expected_versions, quic_params_.supported_versions);
+  EXPECT_TRUE(QuicVersionVectorsEqual(expected_versions,
+                                      quic_params_.supported_versions));
 }
 
 TEST_P(NetworkSessionConfiguratorWithQuicVersionTest,
@@ -986,7 +1029,8 @@
   base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
   ParseFieldTrials();
   quic::ParsedQuicVersionVector expected_versions = {version_};
-  EXPECT_EQ(expected_versions, quic_params_.supported_versions);
+  EXPECT_TRUE(QuicVersionVectorsEqual(expected_versions,
+                                      quic_params_.supported_versions));
 }
 
 TEST_P(NetworkSessionConfiguratorWithQuicVersionTest, ObsoleteQuicVersion) {
diff --git a/components/segmentation_platform/OWNERS b/components/segmentation_platform/OWNERS
index 2c36451..932eb9b0 100644
--- a/components/segmentation_platform/OWNERS
+++ b/components/segmentation_platform/OWNERS
@@ -1,2 +1,4 @@
 nyquist@chromium.org
+qinmin@chromium.org
 shaktisahu@chromium.org
+ssid@chromium.org
diff --git a/components/segmentation_platform/internal/BUILD.gn b/components/segmentation_platform/internal/BUILD.gn
index 1a03b89..430313df 100644
--- a/components/segmentation_platform/internal/BUILD.gn
+++ b/components/segmentation_platform/internal/BUILD.gn
@@ -51,6 +51,8 @@
     "scheduler/model_execution_scheduler_impl.h",
     "segmentation_platform_service_impl.cc",
     "segmentation_platform_service_impl.h",
+    "segmentation_ukm_helper.cc",
+    "segmentation_ukm_helper.h",
     "selection/segment_score_provider.cc",
     "selection/segment_score_provider.h",
     "selection/segment_selector.h",
@@ -77,6 +79,8 @@
     "//components/prefs",
     "//components/segmentation_platform/internal/proto",
     "//components/segmentation_platform/public",
+    "//services/metrics/public/cpp:metrics_cpp",
+    "//services/metrics/public/cpp:ukm_builders",
   ]
 
   public_deps = [
@@ -137,6 +141,7 @@
     "execution/model_execution_manager_factory_unittest.cc",
     "scheduler/model_execution_scheduler_unittest.cc",
     "segmentation_platform_service_impl_unittest.cc",
+    "segmentation_ukm_helper_unittest.cc",
     "selection/segment_score_provider_unittest.cc",
     "selection/segment_selector_unittest.cc",
     "selection/segmentation_result_prefs_unittest.cc",
@@ -157,6 +162,8 @@
     "//components/prefs:test_support",
     "//components/segmentation_platform/internal/proto",
     "//components/segmentation_platform/public",
+    "//components/ukm:test_support",
+    "//services/metrics/public/cpp:ukm_builders",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/components/segmentation_platform/internal/DEPS b/components/segmentation_platform/internal/DEPS
new file mode 100644
index 0000000..b013101
--- /dev/null
+++ b/components/segmentation_platform/internal/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+components/ukm/test_ukm_recorder.h",
+  "+services/metrics/public/cpp",
+]
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc b/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc
index cafd7d9..da39398 100644
--- a/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc
+++ b/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc
@@ -29,6 +29,7 @@
 #include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
 #include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
 #include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "components/segmentation_platform/internal/segmentation_ukm_helper.h"
 #include "components/segmentation_platform/internal/stats.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/perfetto/include/perfetto/tracing/track.h"
@@ -362,6 +363,11 @@
   if (result.has_value()) {
     VLOG(1) << "Segmentation model result: " << *result;
     stats::RecordModelExecutionResult(state->segment_id, result.value());
+    if (state->model_handler->GetModelInfo()) {
+      SegmentationUkmHelper::GetInstance()->RecordModelExecutionResult(
+          state->segment_id, state->model_handler->GetModelInfo()->GetVersion(),
+          state->input_tensor, result.value());
+    }
     RunModelExecutionCallback(std::move(state), *result,
                               ModelExecutionStatus::kSuccess);
   } else {
diff --git a/components/segmentation_platform/internal/segmentation_ukm_helper.cc b/components/segmentation_platform/internal/segmentation_ukm_helper.cc
new file mode 100644
index 0000000..c1c434493
--- /dev/null
+++ b/components/segmentation_platform/internal/segmentation_ukm_helper.cc
@@ -0,0 +1,131 @@
+// Copyright 2022 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/segmentation_platform/internal/segmentation_ukm_helper.h"
+
+#include "base/bit_cast.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "components/segmentation_platform/internal/stats.h"
+#include "components/segmentation_platform/public/config.h"
+#include "components/segmentation_platform/public/features.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
+
+#define CALL_MEMBER_FN(obj, func) ((obj).*(func))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x)[0])
+
+using ukm::builders::Segmentation_ModelExecution;
+
+namespace {
+using UkmMemberFn =
+    Segmentation_ModelExecution& (Segmentation_ModelExecution::*)(int64_t);
+
+const UkmMemberFn kSegmentationUkmMethods[] = {
+    &Segmentation_ModelExecution::SetInput0,
+    &Segmentation_ModelExecution::SetInput1,
+    &Segmentation_ModelExecution::SetInput2,
+    &Segmentation_ModelExecution::SetInput3,
+    &Segmentation_ModelExecution::SetInput4,
+    &Segmentation_ModelExecution::SetInput5,
+    &Segmentation_ModelExecution::SetInput6,
+    &Segmentation_ModelExecution::SetInput7,
+    &Segmentation_ModelExecution::SetInput8,
+    &Segmentation_ModelExecution::SetInput9,
+    &Segmentation_ModelExecution::SetInput10,
+    &Segmentation_ModelExecution::SetInput11,
+    &Segmentation_ModelExecution::SetInput12,
+    &Segmentation_ModelExecution::SetInput13,
+    &Segmentation_ModelExecution::SetInput14,
+    &Segmentation_ModelExecution::SetInput15,
+    &Segmentation_ModelExecution::SetInput16,
+    &Segmentation_ModelExecution::SetInput17,
+    &Segmentation_ModelExecution::SetInput18,
+    &Segmentation_ModelExecution::SetInput19,
+    &Segmentation_ModelExecution::SetInput20,
+    &Segmentation_ModelExecution::SetInput21,
+    &Segmentation_ModelExecution::SetInput22,
+    &Segmentation_ModelExecution::SetInput23,
+    &Segmentation_ModelExecution::SetInput24,
+    &Segmentation_ModelExecution::SetInput25,
+    &Segmentation_ModelExecution::SetInput26,
+    &Segmentation_ModelExecution::SetInput27,
+    &Segmentation_ModelExecution::SetInput28,
+    &Segmentation_ModelExecution::SetInput29};
+
+// Gets a set of segment IDs that are allowed to upload metrics.
+base::flat_set<int> GetSegmentIdsAllowedForReporting() {
+  std::vector<std::string> segment_ids = base::SplitString(
+      base::GetFieldTrialParamValueByFeature(
+          segmentation_platform::features::
+              kSegmentationStructuredMetricsFeature,
+          segmentation_platform::kSegmentIdsAllowedForReportingKey),
+      ",;", base::WhitespaceHandling::TRIM_WHITESPACE,
+      base::SplitResult::SPLIT_WANT_NONEMPTY);
+  base::flat_set<int> result;
+  for (const auto& id : segment_ids) {
+    int segment_id;
+    if (base::StringToInt(id, &segment_id))
+      result.emplace(segment_id);
+  }
+  return result;
+}
+
+}  // namespace
+
+namespace segmentation_platform {
+
+SegmentationUkmHelper::SegmentationUkmHelper() {
+  Initialize();
+}
+
+SegmentationUkmHelper::~SegmentationUkmHelper() = default;
+
+void SegmentationUkmHelper::Initialize() {
+  allowed_segment_ids_ = GetSegmentIdsAllowedForReporting();
+}
+
+// static
+SegmentationUkmHelper* SegmentationUkmHelper::GetInstance() {
+  static base::NoDestructor<SegmentationUkmHelper> helper;
+  return helper.get();
+}
+
+ukm::SourceId SegmentationUkmHelper::RecordModelExecutionResult(
+    OptimizationTarget segment_id,
+    int64_t model_version,
+    const std::vector<float>& input_tensor,
+    float result) {
+  // Check if the |segment_id| is allowed to record metrics.
+  if (!allowed_segment_ids_.contains(static_cast<int>(segment_id)))
+    return ukm::kInvalidSourceId;
+
+  ukm::SourceId source_id = ukm::NoURLSourceId();
+  // Don't record UKM if there are too many tensors.
+  if (input_tensor.size() > ARRAY_SIZE(kSegmentationUkmMethods)) {
+    stats::RecordTooManyInputTensors(input_tensor.size());
+    return ukm::kInvalidSourceId;
+  }
+  ukm::builders::Segmentation_ModelExecution execution_result(source_id);
+
+  execution_result.SetOptimizationTarget(segment_id)
+      .SetModelVersion(model_version);
+
+  for (size_t i = 0; i < input_tensor.size(); ++i) {
+    CALL_MEMBER_FN(execution_result, kSegmentationUkmMethods[i])
+    (FloatToInt64(input_tensor[i]));
+  }
+  execution_result.SetPredictionResult(FloatToInt64(result))
+      .Record(ukm::UkmRecorder::Get());
+  return source_id;
+}
+
+// static
+int64_t SegmentationUkmHelper::FloatToInt64(float f) {
+  // Encode the float number in IEEE754 double precision.
+  return bit_cast<int64_t>(static_cast<double>(f));
+}
+
+}  // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/segmentation_ukm_helper.h b/components/segmentation_platform/internal/segmentation_ukm_helper.h
new file mode 100644
index 0000000..3df9338
--- /dev/null
+++ b/components/segmentation_platform/internal/segmentation_ukm_helper.h
@@ -0,0 +1,48 @@
+// Copyright 2022 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_SEGMENTATION_PLATFORM_INTERNAL_SEGMENTATION_UKM_HELPER_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SEGMENTATION_UKM_HELPER_H_
+
+#include "base/containers/flat_set.h"
+#include "base/no_destructor.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
+
+using optimization_guide::proto::OptimizationTarget;
+
+namespace segmentation_platform {
+
+// A helper class to record segmentation model execution results in UKM.
+class SegmentationUkmHelper {
+ public:
+  static SegmentationUkmHelper* GetInstance();
+  SegmentationUkmHelper(const SegmentationUkmHelper&) = delete;
+  SegmentationUkmHelper& operator=(const SegmentationUkmHelper&) = delete;
+
+  // Record segmentation model information and input/output after the
+  // executing the model, and return the UKM source ID.
+  ukm::SourceId RecordModelExecutionResult(
+      OptimizationTarget segment_id,
+      int64_t model_version,
+      const std::vector<float>& input_tensor,
+      float result);
+
+  // Helper method to encode a float number into int64.
+  static int64_t FloatToInt64(float f);
+
+ private:
+  friend class base::NoDestructor<SegmentationUkmHelper>;
+  friend class SegmentationUkmHelperTest;
+  SegmentationUkmHelper();
+  ~SegmentationUkmHelper();
+
+  void Initialize();
+
+  base::flat_set<int> allowed_segment_ids_;
+};
+
+}  // namespace segmentation_platform
+
+#endif  // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SEGMENTATION_UKM_HELPER_H_
diff --git a/components/segmentation_platform/internal/segmentation_ukm_helper_unittest.cc b/components/segmentation_platform/internal/segmentation_ukm_helper_unittest.cc
new file mode 100644
index 0000000..d88fcd44
--- /dev/null
+++ b/components/segmentation_platform/internal/segmentation_ukm_helper_unittest.cc
@@ -0,0 +1,180 @@
+// Copyright 2022 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/segmentation_platform/internal/segmentation_ukm_helper.h"
+
+#include <cmath>
+
+#include "base/bit_cast.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "components/segmentation_platform/public/config.h"
+#include "components/segmentation_platform/public/features.h"
+#include "components/ukm/test_ukm_recorder.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using Segmentation_ModelExecution = ukm::builders::Segmentation_ModelExecution;
+
+namespace {
+
+// Round errors allowed during conversion.
+static const double kRoundingError = 1E-5;
+
+float Int64ToFloat(int64_t encoded) {
+  return static_cast<float>(bit_cast<double>(encoded));
+}
+
+void CompareEncodeDecodeDifference(float tensor) {
+  ASSERT_LT(
+      std::abs(tensor -
+               Int64ToFloat(
+                   segmentation_platform::SegmentationUkmHelper::FloatToInt64(
+                       tensor))),
+      kRoundingError);
+}
+
+}  // namespace
+
+namespace segmentation_platform {
+
+class SegmentationUkmHelperTest : public testing::Test {
+ public:
+  SegmentationUkmHelperTest() = default;
+
+  SegmentationUkmHelperTest(const SegmentationUkmHelperTest&) = delete;
+  SegmentationUkmHelperTest& operator=(const SegmentationUkmHelperTest&) =
+      delete;
+
+  ~SegmentationUkmHelperTest() override = default;
+
+  void SetUp() override { test_recorder_.Purge(); }
+
+  void ExpectUkmMetrics(const base::StringPiece entry_name,
+                        const std::vector<base::StringPiece>& keys,
+                        const std::vector<int64_t>& values) {
+    const auto& entries = test_recorder_.GetEntriesByName(entry_name);
+    EXPECT_EQ(1u, entries.size());
+    for (const auto* entry : entries) {
+      const size_t keys_size = keys.size();
+      EXPECT_EQ(keys_size, values.size());
+      for (size_t i = 0; i < keys_size; ++i) {
+        test_recorder_.ExpectEntryMetric(entry, keys[i], values[i]);
+      }
+    }
+  }
+
+  void ExpectEmptyUkmMetrics(const base::StringPiece entry_name) {
+    EXPECT_EQ(0u, test_recorder_.GetEntriesByName(entry_name).size());
+  }
+
+  void InitializeAllowedSegmentIds(const std::string& allowed_ids) {
+    std::map<std::string, std::string> params = {
+        {kSegmentIdsAllowedForReportingKey, allowed_ids}};
+    feature_list_.InitAndEnableFeatureWithParameters(
+        features::kSegmentationStructuredMetricsFeature, params);
+    SegmentationUkmHelper::GetInstance()->Initialize();
+  }
+
+  void DisableStructureMetrics() {
+    feature_list_.InitAndDisableFeature(
+        features::kSegmentationStructuredMetricsFeature);
+    SegmentationUkmHelper::GetInstance()->Initialize();
+  }
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
+  ukm::TestAutoSetUkmRecorder test_recorder_;
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// Tests that basic recording works properly.
+TEST_F(SegmentationUkmHelperTest, TestBasicReporting) {
+  // Allow results for OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB to be recorded.
+  InitializeAllowedSegmentIds("4");
+  std::vector<float> input_tensors = {0.1, 0.7, 0.8, 0.5};
+  SegmentationUkmHelper::GetInstance()->RecordModelExecutionResult(
+      optimization_guide::proto::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, 101,
+      input_tensors, 0.6);
+  ExpectUkmMetrics(
+      Segmentation_ModelExecution::kEntryName,
+      {Segmentation_ModelExecution::kOptimizationTargetName,
+       Segmentation_ModelExecution::kModelVersionName,
+       Segmentation_ModelExecution::kInput0Name,
+       Segmentation_ModelExecution::kInput1Name,
+       Segmentation_ModelExecution::kInput2Name,
+       Segmentation_ModelExecution::kInput3Name,
+       Segmentation_ModelExecution::kPredictionResultName},
+      {
+          optimization_guide::proto::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+          101,
+          SegmentationUkmHelper::FloatToInt64(0.1),
+          SegmentationUkmHelper::FloatToInt64(0.7),
+          SegmentationUkmHelper::FloatToInt64(0.8),
+          SegmentationUkmHelper::FloatToInt64(0.5),
+          SegmentationUkmHelper::FloatToInt64(0.6),
+      });
+}
+
+// Tests that recording is disabled if kSegmentationStructuredMetricsFeature
+// is disabled.
+TEST_F(SegmentationUkmHelperTest, TestDisabledStructuredMetrics) {
+  DisableStructureMetrics();
+  std::vector<float> input_tensors = {0.1, 0.7, 0.8, 0.5};
+  SegmentationUkmHelper::GetInstance()->RecordModelExecutionResult(
+      optimization_guide::proto::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, 101,
+      input_tensors, 0.6);
+  ExpectEmptyUkmMetrics(Segmentation_ModelExecution::kEntryName);
+}
+
+// Tests that recording is disabled for segment IDs that are not in the allowed
+// list.
+TEST_F(SegmentationUkmHelperTest, TestNotAllowedSegmentId) {
+  InitializeAllowedSegmentIds("7, 8");
+  std::vector<float> input_tensors = {0.1, 0.7, 0.8, 0.5};
+  SegmentationUkmHelper::GetInstance()->RecordModelExecutionResult(
+      optimization_guide::proto::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, 101,
+      input_tensors, 0.6);
+  ExpectEmptyUkmMetrics(Segmentation_ModelExecution::kEntryName);
+}
+
+// Tests that float encoding works properly.
+TEST_F(SegmentationUkmHelperTest, TestFloatEncoding) {
+  // Compare the numbers with their IEEE754 binary representations in double.
+  ASSERT_EQ(SegmentationUkmHelper::FloatToInt64(0.5), 0x3FE0000000000000);
+  ASSERT_EQ(SegmentationUkmHelper::FloatToInt64(0.25), 0x3FD0000000000000);
+  ASSERT_EQ(SegmentationUkmHelper::FloatToInt64(0.125), 0x3FC0000000000000);
+  ASSERT_EQ(SegmentationUkmHelper::FloatToInt64(0.75), 0x3FE8000000000000);
+  ASSERT_EQ(SegmentationUkmHelper::FloatToInt64(1), 0x3FF0000000000000);
+  ASSERT_EQ(SegmentationUkmHelper::FloatToInt64(0), 0);
+  ASSERT_EQ(SegmentationUkmHelper::FloatToInt64(10), 0x4024000000000000);
+}
+
+// Tests that floats encoded can be properly decoded later.
+TEST_F(SegmentationUkmHelperTest, FloatEncodeDeocode) {
+  CompareEncodeDecodeDifference(0.1);
+  CompareEncodeDecodeDifference(0.5);
+  CompareEncodeDecodeDifference(0.88);
+  CompareEncodeDecodeDifference(0.01);
+  ASSERT_EQ(0, Int64ToFloat(SegmentationUkmHelper::FloatToInt64(0)));
+  ASSERT_EQ(1, Int64ToFloat(SegmentationUkmHelper::FloatToInt64(1)));
+}
+
+// Tests that there are too many input tensors to record.
+TEST_F(SegmentationUkmHelperTest, TooManyInputTensors) {
+  base::HistogramTester tester;
+  std::string histogram_name(
+      "SegmentationPlatform.StructuredMetrics.TooManyTensors.Count");
+  InitializeAllowedSegmentIds("4");
+  std::vector<float> input_tensors(100, 0.1);
+  ukm::SourceId source_id =
+      SegmentationUkmHelper::GetInstance()->RecordModelExecutionResult(
+          optimization_guide::proto::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+          101, input_tensors, 0.6);
+  ASSERT_EQ(source_id, ukm::kInvalidSourceId);
+  tester.ExpectTotalCount(histogram_name, 1);
+  ASSERT_EQ(tester.GetTotalSum(histogram_name), 100);
+}
+}  // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/stats.cc b/components/segmentation_platform/internal/stats.cc
index 16fc93d3..2503e7ec 100644
--- a/components/segmentation_platform/internal/stats.cc
+++ b/components/segmentation_platform/internal/stats.cc
@@ -527,5 +527,11 @@
       availability);
 }
 
+void RecordTooManyInputTensors(int tensor_size) {
+  UMA_HISTOGRAM_COUNTS_100(
+      "SegmentationPlatform.StructuredMetrics.TooManyTensors.Count",
+      tensor_size);
+}
+
 }  // namespace stats
 }  // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/stats.h b/components/segmentation_platform/internal/stats.h
index 91f3713d..fb63787 100644
--- a/components/segmentation_platform/internal/stats.h
+++ b/components/segmentation_platform/internal/stats.h
@@ -179,6 +179,10 @@
 void RecordModelAvailability(OptimizationTarget segment_id,
                              SegmentationModelAvailability availability);
 
+// Records the number of input tensor that's causing a failure to upload
+// structured metrics.
+void RecordTooManyInputTensors(int tensor_size);
+
 }  // namespace stats
 }  // namespace segmentation_platform
 
diff --git a/components/segmentation_platform/public/config.h b/components/segmentation_platform/public/config.h
index cdc2658..13a98f5 100644
--- a/components/segmentation_platform/public/config.h
+++ b/components/segmentation_platform/public/config.h
@@ -33,6 +33,11 @@
 const char kChromeLowUserEngagementSegmentationKey[] =
     "chrome_low_user_engagement";
 
+// The key provide a list of segment IDs, separated by commas, whose ML model
+// execution results are allowed to be uploaded through UKM.
+const char kSegmentIdsAllowedForReportingKey[] =
+    "segment_ids_allowed_for_reporting";
+
 // Contains various finch configuration params used by the segmentation
 // platform.
 struct Config {
diff --git a/components/segmentation_platform/public/features.cc b/components/segmentation_platform/public/features.cc
index b81c01e1..105bceae 100644
--- a/components/segmentation_platform/public/features.cc
+++ b/components/segmentation_platform/public/features.cc
@@ -21,5 +21,7 @@
 const base::Feature kSegmentationPlatformDummyFeature{
     "SegmentationPlatformDummyFeature", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kSegmentationStructuredMetricsFeature{
+    "SegmentationStructuredMetrics", base::FEATURE_DISABLED_BY_DEFAULT};
 }  // namespace features
 }  // namespace segmentation_platform
diff --git a/components/segmentation_platform/public/features.h b/components/segmentation_platform/public/features.h
index 42753278..30411db 100644
--- a/components/segmentation_platform/public/features.h
+++ b/components/segmentation_platform/public/features.h
@@ -17,6 +17,8 @@
 // experimental models and data collection.
 extern const base::Feature kSegmentationPlatformDummyFeature;
 
+// Feature flag for allowing structured metrics to be collected.
+extern const base::Feature kSegmentationStructuredMetricsFeature;
 }  // namespace features
 }  // namespace segmentation_platform
 
diff --git a/components/services/storage/BUILD.gn b/components/services/storage/BUILD.gn
index 007edf0..00ed503c 100644
--- a/components/services/storage/BUILD.gn
+++ b/components/services/storage/BUILD.gn
@@ -77,6 +77,12 @@
     "service_worker/service_worker_storage.h",
     "service_worker/service_worker_storage_control_impl.cc",
     "service_worker/service_worker_storage_control_impl.h",
+    "shared_storage/async_shared_storage_database.cc",
+    "shared_storage/async_shared_storage_database.h",
+    "shared_storage/shared_storage_database.cc",
+    "shared_storage/shared_storage_database.h",
+    "shared_storage/shared_storage_options.cc",
+    "shared_storage/shared_storage_options.h",
     "storage_service_impl.cc",
     "storage_service_impl.h",
   ]
@@ -90,6 +96,7 @@
     "//components/services/storage/service_worker:service_worker_proto",
     "//mojo/public/cpp/bindings",
     "//sql",
+    "//third_party/abseil-cpp:absl",
     "//third_party/blink/public/common",
     "//third_party/leveldatabase",
     "//url",
@@ -101,6 +108,7 @@
     "//net",
     "//services/network/public/cpp",
     "//services/network/public/mojom",
+    "//storage/browser",
     "//storage/common",
   ]
 }
@@ -136,6 +144,18 @@
   defines = [ "IS_STORAGE_SERVICE_TEST_API_STUBS_IMPL" ]
 }
 
+bundle_data("tests_bundle_data") {
+  visibility = [ ":tests" ]
+  testonly = true
+  sources = [
+    "//components/test/data/storage/shared_storage.v0.init_too_old.sql",
+    "//components/test/data/storage/shared_storage.v1.init_too_new.sql",
+    "//components/test/data/storage/shared_storage.v1.sql",
+  ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
+}
+
 source_set("tests") {
   testonly = true
 
@@ -164,12 +184,15 @@
     "service_worker/service_worker_storage_test_utils.cc",
     "service_worker/service_worker_storage_test_utils.h",
     "service_worker/service_worker_storage_unittest.cc",
+    "shared_storage/async_shared_storage_database_unittest.cc",
+    "shared_storage/shared_storage_database_unittest.cc",
     "storage_service_impl_unittest.cc",
   ]
 
   deps = [
     ":storage",
     ":test_support",
+    ":tests_bundle_data",
     "//base",
     "//base/test:test_support",
     "//components/services/storage/public/cpp",
@@ -180,8 +203,13 @@
     "//mojo/public/cpp/system",
     "//net",
     "//net:test_support",
+    "//sql",
+    "//sql:test_support",
+    "//storage/browser:browser",
+    "//storage/browser:test_support",
     "//testing/gmock",
     "//testing/gtest",
+    "//third_party/sqlite",
   ]
 
   data = [ "//components/services/storage/test_data/" ]
@@ -201,11 +229,14 @@
     "indexed_db/leveldb/mock_level_db.h",
     "indexed_db/scopes/leveldb_scopes_test_utils.cc",
     "indexed_db/scopes/leveldb_scopes_test_utils.h",
+    "shared_storage/shared_storage_test_utils.cc",
+    "shared_storage/shared_storage_test_utils.h",
   ]
 
   deps = [
     ":storage",
     "//base/test:test_support",
+    "//sql:test_support",
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/leveldatabase",
diff --git a/components/services/storage/DEPS b/components/services/storage/DEPS
index fadaaf0..8c47aae7 100644
--- a/components/services/storage/DEPS
+++ b/components/services/storage/DEPS
@@ -4,4 +4,6 @@
   "+third_party/blink/public/mojom",
   "+third_party/leveldatabase",
   "+sql",
+  "+storage/browser/quota/special_storage_policy.h",
+  "+storage/browser/test/mock_special_storage_policy.h",
 ]
diff --git a/components/services/storage/shared_storage/DIR_METADATA b/components/services/storage/shared_storage/DIR_METADATA
new file mode 100644
index 0000000..95ccec4a
--- /dev/null
+++ b/components/services/storage/shared_storage/DIR_METADATA
@@ -0,0 +1,12 @@
+# Metadata information for this directory.
+#
+# For more information on DIR_METADATA files, see:
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
+#
+# For the schema of this file, see Metadata message:
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+
+monorail {
+  component: "Blink>Storage>SharedStorage"
+}
+team_email: "chrome-ads-core@google.com"
diff --git a/components/services/storage/shared_storage/OWNERS b/components/services/storage/shared_storage/OWNERS
new file mode 100644
index 0000000..6ab8756
--- /dev/null
+++ b/components/services/storage/shared_storage/OWNERS
@@ -0,0 +1,6 @@
+# Primary:
+cammie@chromium.org
+
+# Secondary:
+yaoxia@chromium.org
+jkarlin@chromium.org
diff --git a/components/services/storage/shared_storage/async_shared_storage_database.cc b/components/services/storage/shared_storage/async_shared_storage_database.cc
new file mode 100644
index 0000000..3a6d9f4
--- /dev/null
+++ b/components/services/storage/shared_storage/async_shared_storage_database.cc
@@ -0,0 +1,196 @@
+// Copyright 2021 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/services/storage/shared_storage/async_shared_storage_database.h"
+
+#include <inttypes.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/files/file_util.h"
+#include "base/time/time.h"
+#include "components/services/storage/public/mojom/storage_usage_info.mojom.h"
+#include "components/services/storage/shared_storage/shared_storage_options.h"
+#include "storage/browser/quota/special_storage_policy.h"
+#include "url/origin.h"
+
+namespace storage {
+
+// static
+std::unique_ptr<AsyncSharedStorageDatabase> AsyncSharedStorageDatabase::Create(
+    base::FilePath db_path,
+    scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+    scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
+    std::unique_ptr<SharedStorageDatabaseOptions> options) {
+  return absl::WrapUnique(new AsyncSharedStorageDatabase(
+      std::move(db_path), std::move(blocking_task_runner),
+      std::move(special_storage_policy), std::move(options)));
+}
+
+AsyncSharedStorageDatabase::AsyncSharedStorageDatabase(
+    base::FilePath db_path,
+    scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+    scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
+    std::unique_ptr<SharedStorageDatabaseOptions> options)
+    : database_(base::SequenceBound<SharedStorageDatabase>(
+          std::move(blocking_task_runner),
+          std::move(db_path),
+          std::move(special_storage_policy),
+          std::move(options))) {}
+
+AsyncSharedStorageDatabase::~AsyncSharedStorageDatabase() = default;
+
+void AsyncSharedStorageDatabase::Destroy(
+    base::OnceCallback<void(bool)> callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::Destroy)
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::TrimMemory(base::OnceClosure callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::TrimMemory)
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::Get(
+    url::Origin context_origin,
+    std::u16string key,
+    base::OnceCallback<void(GetResult)> callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::Get)
+      .WithArgs(std::move(context_origin), std::move(key))
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::Set(
+    url::Origin context_origin,
+    std::u16string key,
+    std::u16string value,
+    base::OnceCallback<void(OperationResult)> callback,
+    SetBehavior behavior) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::Set)
+      .WithArgs(std::move(context_origin), std::move(key), std::move(value),
+                behavior)
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::Append(
+    url::Origin context_origin,
+    std::u16string key,
+    std::u16string value,
+    base::OnceCallback<void(OperationResult)> callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::Append)
+      .WithArgs(std::move(context_origin), std::move(key), std::move(value))
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::Delete(
+    url::Origin context_origin,
+    std::u16string key,
+    base::OnceCallback<void(OperationResult)> callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::Delete)
+      .WithArgs(std::move(context_origin), std::move(key))
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::Clear(
+    url::Origin context_origin,
+    base::OnceCallback<void(OperationResult)> callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::Clear)
+      .WithArgs(std::move(context_origin))
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::Length(
+    url::Origin context_origin,
+    base::OnceCallback<void(int)> callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::Length)
+      .WithArgs(std::move(context_origin))
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::Key(
+    url::Origin context_origin,
+    int index,
+    base::OnceCallback<void(GetResult)> callback) {
+  DCHECK_GE(index, 0);
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::Key)
+      .WithArgs(std::move(context_origin), static_cast<uint64_t>(index))
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::PurgeMatchingOrigins(
+    OriginMatcherFunction origin_matcher,
+    base::Time begin,
+    base::Time end,
+    base::OnceCallback<void(OperationResult)> callback,
+    bool perform_storage_cleanup) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::PurgeMatchingOrigins)
+      .WithArgs(std::move(origin_matcher), begin, end, perform_storage_cleanup)
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::PurgeStaleOrigins(
+    base::TimeDelta window_to_be_deemed_active,
+    base::OnceCallback<void(OperationResult)> callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::PurgeStaleOrigins)
+      .WithArgs(window_to_be_deemed_active)
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::FetchOrigins(
+    base::OnceCallback<void(std::vector<mojom::StorageUsageInfoPtr>)>
+        callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::FetchOrigins)
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::IsOpenForTesting(
+    base::OnceCallback<void(bool)> callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::IsOpenForTesting)
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::DBStatusForTesting(
+    base::OnceCallback<void(InitStatus)> callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::DBStatusForTesting)
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::OverrideLastUsedTimeForTesting(
+    url::Origin context_origin,
+    base::Time override_last_used_time,
+    base::OnceCallback<void(bool)> callback) {
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::OverrideLastUsedTimeForTesting)
+      .WithArgs(std::move(context_origin), override_last_used_time)
+      .Then(std::move(callback));
+}
+
+void AsyncSharedStorageDatabase::OverrideSpecialStoragePolicyForTesting(
+    scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
+    base::OnceCallback<void(bool)> callback) {
+  DCHECK(database_);
+  database_
+      .AsyncCall(&SharedStorageDatabase::OverrideSpecialStoragePolicyForTesting)
+      .WithArgs(std::move(special_storage_policy))
+      .Then(std::move(callback));
+}
+
+}  // namespace storage
diff --git a/components/services/storage/shared_storage/async_shared_storage_database.h b/components/services/storage/shared_storage/async_shared_storage_database.h
new file mode 100644
index 0000000..1771c4f
--- /dev/null
+++ b/components/services/storage/shared_storage/async_shared_storage_database.h
@@ -0,0 +1,237 @@
+// Copyright 2021 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_SERVICES_STORAGE_SHARED_STORAGE_ASYNC_SHARED_STORAGE_DATABASE_H_
+#define COMPONENTS_SERVICES_STORAGE_SHARED_STORAGE_ASYNC_SHARED_STORAGE_DATABASE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/threading/sequence_bound.h"
+#include "components/services/storage/shared_storage/shared_storage_database.h"
+
+namespace base {
+class FilePath;
+class Time;
+class TimeDelta;
+}  // namespace base
+
+namespace url {
+class Origin;
+}  // namespace url
+
+namespace storage {
+struct SharedStorageDatabaseOptions;
+class SpecialStoragePolicy;
+
+// A wrapper around SharedStorageDatabase which makes the operations
+// asynchronous.
+class AsyncSharedStorageDatabase {
+ public:
+  using InitStatus = SharedStorageDatabase::InitStatus;
+  using SetBehavior = SharedStorageDatabase::SetBehavior;
+  using OperationResult = SharedStorageDatabase::OperationResult;
+  using GetResult = SharedStorageDatabase::GetResult;
+
+  // A callback type to check if a given origin matches a storage policy.
+  // Can be passed empty/null where used, which means the origin will always
+  // match.
+  using OriginMatcherFunction = SharedStorageDatabase::OriginMatcherFunction;
+
+  // Creates an `AsyncSharedStorageDatabase` instance. If `db_path` is empty,
+  // creates a temporary, in-memory database; otherwise creates a persistent
+  // database within a filesystem directory given by `db_path`, which must be an
+  // absolute path. If file-backed, the database may or may not already exist at
+  // `db_path`, and if it doesn't, it will be created.
+  //
+  // The instance will be bound to and perform all operations on
+  // `blocking_task_runner`, which must support blocking operations.
+  static std::unique_ptr<AsyncSharedStorageDatabase> Create(
+      base::FilePath db_path,
+      scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+      scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
+      std::unique_ptr<SharedStorageDatabaseOptions> options);
+
+  AsyncSharedStorageDatabase(const AsyncSharedStorageDatabase&) = delete;
+  AsyncSharedStorageDatabase& operator=(const AsyncSharedStorageDatabase&) =
+      delete;
+  AsyncSharedStorageDatabase(const AsyncSharedStorageDatabase&&) = delete;
+  AsyncSharedStorageDatabase& operator=(const AsyncSharedStorageDatabase&&) =
+      delete;
+
+  ~AsyncSharedStorageDatabase();
+
+  base::SequenceBound<SharedStorageDatabase>&
+  GetSequenceBoundDatabaseForTesting() {
+    return database_;
+  }
+
+  // Destroys the database.
+  //
+  // If filebacked, deletes the persistent database within the filesystem
+  // directory.
+  //
+  // It is OK to call `Destroy()` regardless of whether database initialization
+  // was successful.
+  void Destroy(base::OnceCallback<void(bool)> callback);
+
+  // `TrimMemory()`, `Get()`, `Set()`, `Append()`, `Delete()`, `Clear()`,
+  // `Length()`, `Key()`, `PurgeMatchingOrigins()`, `PurgeStaleOrigins()`, and
+  // `FetchOrigins()` are all async versions of the corresponding methods in
+  // `storage::SharedStorageDatabase`, with the modification that `Set()` and
+  // `Append()` take a boolean callback to indicate that a value was set or
+  // appended, rather than a long integer callback with the row number for the
+  // next available row.
+  //
+  // It is OK to call these async methods even if the database has failed to
+  // initialize, as there is an alternate code path to handle this case that
+  // skips accessing `database_` (as it will be null) and hence performing the
+  // intending operation, logs the occurrence of the missing database to UMA,
+  // and runs the callback with a trivial instance of its expected result type).
+
+  // Releases all non-essential memory associated with this database connection.
+  // `callback` runs once the operation is finished.
+  void TrimMemory(base::OnceClosure callback);
+
+  // Retrieves the `value` for `context_origin` and `key`. `callback` is called
+  // with a struct bundling a string `value` in its data field if one is found,
+  // `absl::nullopt` otherwise, and a OperationResult to indicate whether the
+  // transaction was free of database errors.
+  //
+  // `key` must be of length at most
+  // `SharedStorageDatabaseOptions::max_string_length`, with the burden on the
+  // caller to handle errors for strings that exceed this length.
+  void Get(url::Origin context_origin,
+           std::u16string key,
+           base::OnceCallback<void(GetResult)> callback);
+
+  // Sets an entry for `context_origin` and `key` to have `value`.
+  // If `behavior` is `kIgnoreIfPresent` and an entry already exists for
+  // `context_origin` and `key`, then the database table is not modified.
+  // The parameter of `callback` reports whether or not any entry is added, the
+  // request is ignored, or if there is an error.
+  //
+  // `key` and `value` must be each of length at most
+  // `SharedStorageDatabaseOptions::max_string_length`, with the burden on the
+  // caller to handle errors for strings that exceed this length. Moreover, if
+  // the length retrieved by `Length(context_origin, callback)` equals
+  // `SharedStorageDatabaseOptions::max_entries_per_origin_`, `Set()` will fail
+  // and the table will not be modified.
+  void Set(url::Origin context_origin,
+           std::u16string key,
+           std::u16string value,
+           base::OnceCallback<void(OperationResult)> callback,
+           SetBehavior behavior = SetBehavior::kDefault);
+
+  // Appends `value` to the end of the current `value` for `context_origin` and
+  // `key`, if `key` exists. If `key` does not exist, creates an entry for `key`
+  // with value `value`. The parameter of `callback` reports whether or not any
+  // entry is added or modified or if there is an error.
+  //
+  // `key` and `value` must be each of length at most
+  // `SharedStorageDatabaseOptions::max_string_length`, with the burden on the
+  // caller to handle errors for strings that exceed this length. Moreover, if
+  // the length of the string obtained by concatening the current `script_value`
+  // (if one exists) and `value` exceeds
+  // `SharedStorageDatabaseOptions::max_string_length`, or if the length
+  // retrieved by `Length(context_origin, callback)` equals
+  // `SharedStorageDatabaseOptions::max_entries_per_origin_`, `Append()` will
+  // fail and the database table will not be modified.
+  void Append(url::Origin context_origin,
+              std::u16string key,
+              std::u16string value,
+              base::OnceCallback<void(OperationResult)> callback);
+
+  // Deletes the entry for `context_origin` and `key`. The parameter of
+  // `callback` reports whether the deletion is successful.
+  //
+  // `key` must be of length at most
+  // `SharedStorageDatabaseOptions::max_string_length`, with the burden on the
+  // caller to handle errors for strings that exceed this length.
+  void Delete(url::Origin context_origin,
+              std::u16string key,
+              base::OnceCallback<void(OperationResult)> callback);
+
+  // Clears all entries for `context_origin`. The parameter of `callback`
+  // reports whether the operation is successful.
+  void Clear(url::Origin context_origin,
+             base::OnceCallback<void(OperationResult)> callback);
+
+  // The parameter of `callback` reports the number of entries for
+  // `context_origin`, 0 if there are none, or -1 on operation failure.
+  void Length(url::Origin context_origin,
+              base::OnceCallback<void(int)> callback);
+
+  // If a list of all the keys for `context_origin` are taken in lexicographic
+  // order, retrieves the `key` at `index` of the list and calls `callback` with
+  // a struct bundling it as a parameter (along with a OperationResult to
+  // indicate whether the transaction was free of database errors); otherwise
+  // calls `callback` with `absl::nullopt` in the data field of the struct.
+  // `index` must be non-negative.
+  //
+  // TODO(crbug.com/1247861): Replace with an async iterator.
+  void Key(url::Origin context_origin,
+           int index,
+           base::OnceCallback<void(GetResult)> callback);
+
+  // Clears all origins that match `origin_matcher` run on the owning
+  // StoragePartition's `SpecialStoragePolicy` and have `last_used_time` between
+  // the times `begin` and `end`. If `perform_storage_cleanup` is true, vacuums
+  // the database afterwards. The parameter of `callback` reports whether the
+  // transaction was successful.
+  //
+  // Note that `origin_matcher` is accessed on a different sequence than where
+  // it was created.
+  void PurgeMatchingOrigins(OriginMatcherFunction origin_matcher,
+                            base::Time begin,
+                            base::Time end,
+                            base::OnceCallback<void(OperationResult)> callback,
+                            bool perform_storage_cleanup = false);
+
+  // Clear all entries for all origins whose `last_read_time` falls before
+  // `base::Time::Now() - window_to_be_deemed_active`.
+  void PurgeStaleOrigins(base::TimeDelta window_to_be_deemed_active,
+                         base::OnceCallback<void(OperationResult)> callback);
+
+  // Fetches a vector of `mojom::StorageUsageInfoPtr`, with one
+  // `mojom::StorageUsageInfoPtr` for each origin currently using shared storage
+  // in this profile.
+  void FetchOrigins(
+      base::OnceCallback<void(std::vector<mojom::StorageUsageInfoPtr>)>
+          callback);
+
+  // Asynchronously determines whether the database is open. Useful for testing.
+  void IsOpenForTesting(base::OnceCallback<void(bool)> callback);
+
+  // Asynchronously determines the database `InitStatus`. Useful for testing.
+  void DBStatusForTesting(base::OnceCallback<void(InitStatus)> callback);
+
+  // Changes `last_used_time` to `override_last_used_time` for `context_origin`.
+  void OverrideLastUsedTimeForTesting(url::Origin context_origin,
+                                      base::Time override_last_used_time,
+                                      base::OnceCallback<void(bool)> callback);
+
+  // Overrides the `SpecialStoragePolicy` for tests.
+  void OverrideSpecialStoragePolicyForTesting(
+      scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
+      base::OnceCallback<void(bool)> callback);
+
+ private:
+  // Instances should be obtained from the `Create()` factory method.
+  AsyncSharedStorageDatabase(
+      base::FilePath db_path,
+      scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+      scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
+      std::unique_ptr<SharedStorageDatabaseOptions> options);
+
+  base::SequenceBound<SharedStorageDatabase> database_;
+};
+
+}  // namespace storage
+
+#endif  // COMPONENTS_SERVICES_STORAGE_SHARED_STORAGE_ASYNC_SHARED_STORAGE_DATABASE_H_
diff --git a/components/services/storage/shared_storage/async_shared_storage_database_unittest.cc b/components/services/storage/shared_storage/async_shared_storage_database_unittest.cc
new file mode 100644
index 0000000..fdf3041a
--- /dev/null
+++ b/components/services/storage/shared_storage/async_shared_storage_database_unittest.cc
@@ -0,0 +1,1648 @@
+// Copyright 2021 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/services/storage/shared_storage/async_shared_storage_database.h"
+
+#include <memory>
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/strings/strcat.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/thread_pool.h"
+#include "base/test/bind.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
+#include "base/threading/sequence_bound.h"
+#include "base/threading/thread.h"
+#include "components/services/storage/public/mojom/storage_usage_info.mojom.h"
+#include "components/services/storage/shared_storage/shared_storage_database.h"
+#include "components/services/storage/shared_storage/shared_storage_options.h"
+#include "components/services/storage/shared_storage/shared_storage_test_utils.h"
+#include "sql/database.h"
+#include "storage/browser/quota/special_storage_policy.h"
+#include "storage/browser/test/mock_special_storage_policy.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace storage {
+
+namespace {
+
+using ::testing::ElementsAre;
+using InitStatus = SharedStorageDatabase::InitStatus;
+using SetBehavior = SharedStorageDatabase::SetBehavior;
+using OperationResult = SharedStorageDatabase::OperationResult;
+using GetResult = SharedStorageDatabase::GetResult;
+using DBOperation = TestDatabaseOperationReceiver::DBOperation;
+using Type = DBOperation::Type;
+
+const int kMaxEntriesPerOrigin = 5;
+const int kMaxStringLength = 100;
+
+}  // namespace
+
+class AsyncSharedStorageDatabaseTest : public testing::Test {
+ public:
+  AsyncSharedStorageDatabaseTest()
+      : task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
+            {base::MayBlock(), base::WithBaseSyncPrimitives(),
+             base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+        special_storage_policy_(
+            base::MakeRefCounted<MockSpecialStoragePolicy>()),
+        receiver_(std::make_unique<TestDatabaseOperationReceiver>()) {}
+
+  ~AsyncSharedStorageDatabaseTest() override = default;
+
+  void SetUp() override {
+    InitSharedStorageFeature();
+
+    // Get a temporary directory for the test DB files.
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+    file_name_ = temp_dir_.GetPath().AppendASCII("TestSharedStorage.db");
+  }
+
+  void TearDown() override {
+    task_environment_.RunUntilIdle();
+
+    // It's not strictly necessary as part of test cleanup, but here we test
+    // the code path that force razes the database, and, if file-backed,
+    // force deletes the database file.
+    EXPECT_TRUE(DestroySync());
+    EXPECT_FALSE(base::PathExists(file_name_));
+    EXPECT_TRUE(temp_dir_.Delete());
+  }
+
+  virtual void InitSharedStorageFeature() {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        {blink::features::kSharedStorageAPI},
+        {{"MaxSharedStorageInitTries", "1"}});
+  }
+
+  // Initialize an async shared storage database instance from the SQL file at
+  // `relative_file_path` in the "storage/" subdirectory of test data.
+  void LoadFromFileSync(const char* relative_file_path) {
+    DCHECK(!file_name_.empty());
+
+    ASSERT_TRUE(CreateDatabaseFromSQL(file_name_, relative_file_path));
+
+    async_database_ = AsyncSharedStorageDatabase::Create(
+        file_name_, task_runner_, special_storage_policy_,
+        SharedStorageOptions::Create()->GetDatabaseOptions());
+  }
+
+  void CreateSync(const base::FilePath& db_path,
+                  std::unique_ptr<SharedStorageDatabaseOptions> options) {
+    async_database_ = AsyncSharedStorageDatabase::Create(
+        db_path, task_runner_, special_storage_policy_, std::move(options));
+  }
+
+  void Destroy(bool* out_success) {
+    DCHECK(out_success);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    DBOperation operation(Type::DB_DESTROY);
+    auto callback =
+        receiver_->MakeBoolCallback(std::move(operation), out_success);
+    async_database_->Destroy(std::move(callback));
+  }
+
+  bool DestroySync() {
+    if (!async_database_)
+      return true;
+
+    base::test::TestFuture<bool> future;
+    async_database_->Destroy(future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+    return future.Get();
+  }
+
+  bool is_finished() const {
+    DCHECK(receiver_);
+    return receiver_->is_finished();
+  }
+
+  void SetExpectedOperationList(std::queue<DBOperation> expected_operations) {
+    DCHECK(receiver_);
+    receiver_->set_expected_operations(std::move(expected_operations));
+  }
+
+  void WaitForOperations() {
+    DCHECK(receiver_);
+    receiver_->WaitForOperations();
+  }
+
+  void VerifySharedStorageTablesAndColumnsSync() {
+    DCHECK(async_database_);
+
+    auto task = base::BindOnce([](SharedStorageDatabase* db) -> bool {
+      auto* sql_db = db->db();
+      EXPECT_TRUE(sql_db);
+      VerifySharedStorageTablesAndColumns(*sql_db);
+      return true;
+    });
+
+    base::test::TestFuture<bool> future;
+
+    auto wrapped_task = base::BindOnce(
+        [](base::OnceCallback<bool(SharedStorageDatabase*)> task,
+           base::OnceCallback<void(bool)> callback,
+           scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+           SharedStorageDatabase* db) {
+          callback_task_runner->PostTask(
+              FROM_HERE,
+              base::BindOnce(std::move(callback), std::move(task).Run(db)));
+        },
+        std::move(task), future.GetCallback(),
+        base::SequencedTaskRunnerHandle::Get());
+
+    async_database_->GetSequenceBoundDatabaseForTesting()
+        .PostTaskWithThisObject(std::move(wrapped_task));
+
+    EXPECT_TRUE(future.Wait());
+    EXPECT_TRUE(future.Get());
+  }
+
+  void IsOpen(bool* out_boolean) {
+    DCHECK(out_boolean);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    DBOperation operation(Type::DB_IS_OPEN);
+    auto callback =
+        receiver_->MakeBoolCallback(std::move(operation), out_boolean);
+    async_database_->IsOpenForTesting(std::move(callback));
+  }
+
+  bool IsOpenSync() {
+    DCHECK(async_database_);
+
+    base::test::TestFuture<bool> future;
+    async_database_->IsOpenForTesting(future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+    return future.Get();
+  }
+
+  void DBStatus(InitStatus* out_status) {
+    DCHECK(out_status);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    DBOperation operation(Type::DB_STATUS);
+    auto callback =
+        receiver_->MakeStatusCallback(std::move(operation), out_status);
+    async_database_->DBStatusForTesting(std::move(callback));
+  }
+
+  InitStatus DBStatusSync() {
+    DCHECK(async_database_);
+
+    base::test::TestFuture<InitStatus> future;
+    async_database_->DBStatusForTesting(future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+    return future.Get();
+  }
+
+  void TrimMemory() {
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    DBOperation operation(Type::DB_TRIM_MEMORY);
+    auto callback = receiver_->MakeOnceClosure(std::move(operation));
+    async_database_->TrimMemory(std::move(callback));
+  }
+
+  void OverrideLastUsedTime(url::Origin context_origin,
+                            base::Time override_last_used_time,
+                            bool* out_success) {
+    DCHECK(out_success);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    DBOperation operation(Type::DB_OVERRIDE_TIME, context_origin,
+                          {TestDatabaseOperationReceiver::SerializeTime(
+                              override_last_used_time)});
+    auto callback =
+        receiver_->MakeBoolCallback(std::move(operation), out_success);
+    async_database_->OverrideLastUsedTimeForTesting(std::move(context_origin),
+                                                    override_last_used_time,
+                                                    std::move(callback));
+  }
+
+  void Get(url::Origin context_origin,
+           std::u16string key,
+           GetResult* out_value) {
+    DCHECK(out_value);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    DBOperation operation(Type::DB_GET, context_origin, {key});
+    auto callback =
+        receiver_->MakeGetResultCallback(std::move(operation), out_value);
+    async_database_->Get(std::move(context_origin), std::move(key),
+                         std::move(callback));
+  }
+
+  GetResult GetSync(url::Origin context_origin, std::u16string key) {
+    DCHECK(async_database_);
+
+    base::test::TestFuture<GetResult> future;
+    async_database_->Get(std::move(context_origin), std::move(key),
+                         future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+    return future.Get();
+  }
+
+  void Set(url::Origin context_origin,
+           std::u16string key,
+           std::u16string value,
+           OperationResult* out_result,
+           SetBehavior behavior = SetBehavior::kDefault) {
+    DCHECK(out_result);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    *out_result = OperationResult::kSqlError;
+    DBOperation operation(
+        Type::DB_SET, context_origin,
+        {key, value, base::NumberToString16(static_cast<int>(behavior))});
+    auto callback = receiver_->MakeOperationResultCallback(std::move(operation),
+                                                           out_result);
+    async_database_->Set(std::move(context_origin), std::move(key),
+                         std::move(value), std::move(callback), behavior);
+  }
+
+  OperationResult SetSync(url::Origin context_origin,
+                          std::u16string key,
+                          std::u16string value,
+                          SetBehavior behavior = SetBehavior::kDefault) {
+    DCHECK(async_database_);
+
+    base::test::TestFuture<OperationResult> future;
+    async_database_->Set(std::move(context_origin), std::move(key),
+                         std::move(value), future.GetCallback(), behavior);
+    EXPECT_TRUE(future.Wait());
+    return future.Get();
+  }
+
+  void Append(url::Origin context_origin,
+              std::u16string key,
+              std::u16string value,
+              OperationResult* out_result) {
+    DCHECK(out_result);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    *out_result = OperationResult::kSqlError;
+    DBOperation operation(Type::DB_APPEND, context_origin, {key, value});
+    auto callback = receiver_->MakeOperationResultCallback(std::move(operation),
+                                                           out_result);
+    async_database_->Append(std::move(context_origin), std::move(key),
+                            std::move(value), std::move(callback));
+  }
+
+  OperationResult AppendSync(url::Origin context_origin,
+                             std::u16string key,
+                             std::u16string value) {
+    DCHECK(async_database_);
+
+    base::test::TestFuture<OperationResult> future;
+    async_database_->Append(std::move(context_origin), std::move(key),
+                            std::move(value), future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+    return future.Get();
+  }
+
+  void Delete(url::Origin context_origin,
+              std::u16string key,
+              OperationResult* out_result) {
+    DCHECK(out_result);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    *out_result = OperationResult::kSqlError;
+    DBOperation operation(Type::DB_DELETE, context_origin, {key});
+    auto callback = receiver_->MakeOperationResultCallback(std::move(operation),
+                                                           out_result);
+    async_database_->Delete(std::move(context_origin), std::move(key),
+                            std::move(callback));
+  }
+
+  OperationResult DeleteSync(url::Origin context_origin, std::u16string key) {
+    DCHECK(async_database_);
+
+    base::test::TestFuture<OperationResult> future;
+    async_database_->Delete(std::move(context_origin), std::move(key),
+                            future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+    return future.Get();
+  }
+
+  void Length(url::Origin context_origin, int* out_length) {
+    DCHECK(out_length);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    *out_length = -1;
+    DBOperation operation(Type::DB_LENGTH, context_origin);
+    auto callback =
+        receiver_->MakeIntCallback(std::move(operation), out_length);
+    async_database_->Length(std::move(context_origin), std::move(callback));
+  }
+
+  int LengthSync(url::Origin context_origin) {
+    DCHECK(async_database_);
+
+    base::test::TestFuture<int> future;
+    async_database_->Length(std::move(context_origin), future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+    return future.Get();
+  }
+
+  void Key(url::Origin context_origin, int index, GetResult* out_key) {
+    DCHECK(out_key);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    DBOperation operation(Type::DB_KEY, context_origin,
+                          {base::NumberToString16(index)});
+    auto callback =
+        receiver_->MakeGetResultCallback(std::move(operation), out_key);
+    async_database_->Key(std::move(context_origin), index, std::move(callback));
+  }
+
+  GetResult KeySync(url::Origin context_origin, int index) {
+    DCHECK(async_database_);
+
+    base::test::TestFuture<GetResult> future;
+    async_database_->Key(std::move(context_origin), index,
+                         future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+    return future.Get();
+  }
+
+  void Clear(url::Origin context_origin, OperationResult* out_result) {
+    DCHECK(out_result);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    *out_result = OperationResult::kSqlError;
+    DBOperation operation(Type::DB_CLEAR, context_origin);
+    auto callback = receiver_->MakeOperationResultCallback(std::move(operation),
+                                                           out_result);
+    async_database_->Clear(std::move(context_origin), std::move(callback));
+  }
+
+  OperationResult ClearSync(url::Origin context_origin) {
+    DCHECK(async_database_);
+
+    base::test::TestFuture<OperationResult> future;
+    async_database_->Clear(std::move(context_origin), future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+    return future.Get();
+  }
+
+  void FetchOrigins(std::vector<mojom::StorageUsageInfoPtr>* out_result) {
+    DCHECK(out_result);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    DBOperation operation(Type::DB_FETCH_ORIGINS);
+    auto callback =
+        receiver_->MakeInfosCallback(std::move(operation), out_result);
+    async_database_->FetchOrigins(std::move(callback));
+  }
+
+  std::vector<mojom::StorageUsageInfoPtr> FetchOriginsSync() {
+    DCHECK(async_database_);
+
+    base::test::TestFuture<std::vector<mojom::StorageUsageInfoPtr>> future;
+    async_database_->FetchOrigins(future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+    return future.Take();
+  }
+
+  void PurgeMatchingOrigins(OriginMatcherFunctionUtility* matcher_utility,
+                            size_t matcher_id,
+                            base::Time begin,
+                            base::Time end,
+                            OperationResult* out_result,
+                            bool perform_storage_cleanup = false) {
+    DCHECK(out_result);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+    DCHECK(matcher_utility);
+    DCHECK(!(*matcher_utility).is_empty());
+    DCHECK_LT(matcher_id, (*matcher_utility).size());
+
+    std::vector<std::u16string> params(
+        {base::NumberToString16(matcher_id),
+         TestDatabaseOperationReceiver::SerializeTime(begin),
+         TestDatabaseOperationReceiver::SerializeTime(end),
+         TestDatabaseOperationReceiver::SerializeBool(
+             perform_storage_cleanup)});
+    DBOperation operation(Type::DB_PURGE_MATCHING, std::move(params));
+    auto callback = receiver_->MakeOperationResultCallback(std::move(operation),
+                                                           out_result);
+    async_database_->PurgeMatchingOrigins(
+        matcher_utility->TakeMatcherFunctionForId(matcher_id), begin, end,
+        std::move(callback), perform_storage_cleanup);
+  }
+
+  void PurgeStaleOrigins(base::TimeDelta window_to_be_deemed_active,
+                         OperationResult* out_result) {
+    DCHECK(out_result);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    DBOperation operation(Type::DB_PURGE_STALE,
+                          {TestDatabaseOperationReceiver::SerializeTimeDelta(
+                              window_to_be_deemed_active)});
+    auto callback = receiver_->MakeOperationResultCallback(std::move(operation),
+                                                           out_result);
+    async_database_->PurgeStaleOrigins(window_to_be_deemed_active,
+                                       std::move(callback));
+  }
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  scoped_refptr<storage::MockSpecialStoragePolicy> special_storage_policy_;
+  std::unique_ptr<AsyncSharedStorageDatabase> async_database_;
+  std::unique_ptr<TestDatabaseOperationReceiver> receiver_;
+  base::test::ScopedFeatureList scoped_feature_list_;
+  base::ScopedTempDir temp_dir_;
+  base::FilePath file_name_;
+};
+
+// Test loading version 1 database.
+TEST_F(AsyncSharedStorageDatabaseTest, Version1_LoadFromFile) {
+  LoadFromFileSync("shared_storage.v1.sql");
+  ASSERT_TRUE(async_database_);
+
+  url::Origin google_com = url::Origin::Create(GURL("http://google.com/"));
+  EXPECT_EQ(GetSync(google_com, u"key1").data, u"value1");
+  EXPECT_EQ(GetSync(google_com, u"key2").data, u"value2");
+
+  // Because the SQL database is lazy-initialized, wait to verify tables and
+  // columns until after the first call to `GetSync()`.
+  VerifySharedStorageTablesAndColumnsSync();
+
+  std::vector<url::Origin> origins;
+  for (const auto& info : FetchOriginsSync())
+    origins.push_back(info->origin);
+  EXPECT_THAT(
+      origins,
+      ElementsAre(url::Origin::Create(GURL("http://abc.xyz")),
+                  url::Origin::Create(GURL("http://chromium.org")), google_com,
+                  url::Origin::Create(GURL("http://google.org")),
+                  url::Origin::Create(GURL("http://growwithgoogle.com")),
+                  url::Origin::Create(GURL("http://gv.com")),
+                  url::Origin::Create(GURL("http://waymo.com")),
+                  url::Origin::Create(GURL("http://withgoogle.com")),
+                  url::Origin::Create(GURL("http://youtube.com"))));
+}
+
+TEST_F(AsyncSharedStorageDatabaseTest, Version1_DestroyTooNew) {
+  // Initialization should fail, since the last compatible version number
+  // is too high.
+  LoadFromFileSync("shared_storage.v1.init_too_new.sql");
+  ASSERT_TRUE(async_database_);
+
+  // Call an operation so that the database will attempt to be lazy-initialized.
+  EXPECT_EQ(
+      OperationResult::kInitFailure,
+      SetSync(url::Origin::Create(GURL("http://www.a.com")), u"key", u"value"));
+  ASSERT_FALSE(IsOpenSync());
+  EXPECT_EQ(InitStatus::kTooNew, DBStatusSync());
+
+  // Test that it is still OK to `Destroy()` the database.
+  EXPECT_TRUE(DestroySync());
+}
+
+TEST_F(AsyncSharedStorageDatabaseTest, Version0_DestroyTooOld) {
+  // Initialization should fail, since the current version number
+  // is too low and we're forcing there not to be a retry attempt.
+  LoadFromFileSync("shared_storage.v0.init_too_old.sql");
+  ASSERT_TRUE(async_database_);
+
+  // Call an operation so that the database will attempt to be lazy-initialized.
+  EXPECT_EQ(
+      OperationResult::kInitFailure,
+      SetSync(url::Origin::Create(GURL("http://www.a.com")), u"key", u"value"));
+  ASSERT_FALSE(IsOpenSync());
+  EXPECT_EQ(InitStatus::kTooOld, DBStatusSync());
+
+  // Test that it is still OK to `Destroy()` the database.
+  EXPECT_TRUE(DestroySync());
+}
+
+class AsyncSharedStorageDatabaseParamTest
+    : public AsyncSharedStorageDatabaseTest,
+      public testing::WithParamInterface<SharedStorageWrappedBool> {
+ public:
+  void SetUp() override {
+    AsyncSharedStorageDatabaseTest::SetUp();
+
+    auto options = SharedStorageOptions::Create()->GetDatabaseOptions();
+
+    if (GetParam().in_memory_only)
+      CreateSync(base::FilePath(), std::move(options));
+    else
+      CreateSync(file_name_, std::move(options));
+  }
+
+  void TearDown() override {
+    if (!GetParam().in_memory_only) {
+      // `TearDown()` will call `DestroySync()`. First verify that the file
+      // exists, so that when the we verify after destruction in `TearDown()`
+      // that the file no longer exists, we know that `Destroy()` was indeed
+      // successful.
+      EXPECT_TRUE(base::PathExists(file_name_));
+    }
+
+    AsyncSharedStorageDatabaseTest::TearDown();
+  }
+
+  void InitSharedStorageFeature() override {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        {blink::features::kSharedStorageAPI},
+        {{"MaxSharedStorageEntriesPerOrigin",
+          base::NumberToString(kMaxEntriesPerOrigin)},
+         {"MaxSharedStorageStringLength",
+          base::NumberToString(kMaxStringLength)}});
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         AsyncSharedStorageDatabaseParamTest,
+                         testing::ValuesIn(GetSharedStorageWrappedBools()),
+                         testing::PrintToStringParamName());
+
+// Operations are tested more thoroughly in shared_storage_database_unittest.cc.
+TEST_P(AsyncSharedStorageDatabaseParamTest, SyncOperations) {
+  url::Origin kOrigin1 = url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, SetSync(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(GetSync(kOrigin1, u"key1").data, u"value1");
+
+  EXPECT_EQ(OperationResult::kSet, SetSync(kOrigin1, u"key1", u"value2"));
+  EXPECT_EQ(GetSync(kOrigin1, u"key1").data, u"value2");
+
+  EXPECT_EQ(OperationResult::kSet, SetSync(kOrigin1, u"key2", u"value1"));
+  EXPECT_EQ(GetSync(kOrigin1, u"key2").data, u"value1");
+  EXPECT_EQ(2, LengthSync(kOrigin1));
+
+  EXPECT_EQ(OperationResult::kSuccess, DeleteSync(kOrigin1, u"key1"));
+  EXPECT_FALSE(GetSync(kOrigin1, u"key1").data);
+  EXPECT_EQ(1, LengthSync(kOrigin1));
+
+  EXPECT_EQ(OperationResult::kSet, AppendSync(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(GetSync(kOrigin1, u"key1").data, u"value1");
+  EXPECT_EQ(2, LengthSync(kOrigin1));
+
+  EXPECT_EQ(OperationResult::kSet, AppendSync(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(GetSync(kOrigin1, u"key1").data,
+            base::StrCat({u"value1", u"value1"}));
+  EXPECT_EQ(2, LengthSync(kOrigin1));
+
+  EXPECT_EQ(KeySync(kOrigin1, 0).data, u"key1");
+  EXPECT_EQ(KeySync(kOrigin1, 1).data, u"key2");
+
+  EXPECT_EQ(OperationResult::kSuccess, ClearSync(kOrigin1));
+  EXPECT_EQ(0, LengthSync(kOrigin1));
+}
+
+// Verifies that the async operations are executed in order and without races.
+TEST_P(AsyncSharedStorageDatabaseParamTest, AsyncOperations) {
+  url::Origin kOrigin1 = url::Origin::Create(GURL("http://www.example1.test"));
+
+  std::queue<DBOperation> operation_list(
+      {{Type::DB_SET,
+        kOrigin1,
+        {u"key1", u"value1",
+         TestDatabaseOperationReceiver::SerializeSetBehavior(
+             SetBehavior::kDefault)}},
+       {Type::DB_GET, kOrigin1, {u"key1"}},
+       {Type::DB_SET,
+        kOrigin1,
+        {u"key1", u"value2",
+         TestDatabaseOperationReceiver::SerializeSetBehavior(
+             SetBehavior::kDefault)}},
+       {Type::DB_GET, kOrigin1, {u"key1"}},
+       {Type::DB_SET,
+        kOrigin1,
+        {u"key2", u"value1",
+         TestDatabaseOperationReceiver::SerializeSetBehavior(
+             SetBehavior::kDefault)}},
+       {Type::DB_GET, kOrigin1, {u"key2"}},
+       {Type::DB_LENGTH, kOrigin1},
+       {Type::DB_DELETE, kOrigin1, {u"key1"}},
+       {Type::DB_LENGTH, kOrigin1},
+       {Type::DB_APPEND, kOrigin1, {u"key1", u"value1"}},
+       {Type::DB_GET, kOrigin1, {u"key1"}},
+       {Type::DB_LENGTH, kOrigin1},
+       {Type::DB_APPEND, kOrigin1, {u"key1", u"value1"}},
+       {Type::DB_GET, kOrigin1, {u"key1"}},
+       {Type::DB_LENGTH, kOrigin1},
+       {Type::DB_KEY, kOrigin1, {base::NumberToString16(0)}},
+       {Type::DB_KEY, kOrigin1, {base::NumberToString16(1)}},
+       {Type::DB_CLEAR, kOrigin1},
+       {Type::DB_LENGTH, kOrigin1}});
+
+  SetExpectedOperationList(std::move(operation_list));
+
+  OperationResult result1 = OperationResult::kSqlError;
+  Set(kOrigin1, u"key1", u"value1", &result1);
+  GetResult value1;
+  Get(kOrigin1, u"key1", &value1);
+  OperationResult result2 = OperationResult::kSqlError;
+  Set(kOrigin1, u"key1", u"value2", &result2);
+  GetResult value2;
+  Get(kOrigin1, u"key1", &value2);
+  OperationResult result3 = OperationResult::kSqlError;
+  Set(kOrigin1, u"key2", u"value1", &result3);
+  GetResult value3;
+  Get(kOrigin1, u"key2", &value3);
+  int length1 = -1;
+  Length(kOrigin1, &length1);
+
+  OperationResult result4 = OperationResult::kSqlError;
+  Delete(kOrigin1, u"key1", &result4);
+  int length2 = -1;
+  Length(kOrigin1, &length2);
+
+  OperationResult result5 = OperationResult::kSqlError;
+  Append(kOrigin1, u"key1", u"value1", &result5);
+  GetResult value4;
+  Get(kOrigin1, u"key1", &value4);
+  int length3 = -1;
+  Length(kOrigin1, &length3);
+
+  OperationResult result6 = OperationResult::kSqlError;
+  Append(kOrigin1, u"key1", u"value1", &result6);
+  GetResult value5;
+  Get(kOrigin1, u"key1", &value5);
+  int length4 = -1;
+  Length(kOrigin1, &length4);
+
+  GetResult key1;
+  Key(kOrigin1, 0, &key1);
+  GetResult key2;
+  Key(kOrigin1, 1, &key2);
+
+  OperationResult result7 = OperationResult::kSqlError;
+  Clear(kOrigin1, &result7);
+  int length5 = -1;
+  Length(kOrigin1, &length5);
+
+  WaitForOperations();
+  EXPECT_TRUE(is_finished());
+
+  EXPECT_EQ(OperationResult::kSet, result1);
+  EXPECT_EQ(value1.data, u"value1");
+  EXPECT_EQ(OperationResult::kSet, result2);
+  EXPECT_EQ(value2.data, u"value2");
+  EXPECT_EQ(OperationResult::kSet, result3);
+  EXPECT_EQ(value3.data, u"value1");
+  EXPECT_EQ(2, length1);
+
+  EXPECT_EQ(OperationResult::kSuccess, result4);
+  EXPECT_EQ(1, length2);
+
+  EXPECT_EQ(OperationResult::kSet, result5);
+  EXPECT_EQ(value4.data, u"value1");
+  EXPECT_EQ(2, length3);
+
+  EXPECT_EQ(OperationResult::kSet, result6);
+  EXPECT_EQ(value5.data, u"value1value1");
+  EXPECT_EQ(2, length4);
+
+  EXPECT_EQ(key1.data, u"key1");
+  EXPECT_EQ(key2.data, u"key2");
+
+  EXPECT_EQ(OperationResult::kSuccess, result7);
+  EXPECT_EQ(0, length5);
+}
+
+TEST_P(AsyncSharedStorageDatabaseParamTest,
+       LazyInit_IgnoreForGet_CreateForSet) {
+  url::Origin kOrigin1 = url::Origin::Create(GURL("http://www.example1.test"));
+
+  std::queue<DBOperation> operation_list;
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin1, {u"key1"}));
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin1,
+                  {u"key1", u"value1",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin1, {u"key1"}));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin1));
+
+  SetExpectedOperationList(std::move(operation_list));
+
+  bool open1 = false;
+  IsOpen(&open1);
+  InitStatus status1 = InitStatus::kUnattempted;
+  DBStatus(&status1);
+
+  // Test that we can successfully call `Get()` on a nonexistent key before the
+  // database is initialized.
+  GetResult value1;
+  Get(kOrigin1, u"key1", &value1);
+  bool open2 = false;
+  IsOpen(&open2);
+  InitStatus status2 = InitStatus::kUnattempted;
+  DBStatus(&status2);
+
+  // Call an operation that initializes the database.
+  OperationResult result1 = OperationResult::kSqlError;
+  Set(kOrigin1, u"key1", u"value1", &result1);
+  bool open3 = false;
+  IsOpen(&open3);
+  InitStatus status3 = InitStatus::kUnattempted;
+  DBStatus(&status3);
+
+  GetResult value2;
+  Get(kOrigin1, u"key1", &value2);
+  int length1 = -1;
+  Length(kOrigin1, &length1);
+
+  WaitForOperations();
+  EXPECT_TRUE(is_finished());
+
+  EXPECT_FALSE(open1);
+  EXPECT_EQ(InitStatus::kUnattempted, status1);
+
+  EXPECT_FALSE(value1.data);
+  EXPECT_EQ(OperationResult::kSuccess, value1.result);
+  EXPECT_EQ(!GetParam().in_memory_only, open2);
+  EXPECT_EQ(InitStatus::kUnattempted, status2);
+
+  EXPECT_EQ(OperationResult::kSet, result1);
+  EXPECT_TRUE(open3);
+  EXPECT_EQ(InitStatus::kSuccess, status3);
+
+  EXPECT_EQ(value2.data, u"value1");
+  EXPECT_EQ(OperationResult::kSuccess, value2.result);
+  EXPECT_EQ(1, length1);
+}
+
+TEST_P(AsyncSharedStorageDatabaseParamTest,
+       LazyInit_IgnoreForDelete_CreateForAppend) {
+  url::Origin kOrigin1 = url::Origin::Create(GURL("http://www.example1.test"));
+
+  std::queue<DBOperation> operation_list;
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+  operation_list.push(DBOperation(Type::DB_DELETE, kOrigin1, {u"key1"}));
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+  operation_list.push(
+      DBOperation(Type::DB_APPEND, kOrigin1, {u"key1", u"value1"}));
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+  operation_list.push(DBOperation(Type::DB_DELETE, kOrigin1, {u"key2"}));
+
+  SetExpectedOperationList(std::move(operation_list));
+
+  bool open1 = false;
+  IsOpen(&open1);
+  InitStatus status1 = InitStatus::kUnattempted;
+  DBStatus(&status1);
+
+  // Test that we can successfully call `Delete()` on a nonexistent key before
+  // the database is initialized.
+  OperationResult result1 = OperationResult::kSqlError;
+  Delete(kOrigin1, u"key1", &result1);
+  bool open2 = false;
+  IsOpen(&open2);
+  InitStatus status2 = InitStatus::kUnattempted;
+  DBStatus(&status2);
+
+  // Call an operation that initializes the database.
+  OperationResult result2 = OperationResult::kSqlError;
+  Append(kOrigin1, u"key1", u"value1", &result2);
+  bool open3 = false;
+  IsOpen(&open3);
+  InitStatus status3 = InitStatus::kUnattempted;
+  DBStatus(&status3);
+
+  // Test that we can successfully call `Delete()` on a nonexistent key after
+  // the database is initialized.
+  OperationResult result3 = OperationResult::kSqlError;
+  Delete(kOrigin1, u"key2", &result3);
+
+  WaitForOperations();
+  EXPECT_TRUE(is_finished());
+
+  EXPECT_FALSE(open1);
+  EXPECT_EQ(InitStatus::kUnattempted, status1);
+
+  EXPECT_EQ(OperationResult::kSuccess, result1);
+  EXPECT_EQ(!GetParam().in_memory_only, open2);
+  EXPECT_EQ(InitStatus::kUnattempted, status2);
+
+  EXPECT_EQ(OperationResult::kSet, result2);
+  EXPECT_TRUE(open3);
+  EXPECT_EQ(InitStatus::kSuccess, status3);
+
+  EXPECT_EQ(OperationResult::kSuccess, result3);
+}
+
+TEST_P(AsyncSharedStorageDatabaseParamTest,
+       LazyInit_IgnoreForClear_CreateForAppend) {
+  url::Origin kOrigin1 = url::Origin::Create(GURL("http://www.example1.test"));
+  url::Origin kOrigin2 = url::Origin::Create(GURL("http://www.example2.test"));
+
+  std::queue<DBOperation> operation_list;
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+  operation_list.push(DBOperation(Type::DB_CLEAR, kOrigin1));
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+  operation_list.push(
+      DBOperation(Type::DB_APPEND, kOrigin1, {u"key1", u"value1"}));
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+  operation_list.push(DBOperation(Type::DB_CLEAR, kOrigin2));
+
+  SetExpectedOperationList(std::move(operation_list));
+
+  bool open1 = false;
+  IsOpen(&open1);
+  InitStatus status1 = InitStatus::kUnattempted;
+  DBStatus(&status1);
+
+  // Test that we can successfully call `Clear()` on a nonexistent origin before
+  // the database is initialized.
+  OperationResult result1 = OperationResult::kSqlError;
+  Clear(kOrigin1, &result1);
+  bool open2 = false;
+  IsOpen(&open2);
+  InitStatus status2 = InitStatus::kUnattempted;
+  DBStatus(&status2);
+
+  // Call an operation that initializes the database.
+  OperationResult result2 = OperationResult::kSqlError;
+  Append(kOrigin1, u"key1", u"value1", &result2);
+  bool open3 = false;
+  IsOpen(&open3);
+  InitStatus status3 = InitStatus::kUnattempted;
+  DBStatus(&status3);
+
+  // Test that we can successfully call `Clear()` on a nonexistent origin after
+  // the database is initialized.
+  OperationResult result3 = OperationResult::kSqlError;
+  Clear(kOrigin2, &result3);
+
+  WaitForOperations();
+  EXPECT_TRUE(is_finished());
+
+  EXPECT_FALSE(open1);
+  EXPECT_EQ(InitStatus::kUnattempted, status1);
+
+  EXPECT_EQ(OperationResult::kSuccess, result1);
+  EXPECT_EQ(!GetParam().in_memory_only, open2);
+  EXPECT_EQ(InitStatus::kUnattempted, status2);
+
+  EXPECT_EQ(OperationResult::kSet, result2);
+  EXPECT_TRUE(open3);
+  EXPECT_EQ(InitStatus::kSuccess, status3);
+
+  EXPECT_EQ(OperationResult::kSuccess, result3);
+}
+
+TEST_P(AsyncSharedStorageDatabaseParamTest, PurgeStaleOrigins) {
+  url::Origin kOrigin1 = url::Origin::Create(GURL("http://www.example1.test"));
+  url::Origin kOrigin2 = url::Origin::Create(GURL("http://www.example2.test"));
+  url::Origin kOrigin3 = url::Origin::Create(GURL("http://www.example3.test"));
+  url::Origin kOrigin4 = url::Origin::Create(GURL("http://www.example4.test"));
+
+  std::queue<DBOperation> operation_list;
+  operation_list.push(DBOperation(Type::DB_FETCH_ORIGINS));
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+
+  operation_list.push(DBOperation(
+      Type::DB_PURGE_STALE,
+      {TestDatabaseOperationReceiver::SerializeTimeDelta(base::Days(1))}));
+
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin1,
+                  {u"key1", u"value1",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin1,
+                  {u"key2", u"value2",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin1));
+
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin2,
+                  {u"key1", u"value1",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin2));
+
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin3,
+                  {u"key1", u"value1",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin3,
+                  {u"key2", u"value2",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin3,
+                  {u"key3", u"value3",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin3));
+
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin4,
+                  {u"key1", u"value1",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin4,
+                  {u"key2", u"value2",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin4,
+                  {u"key3", u"value3",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin4,
+                  {u"key4", u"value4",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin4));
+
+  operation_list.push(DBOperation(Type::DB_FETCH_ORIGINS));
+
+  base::Time override_time1 = base::Time::Now() - base::Days(2);
+  operation_list.push(DBOperation(
+      Type::DB_OVERRIDE_TIME, kOrigin1,
+      {TestDatabaseOperationReceiver::SerializeTime(override_time1)}));
+  operation_list.push(DBOperation(
+      Type::DB_PURGE_STALE,
+      {TestDatabaseOperationReceiver::SerializeTimeDelta(base::Days(1))}));
+
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin1));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin2));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin3));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin4));
+  operation_list.push(DBOperation(Type::DB_FETCH_ORIGINS));
+
+  base::Time override_time2 = base::Time::Now() - base::Hours(2);
+  operation_list.push(DBOperation(
+      Type::DB_OVERRIDE_TIME, kOrigin3,
+      {TestDatabaseOperationReceiver::SerializeTime(override_time2)}));
+  operation_list.push(DBOperation(
+      Type::DB_PURGE_STALE,
+      {TestDatabaseOperationReceiver::SerializeTimeDelta(base::Hours(1))}));
+
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin1));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin2));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin3));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin4));
+
+  operation_list.push(DBOperation(Type::DB_TRIM_MEMORY));
+  operation_list.push(DBOperation(Type::DB_FETCH_ORIGINS));
+
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin2, {u"key1"}));
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin4, {u"key1"}));
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin4, {u"key2"}));
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin4, {u"key3"}));
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin4, {u"key4"}));
+
+  SetExpectedOperationList(std::move(operation_list));
+
+  // Check that origin list is initially empty due to the database not being
+  // initialized.
+  std::vector<mojom::StorageUsageInfoPtr> infos1;
+  FetchOrigins(&infos1);
+
+  // Check that calling `PurgeStaleOrigins()` on the uninitialized database
+  // doesn't give an error.
+  bool open1 = false;
+  IsOpen(&open1);
+  InitStatus status1 = InitStatus::kUnattempted;
+  DBStatus(&status1);
+
+  OperationResult result1 = OperationResult::kSqlError;
+  PurgeStaleOrigins(base::Days(1), &result1);
+
+  OperationResult result2 = OperationResult::kSqlError;
+  Set(kOrigin1, u"key1", u"value1", &result2);
+
+  bool open2 = false;
+  IsOpen(&open2);
+  InitStatus status2 = InitStatus::kUnattempted;
+  DBStatus(&status2);
+
+  OperationResult result3 = OperationResult::kSqlError;
+  Set(kOrigin1, u"key2", u"value2", &result3);
+  int length1 = -1;
+  Length(kOrigin1, &length1);
+
+  OperationResult result4 = OperationResult::kSqlError;
+  Set(kOrigin2, u"key1", u"value1", &result4);
+  int length2 = -1;
+  Length(kOrigin2, &length2);
+
+  OperationResult result5 = OperationResult::kSqlError;
+  Set(kOrigin3, u"key1", u"value1", &result5);
+  OperationResult result6 = OperationResult::kSqlError;
+  Set(kOrigin3, u"key2", u"value2", &result6);
+  OperationResult result7 = OperationResult::kSqlError;
+  Set(kOrigin3, u"key3", u"value3", &result7);
+  int length3 = -1;
+  Length(kOrigin3, &length3);
+
+  OperationResult result8 = OperationResult::kSqlError;
+  Set(kOrigin4, u"key1", u"value1", &result8);
+  OperationResult result9 = OperationResult::kSqlError;
+  Set(kOrigin4, u"key2", u"value2", &result9);
+  OperationResult result10 = OperationResult::kSqlError;
+  Set(kOrigin4, u"key3", u"value3", &result10);
+  OperationResult result11 = OperationResult::kSqlError;
+  Set(kOrigin4, u"key4", u"value4", &result11);
+  int length4 = -1;
+  Length(kOrigin4, &length4);
+
+  std::vector<mojom::StorageUsageInfoPtr> infos2;
+  FetchOrigins(&infos2);
+
+  bool success1 = false;
+  OverrideLastUsedTime(kOrigin1, override_time1, &success1);
+
+  OperationResult result12 = OperationResult::kSqlError;
+  PurgeStaleOrigins(base::Days(1), &result12);
+
+  int length5 = -1;
+  Length(kOrigin1, &length5);
+  int length6 = -1;
+  Length(kOrigin2, &length6);
+  int length7 = -1;
+  Length(kOrigin3, &length7);
+  int length8 = -1;
+  Length(kOrigin4, &length8);
+
+  std::vector<mojom::StorageUsageInfoPtr> infos3;
+  FetchOrigins(&infos3);
+
+  bool success2 = false;
+  OverrideLastUsedTime(kOrigin3, override_time2, &success2);
+
+  OperationResult result13 = OperationResult::kSqlError;
+  PurgeStaleOrigins(base::Hours(1), &result13);
+
+  int length9 = -1;
+  Length(kOrigin1, &length9);
+  int length10 = -1;
+  Length(kOrigin2, &length10);
+  int length11 = -1;
+  Length(kOrigin3, &length11);
+  int length12 = -1;
+  Length(kOrigin4, &length12);
+
+  TrimMemory();
+
+  std::vector<mojom::StorageUsageInfoPtr> infos4;
+  FetchOrigins(&infos4);
+
+  GetResult value1;
+  Get(kOrigin2, u"key1", &value1);
+  GetResult value2;
+  Get(kOrigin4, u"key1", &value2);
+  GetResult value3;
+  Get(kOrigin4, u"key2", &value3);
+  GetResult value4;
+  Get(kOrigin4, u"key3", &value4);
+  GetResult value5;
+  Get(kOrigin4, u"key4", &value5);
+
+  WaitForOperations();
+  EXPECT_TRUE(is_finished());
+
+  // Database is not yet initialized. `FetchOrigins()` returns an empty vector.
+  EXPECT_TRUE(infos1.empty());
+  EXPECT_EQ(!GetParam().in_memory_only, open1);
+  EXPECT_EQ(InitStatus::kUnattempted, status1);
+
+  // No error from calling `PurgeStaleOrigins()` on an uninitialized
+  // database.
+  EXPECT_EQ(OperationResult::kSuccess, result1);
+
+  // The call to `Set()` initializes the database.
+  EXPECT_EQ(OperationResult::kSet, result2);
+  EXPECT_TRUE(open2);
+  EXPECT_EQ(InitStatus::kSuccess, status2);
+
+  EXPECT_EQ(OperationResult::kSet, result3);
+  EXPECT_EQ(2, length1);
+
+  EXPECT_EQ(OperationResult::kSet, result4);
+  EXPECT_EQ(1, length2);
+
+  EXPECT_EQ(OperationResult::kSet, result5);
+  EXPECT_EQ(OperationResult::kSet, result6);
+  EXPECT_EQ(OperationResult::kSet, result7);
+  EXPECT_EQ(3, length3);
+
+  EXPECT_EQ(OperationResult::kSet, result8);
+  EXPECT_EQ(OperationResult::kSet, result9);
+  EXPECT_EQ(OperationResult::kSet, result10);
+  EXPECT_EQ(OperationResult::kSet, result11);
+  EXPECT_EQ(4, length4);
+
+  std::vector<url::Origin> origins;
+  for (const auto& info : infos2)
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin2, kOrigin3, kOrigin4));
+
+  EXPECT_TRUE(success1);
+  EXPECT_EQ(OperationResult::kSuccess, result12);
+
+  // `kOrigin1` is cleared. The other origins are not.
+  EXPECT_EQ(0, length5);
+  EXPECT_EQ(1, length6);
+  EXPECT_EQ(3, length7);
+  EXPECT_EQ(4, length8);
+
+  origins.clear();
+  for (const auto& info : infos3)
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin2, kOrigin3, kOrigin4));
+
+  EXPECT_TRUE(success2);
+  EXPECT_EQ(OperationResult::kSuccess, result13);
+
+  // `kOrigin3` is cleared. The other remaining ones are not.
+  EXPECT_EQ(0, length9);
+  EXPECT_EQ(1, length10);
+  EXPECT_EQ(0, length11);
+  EXPECT_EQ(4, length12);
+
+  origins.clear();
+  for (const auto& info : infos4)
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin2, kOrigin4));
+
+  // Database is still intact after trimming memory.
+  EXPECT_EQ(value1.data, u"value1");
+  EXPECT_EQ(OperationResult::kSuccess, value1.result);
+  EXPECT_EQ(value2.data, u"value1");
+  EXPECT_EQ(OperationResult::kSuccess, value2.result);
+  EXPECT_EQ(value3.data, u"value2");
+  EXPECT_EQ(OperationResult::kSuccess, value3.result);
+  EXPECT_EQ(value4.data, u"value3");
+  EXPECT_EQ(OperationResult::kSuccess, value4.result);
+  EXPECT_EQ(value5.data, u"value4");
+  EXPECT_EQ(OperationResult::kSuccess, value5.result);
+}
+
+class AsyncSharedStorageDatabasePurgeMatchingOriginsParamTest
+    : public AsyncSharedStorageDatabaseTest,
+      public testing::WithParamInterface<PurgeMatchingOriginsParams> {
+ public:
+  void SetUp() override {
+    AsyncSharedStorageDatabaseTest::SetUp();
+
+    auto options = SharedStorageOptions::Create()->GetDatabaseOptions();
+
+    if (GetParam().in_memory_only)
+      CreateSync(base::FilePath(), std::move(options));
+    else
+      CreateSync(file_name_, std::move(options));
+  }
+
+  void InitSharedStorageFeature() override {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        {blink::features::kSharedStorageAPI},
+        {{"MaxSharedStorageEntriesPerOrigin",
+          base::NumberToString(kMaxEntriesPerOrigin)},
+         {"MaxSharedStorageStringLength",
+          base::NumberToString(kMaxStringLength)}});
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    AsyncSharedStorageDatabasePurgeMatchingOriginsParamTest,
+    testing::ValuesIn(GetPurgeMatchingOriginsParams()),
+    testing::PrintToStringParamName());
+
+TEST_P(AsyncSharedStorageDatabasePurgeMatchingOriginsParamTest,
+       SinceThreshold) {
+  url::Origin kOrigin1 = url::Origin::Create(GURL("http://www.example1.test"));
+  url::Origin kOrigin2 = url::Origin::Create(GURL("http://www.example2.test"));
+  url::Origin kOrigin3 = url::Origin::Create(GURL("http://www.example3.test"));
+  url::Origin kOrigin4 = url::Origin::Create(GURL("http://www.example4.test"));
+  url::Origin kOrigin5 = url::Origin::Create(GURL("http://www.example5.test"));
+
+  std::queue<DBOperation> operation_list;
+  operation_list.push(DBOperation(Type::DB_FETCH_ORIGINS));
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+
+  base::Time threshold1 = base::Time::Now();
+  OriginMatcherFunctionUtility matcher_utility;
+  size_t matcher_id1 = matcher_utility.RegisterMatcherFunction({kOrigin1});
+
+  operation_list.push(DBOperation(
+      Type::DB_PURGE_MATCHING,
+      {base::NumberToString16(matcher_id1),
+       TestDatabaseOperationReceiver::SerializeTime(threshold1),
+       TestDatabaseOperationReceiver::SerializeTime(base::Time::Max()),
+       TestDatabaseOperationReceiver::SerializeBool(
+           GetParam().perform_storage_cleanup)}));
+
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin1,
+                  {u"key1", u"value1",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_IS_OPEN));
+  operation_list.push(DBOperation(Type::DB_STATUS));
+
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin1,
+                  {u"key2", u"value2",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin1));
+
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin2,
+                  {u"key1", u"value1",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin2));
+
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin3,
+                  {u"key1", u"value1",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin3,
+                  {u"key2", u"value2",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin3,
+                  {u"key3", u"value3",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin3));
+
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin4,
+                  {u"key1", u"value1",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin4,
+                  {u"key2", u"value2",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin4,
+                  {u"key3", u"value3",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin4,
+                  {u"key4", u"value4",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin4));
+
+  operation_list.push(
+      DBOperation(Type::DB_SET, kOrigin5,
+                  {u"key1", u"value1",
+                   TestDatabaseOperationReceiver::SerializeSetBehavior(
+                       SetBehavior::kDefault)}));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin5));
+
+  operation_list.push(DBOperation(Type::DB_FETCH_ORIGINS));
+
+  base::Time threshold2 = base::Time::Now() + base::Seconds(100);
+  base::Time override_time1 = threshold2 + base::Milliseconds(5);
+  operation_list.push(DBOperation(
+      Type::DB_OVERRIDE_TIME, kOrigin1,
+      {TestDatabaseOperationReceiver::SerializeTime(override_time1)}));
+
+  size_t matcher_id2 =
+      matcher_utility.RegisterMatcherFunction({kOrigin1, kOrigin2, kOrigin5});
+  operation_list.push(DBOperation(
+      Type::DB_PURGE_MATCHING,
+      {base::NumberToString16(matcher_id2),
+       TestDatabaseOperationReceiver::SerializeTime(threshold2),
+       TestDatabaseOperationReceiver::SerializeTime(base::Time::Max()),
+       TestDatabaseOperationReceiver::SerializeBool(
+           GetParam().perform_storage_cleanup)}));
+
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin1));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin2));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin3));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin4));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin5));
+
+  operation_list.push(DBOperation(Type::DB_FETCH_ORIGINS));
+
+  base::Time threshold3 = base::Time::Now() + base::Seconds(200);
+  operation_list.push(
+      DBOperation(Type::DB_OVERRIDE_TIME, kOrigin3,
+                  {TestDatabaseOperationReceiver::SerializeTime(threshold3)}));
+
+  base::Time threshold4 = threshold3 + base::Seconds(100);
+  operation_list.push(
+      DBOperation(Type::DB_OVERRIDE_TIME, kOrigin5,
+                  {TestDatabaseOperationReceiver::SerializeTime(threshold4)}));
+
+  size_t matcher_id3 = matcher_utility.RegisterMatcherFunction(
+      {kOrigin2, kOrigin3, kOrigin4, kOrigin5});
+  operation_list.push(
+      DBOperation(Type::DB_PURGE_MATCHING,
+                  {base::NumberToString16(matcher_id3),
+                   TestDatabaseOperationReceiver::SerializeTime(threshold3),
+                   TestDatabaseOperationReceiver::SerializeTime(threshold4),
+                   TestDatabaseOperationReceiver::SerializeBool(
+                       GetParam().perform_storage_cleanup)}));
+
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin1));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin2));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin3));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin4));
+  operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin5));
+
+  operation_list.push(DBOperation(Type::DB_TRIM_MEMORY));
+
+  operation_list.push(DBOperation(Type::DB_FETCH_ORIGINS));
+
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin2, {u"key1"}));
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin4, {u"key1"}));
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin4, {u"key2"}));
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin4, {u"key3"}));
+  operation_list.push(DBOperation(Type::DB_GET, kOrigin4, {u"key4"}));
+
+  operation_list.push(DBOperation(Type::DB_DESTROY));
+
+  SetExpectedOperationList(std::move(operation_list));
+
+  // Check that origin list is initially empty due to the database not being
+  // initialized.
+  std::vector<mojom::StorageUsageInfoPtr> infos1;
+  FetchOrigins(&infos1);
+
+  // Check that calling `PurgeMatchingOrigins()` on the uninitialized database
+  // doesn't give an error.
+  bool open1 = false;
+  IsOpen(&open1);
+  InitStatus status1 = InitStatus::kUnattempted;
+  DBStatus(&status1);
+
+  OperationResult result1 = OperationResult::kSqlError;
+  PurgeMatchingOrigins(&matcher_utility, matcher_id1, threshold1,
+                       base::Time::Max(), &result1,
+                       GetParam().perform_storage_cleanup);
+
+  OperationResult result2 = OperationResult::kSqlError;
+  Set(kOrigin1, u"key1", u"value1", &result2);
+
+  bool open2 = false;
+  IsOpen(&open2);
+  InitStatus status2 = InitStatus::kUnattempted;
+  DBStatus(&status2);
+
+  OperationResult result3 = OperationResult::kSqlError;
+  Set(kOrigin1, u"key2", u"value2", &result3);
+  int length1 = -1;
+  Length(kOrigin1, &length1);
+
+  OperationResult result4 = OperationResult::kSqlError;
+  Set(kOrigin2, u"key1", u"value1", &result4);
+  int length2 = -1;
+  Length(kOrigin2, &length2);
+
+  OperationResult result5 = OperationResult::kSqlError;
+  Set(kOrigin3, u"key1", u"value1", &result5);
+  OperationResult result6 = OperationResult::kSqlError;
+  Set(kOrigin3, u"key2", u"value2", &result6);
+  OperationResult result7 = OperationResult::kSqlError;
+  Set(kOrigin3, u"key3", u"value3", &result7);
+  int length3 = -1;
+  Length(kOrigin3, &length3);
+
+  OperationResult result8 = OperationResult::kSqlError;
+  Set(kOrigin4, u"key1", u"value1", &result8);
+  OperationResult result9 = OperationResult::kSqlError;
+  Set(kOrigin4, u"key2", u"value2", &result9);
+  OperationResult result10 = OperationResult::kSqlError;
+  Set(kOrigin4, u"key3", u"value3", &result10);
+  OperationResult result11 = OperationResult::kSqlError;
+  Set(kOrigin4, u"key4", u"value4", &result11);
+  int length4 = -1;
+  Length(kOrigin4, &length4);
+
+  OperationResult result12 = OperationResult::kSqlError;
+  Set(kOrigin5, u"key1", u"value1", &result12);
+  int length5 = -1;
+  Length(kOrigin5, &length5);
+
+  std::vector<mojom::StorageUsageInfoPtr> infos2;
+  FetchOrigins(&infos2);
+
+  bool success1 = false;
+  OverrideLastUsedTime(kOrigin1, override_time1, &success1);
+
+  // Verify that the only match we get is for `kOrigin1`, whose `last_used_time`
+  // is between the time parameters.
+  OperationResult result13 = OperationResult::kSqlError;
+  PurgeMatchingOrigins(&matcher_utility, matcher_id2, threshold2,
+                       base::Time::Max(), &result13,
+                       GetParam().perform_storage_cleanup);
+
+  int length6 = -1;
+  Length(kOrigin1, &length6);
+  int length7 = -1;
+  Length(kOrigin2, &length7);
+  int length8 = -1;
+  Length(kOrigin3, &length8);
+  int length9 = -1;
+  Length(kOrigin4, &length9);
+  int length10 = -1;
+  Length(kOrigin5, &length10);
+
+  std::vector<mojom::StorageUsageInfoPtr> infos3;
+  FetchOrigins(&infos3);
+
+  bool success2 = false;
+  OverrideLastUsedTime(kOrigin3, threshold3, &success2);
+  bool success3 = false;
+  OverrideLastUsedTime(kOrigin5, threshold4, &success3);
+
+  // Verify that we still get matches for `kOrigin3`, whose `last_used_time` is
+  // exactly at the `begin` time, as well as for `kOrigin5`, whose
+  // `last_used_time` is exactly at the `end` time.
+  OperationResult result14 = OperationResult::kSqlError;
+  PurgeMatchingOrigins(&matcher_utility, matcher_id3, threshold3, threshold4,
+                       &result14, GetParam().perform_storage_cleanup);
+
+  int length11 = -1;
+  Length(kOrigin1, &length11);
+  int length12 = -1;
+  Length(kOrigin2, &length12);
+  int length13 = -1;
+  Length(kOrigin3, &length13);
+  int length14 = -1;
+  Length(kOrigin4, &length14);
+  int length15 = -1;
+  Length(kOrigin5, &length15);
+
+  TrimMemory();
+
+  std::vector<mojom::StorageUsageInfoPtr> infos4;
+  FetchOrigins(&infos4);
+
+  GetResult value1;
+  Get(kOrigin2, u"key1", &value1);
+  GetResult value2;
+  Get(kOrigin4, u"key1", &value2);
+  GetResult value3;
+  Get(kOrigin4, u"key2", &value3);
+  GetResult value4;
+  Get(kOrigin4, u"key3", &value4);
+  GetResult value5;
+  Get(kOrigin4, u"key4", &value5);
+
+  bool success4 = false;
+  Destroy(&success4);
+
+  WaitForOperations();
+  EXPECT_TRUE(is_finished());
+
+  // Database is not yet initialized. `FetchOrigins()` returns an empty vector.
+  EXPECT_TRUE(infos1.empty());
+  EXPECT_EQ(!GetParam().in_memory_only, open1);
+  EXPECT_EQ(InitStatus::kUnattempted, status1);
+
+  // No error from calling `PurgeMatchingOrigins()` on an uninitialized
+  // database.
+  EXPECT_EQ(OperationResult::kSuccess, result1);
+
+  // The call to `Set()` initializes the database.
+  EXPECT_EQ(OperationResult::kSet, result2);
+  EXPECT_TRUE(open2);
+  EXPECT_EQ(InitStatus::kSuccess, status2);
+
+  EXPECT_EQ(OperationResult::kSet, result3);
+  EXPECT_EQ(2, length1);
+
+  EXPECT_EQ(OperationResult::kSet, result4);
+  EXPECT_EQ(1, length2);
+
+  EXPECT_EQ(OperationResult::kSet, result5);
+  EXPECT_EQ(OperationResult::kSet, result6);
+  EXPECT_EQ(OperationResult::kSet, result7);
+  EXPECT_EQ(3, length3);
+
+  EXPECT_EQ(OperationResult::kSet, result8);
+  EXPECT_EQ(OperationResult::kSet, result9);
+  EXPECT_EQ(OperationResult::kSet, result10);
+  EXPECT_EQ(OperationResult::kSet, result11);
+  EXPECT_EQ(4, length4);
+
+  EXPECT_EQ(OperationResult::kSet, result12);
+  EXPECT_EQ(1, length5);
+
+  std::vector<url::Origin> origins;
+  for (const auto& info : infos2)
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins,
+              ElementsAre(kOrigin1, kOrigin2, kOrigin3, kOrigin4, kOrigin5));
+
+  EXPECT_TRUE(success1);
+  EXPECT_EQ(OperationResult::kSuccess, result13);
+
+  // `kOrigin1` is cleared. The other origins are not.
+  EXPECT_EQ(0, length6);
+  EXPECT_EQ(1, length7);
+  EXPECT_EQ(3, length8);
+  EXPECT_EQ(4, length9);
+  EXPECT_EQ(1, length10);
+
+  origins.clear();
+  for (const auto& info : infos3)
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin2, kOrigin3, kOrigin4, kOrigin5));
+
+  EXPECT_TRUE(success2);
+  EXPECT_TRUE(success3);
+
+  EXPECT_EQ(OperationResult::kSuccess, result14);
+
+  // `kOrigin3` and `kOrigin5` are  cleared. The others weren't modified within
+  // the given time period.
+  EXPECT_EQ(0, length11);
+  EXPECT_EQ(1, length12);
+  EXPECT_EQ(0, length13);
+  EXPECT_EQ(4, length14);
+  EXPECT_EQ(0, length15);
+
+  origins.clear();
+  for (const auto& info : infos4)
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin2, kOrigin4));
+
+  // Database is still intact after trimming memory (and possibly performing
+  // storage cleanup).
+  EXPECT_EQ(value1.data, u"value1");
+  EXPECT_EQ(OperationResult::kSuccess, value1.result);
+  EXPECT_EQ(value2.data, u"value1");
+  EXPECT_EQ(OperationResult::kSuccess, value2.result);
+  EXPECT_EQ(value3.data, u"value2");
+  EXPECT_EQ(OperationResult::kSuccess, value3.result);
+  EXPECT_EQ(value4.data, u"value3");
+  EXPECT_EQ(OperationResult::kSuccess, value4.result);
+  EXPECT_EQ(value5.data, u"value4");
+  EXPECT_EQ(OperationResult::kSuccess, value5.result);
+
+  EXPECT_TRUE(success4);
+}
+
+}  // namespace storage
diff --git a/components/services/storage/shared_storage/shared_storage_database.cc b/components/services/storage/shared_storage/shared_storage_database.cc
new file mode 100644
index 0000000..923717a5
--- /dev/null
+++ b/components/services/storage/shared_storage/shared_storage_database.cc
@@ -0,0 +1,900 @@
+// Copyright 2021 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/services/storage/shared_storage/shared_storage_database.h"
+
+#include <inttypes.h>
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/files/file_util.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/time/default_clock.h"
+#include "base/time/time.h"
+#include "components/services/storage/public/mojom/storage_usage_info.mojom.h"
+#include "components/services/storage/shared_storage/shared_storage_options.h"
+#include "sql/error_delegate_util.h"
+#include "sql/statement.h"
+#include "sql/transaction.h"
+#include "storage/browser/quota/special_storage_policy.h"
+#include "third_party/blink/public/common/features.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace storage {
+
+// Because each entry is a key-value pair, and both keys and values are
+// std::u16strings and bounded by `max_string_length_`, the total bytes used per
+// entry is at most 2 * 2 * `max_string_length_`.
+const int kSharedStorageEntryTotalBytesMultiplier = 4;
+
+namespace {
+
+// Version number of the database.
+const int kCurrentVersionNumber = 1;
+
+[[nodiscard]] std::string SerializeOrigin(const url::Origin& origin) {
+  DCHECK(!origin.opaque());
+  DCHECK_NE(url::kFileScheme, origin.scheme());
+  return origin.Serialize();
+}
+
+[[nodiscard]] bool InitSchema(sql::Database& db) {
+  static constexpr char kValuesMappingSql[] =
+      "CREATE TABLE IF NOT EXISTS values_mapping("
+      "context_origin TEXT NOT NULL,"
+      "key TEXT NOT NULL,"
+      "value TEXT,"
+      "PRIMARY KEY(context_origin,key)) WITHOUT ROWID";
+  if (!db.Execute(kValuesMappingSql))
+    return false;
+
+  static constexpr char kPerOriginMappingSql[] =
+      "CREATE TABLE IF NOT EXISTS per_origin_mapping("
+      "context_origin TEXT NOT NULL PRIMARY KEY,"
+      "last_used_time INTEGER NOT NULL,"
+      "length INTEGER NOT NULL) WITHOUT ROWID";
+  if (!db.Execute(kPerOriginMappingSql))
+    return false;
+
+  static constexpr char kLastUsedTimeIndexSql[] =
+      "CREATE INDEX IF NOT EXISTS per_origin_mapping_last_used_time_idx "
+      "ON per_origin_mapping(last_used_time)";
+  if (!db.Execute(kLastUsedTimeIndexSql))
+    return false;
+
+  return true;
+}
+
+}  // namespace
+
+SharedStorageDatabase::GetResult::GetResult() = default;
+
+SharedStorageDatabase::GetResult::GetResult(const GetResult&) = default;
+
+SharedStorageDatabase::GetResult::GetResult(GetResult&&) = default;
+
+SharedStorageDatabase::GetResult::~GetResult() = default;
+
+SharedStorageDatabase::GetResult& SharedStorageDatabase::GetResult::operator=(
+    const GetResult&) = default;
+
+SharedStorageDatabase::GetResult& SharedStorageDatabase::GetResult::operator=(
+    GetResult&&) = default;
+
+SharedStorageDatabase::SharedStorageDatabase(
+    base::FilePath db_path,
+    scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
+    std::unique_ptr<SharedStorageDatabaseOptions> options)
+    : db_({// Run the database in exclusive mode. Nobody else should be
+           // accessing the database while we're running, and this will give
+           // somewhat improved perf.
+           .exclusive_locking = true,
+           .page_size = options->max_page_size,
+           .cache_size = options->max_cache_size}),
+      db_path_(std::move(db_path)),
+      special_storage_policy_(std::move(special_storage_policy)),
+      max_entries_per_origin_(int64_t{options->max_entries_per_origin}),
+      clock_(base::DefaultClock::GetInstance()) {
+  DCHECK(db_path_.empty() || db_path_.IsAbsolute());
+  DCHECK_GT(max_entries_per_origin_, 0);
+  DCHECK_GT(options->max_init_tries, 0);
+  DCHECK_GT(options->max_string_length, 0);
+  max_string_length_ = static_cast<size_t>(options->max_string_length);
+  max_init_tries_ = static_cast<size_t>(options->max_init_tries);
+  db_file_status_ = db_path_.empty() ? DBFileStatus::kNoPreexistingFile
+                                     : DBFileStatus::kNotChecked;
+}
+
+SharedStorageDatabase::~SharedStorageDatabase() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+bool SharedStorageDatabase::Destroy() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (db_.is_open() && !db_.RazeAndClose())
+    return false;
+
+  // The file already doesn't exist.
+  if (db_path_.empty())
+    return true;
+
+  return base::DeleteFile(db_path_);
+}
+
+void SharedStorageDatabase::TrimMemory() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_EQ(InitStatus::kSuccess, db_status_);
+  db_.TrimMemory();
+}
+
+SharedStorageDatabase::GetResult SharedStorageDatabase::Get(
+    url::Origin context_origin,
+    std::u16string key) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_LE(key.size(), max_string_length_);
+  GetResult result;
+
+  if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess) {
+    // We do not return an error if the database doesn't exist, but only if it
+    // pre-exists on disk and yet fails to initialize.
+    if (db_status_ == InitStatus::kUnattempted)
+      result.result = OperationResult::kSuccess;
+    else
+      result.result = OperationResult::kInitFailure;
+
+    return result;
+  }
+
+  // In theory, there ought to be at most one entry found. But we make no
+  // assumption about the state of the disk. In the rare case that multiple
+  // entries are found, we return only the value from the first entry found.
+  static constexpr char kSelectSql[] =
+      "SELECT value FROM values_mapping "
+      "WHERE context_origin=? AND key=? "
+      "LIMIT 1";
+
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
+  std::string origin_str(SerializeOrigin(context_origin));
+  statement.BindString(0, origin_str);
+  statement.BindString16(1, key);
+
+  if (statement.Step())
+    result.data = statement.ColumnString16(0);
+  if (!statement.Succeeded())
+    return result;
+
+  if (UpdateLastUsedTime(origin_str))
+    result.result = OperationResult::kSuccess;
+
+  return result;
+}
+
+SharedStorageDatabase::OperationResult SharedStorageDatabase::Set(
+    url::Origin context_origin,
+    std::u16string key,
+    std::u16string value,
+    SetBehavior behavior) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!key.empty());
+  DCHECK_LE(key.size(), max_string_length_);
+  DCHECK_LE(value.size(), max_string_length_);
+
+  if (LazyInit(DBCreationPolicy::kCreateIfAbsent) != InitStatus::kSuccess)
+    return OperationResult::kInitFailure;
+
+  sql::Transaction transaction(&db_);
+  if (!transaction.Begin())
+    return OperationResult::kSqlError;
+
+  std::string origin_str(SerializeOrigin(context_origin));
+  if (HasEntryFor(origin_str, key)) {
+    if (behavior == SharedStorageDatabase::SetBehavior::kIgnoreIfPresent) {
+      // If we are in a nested transaction, we need to commit, even though we
+      // haven't made any changes, so that the failure to set in this case
+      // isn't seen as an error (as then the entire stack of transactions
+      // will be rolled back and the next transaction within the parent
+      // transaction will fail to begin).
+      if (db_.transaction_nesting())
+        transaction.Commit();
+      return OperationResult::kIgnored;
+    }
+
+    if (Delete(context_origin, key) != OperationResult::kSuccess)
+      return OperationResult::kSqlError;
+  } else if (!HasCapacity(origin_str)) {
+    return OperationResult::kNoCapacity;
+  }
+
+  if (!InsertIntoValuesMapping(origin_str, key, value))
+    return OperationResult::kSqlError;
+
+  if (!UpdateLength(origin_str, /*delta=*/1))
+    return OperationResult::kSqlError;
+
+  if (!transaction.Commit())
+    return OperationResult::kSqlError;
+
+  return OperationResult::kSet;
+}
+
+SharedStorageDatabase::OperationResult SharedStorageDatabase::Append(
+    url::Origin context_origin,
+    std::u16string key,
+    std::u16string tail_value) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!key.empty());
+  DCHECK_LE(key.size(), max_string_length_);
+  DCHECK_LE(tail_value.size(), max_string_length_);
+
+  if (LazyInit(DBCreationPolicy::kCreateIfAbsent) != InitStatus::kSuccess)
+    return OperationResult::kInitFailure;
+
+  sql::Transaction transaction(&db_);
+  if (!transaction.Begin())
+    return OperationResult::kSqlError;
+
+  GetResult get_result = Get(context_origin, key);
+  if (get_result.result != OperationResult::kSuccess)
+    return OperationResult::kSqlError;
+
+  std::u16string new_value;
+  std::string origin_str(SerializeOrigin(context_origin));
+
+  if (get_result.data) {
+    new_value = std::move(*get_result.data);
+    new_value.append(tail_value);
+
+    if (new_value.size() > max_string_length_)
+      return OperationResult::kInvalidAppend;
+
+    if (Delete(context_origin, key) != OperationResult::kSuccess)
+      return OperationResult::kSqlError;
+  } else {
+    new_value = std::move(tail_value);
+
+    if (!HasCapacity(origin_str))
+      return OperationResult::kNoCapacity;
+  }
+
+  if (!InsertIntoValuesMapping(origin_str, key, new_value))
+    return OperationResult::kSqlError;
+
+  if (!UpdateLength(origin_str, /*delta=*/1))
+    return OperationResult::kSqlError;
+
+  if (!transaction.Commit())
+    return OperationResult::kSqlError;
+
+  return OperationResult::kSet;
+}
+
+SharedStorageDatabase::OperationResult SharedStorageDatabase::Delete(
+    url::Origin context_origin,
+    std::u16string key) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_LE(key.size(), max_string_length_);
+
+  if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess) {
+    // We do not return an error if the database doesn't exist, but only if it
+    // pre-exists on disk and yet fails to initialize.
+    if (db_status_ == InitStatus::kUnattempted)
+      return OperationResult::kSuccess;
+    else
+      return OperationResult::kInitFailure;
+  }
+
+  std::string origin_str(SerializeOrigin(context_origin));
+  if (!HasEntryFor(origin_str, key))
+    return OperationResult::kSuccess;
+
+  sql::Transaction transaction(&db_);
+  if (!transaction.Begin())
+    return OperationResult::kSqlError;
+
+  static constexpr char kDeleteSql[] =
+      "DELETE FROM values_mapping "
+      "WHERE context_origin=? AND key=?";
+
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kDeleteSql));
+  statement.BindString(0, origin_str);
+  statement.BindString16(1, key);
+
+  if (!statement.Run())
+    return OperationResult::kSqlError;
+
+  if (!UpdateLength(origin_str, /*delta=*/-1))
+    return OperationResult::kSqlError;
+
+  if (!transaction.Commit())
+    return OperationResult::kSqlError;
+  return OperationResult::kSuccess;
+}
+
+SharedStorageDatabase::OperationResult SharedStorageDatabase::Clear(
+    url::Origin context_origin) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess) {
+    // We do not return an error if the database doesn't exist, but only if it
+    // pre-exists on disk and yet fails to initialize.
+    if (db_status_ == InitStatus::kUnattempted)
+      return OperationResult::kSuccess;
+    else
+      return OperationResult::kInitFailure;
+  }
+
+  if (!Purge(SerializeOrigin(context_origin)))
+    return OperationResult::kSqlError;
+  return OperationResult::kSuccess;
+}
+
+int64_t SharedStorageDatabase::Length(url::Origin context_origin) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess) {
+    // We do not return -1 (to signifiy an error) if the database doesn't exist,
+    // but only if it pre-exists on disk and yet fails to initialize.
+    if (db_status_ == InitStatus::kUnattempted)
+      return 0L;
+    else
+      return -1;
+  }
+
+  std::string origin_str(SerializeOrigin(context_origin));
+  int64_t length = NumEntries(origin_str);
+  if (!length)
+    return 0L;
+
+  if (!UpdateLastUsedTime(origin_str))
+    return -1;
+
+  return length;
+}
+
+SharedStorageDatabase::GetResult SharedStorageDatabase::Key(
+    url::Origin context_origin,
+    uint64_t index) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  GetResult result;
+
+  if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess) {
+    // We do not return an error if the database doesn't exist, but only if it
+    // pre-exists on disk and yet fails to initialize.
+    if (db_status_ == InitStatus::kUnattempted)
+      result.result = OperationResult::kSuccess;
+    else
+      result.result = OperationResult::kInitFailure;
+    return result;
+  }
+
+  static constexpr char kSelectSql[] =
+      "SELECT key FROM values_mapping "
+      "WHERE context_origin=? "
+      "ORDER BY key";
+
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
+  std::string origin_str(SerializeOrigin(context_origin));
+  statement.BindString(0, origin_str);
+
+  uint64_t current_index = 0UL;
+
+  while (statement.Step()) {
+    if (!statement.Succeeded())
+      return result;
+    if (current_index == index) {
+      result.data = statement.ColumnString16(0);
+      break;
+    }
+
+    current_index++;
+  }
+
+  if (UpdateLastUsedTime(origin_str))
+    result.result = OperationResult::kSuccess;
+
+  return result;
+}
+
+SharedStorageDatabase::OperationResult
+SharedStorageDatabase::PurgeMatchingOrigins(
+    OriginMatcherFunction origin_matcher,
+    base::Time begin,
+    base::Time end,
+    bool perform_storage_cleanup) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_LE(begin, end);
+
+  if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess) {
+    // We do not return an error if the database doesn't exist, but only if it
+    // pre-exists on disk and yet fails to initialize.
+    if (db_status_ == InitStatus::kUnattempted)
+      return OperationResult::kSuccess;
+    else
+      return OperationResult::kInitFailure;
+  }
+
+  static constexpr char kSelectSql[] =
+      "SELECT context_origin FROM per_origin_mapping "
+      "WHERE last_used_time BETWEEN ? AND ? "
+      "ORDER BY last_used_time";
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
+  statement.BindTime(0, begin);
+  statement.BindTime(1, end);
+
+  std::vector<std::string> origins;
+
+  while (statement.Step())
+    origins.push_back(statement.ColumnString(0));
+
+  if (!statement.Succeeded())
+    return OperationResult::kSqlError;
+
+  if (origins.empty())
+    return OperationResult::kSuccess;
+
+  sql::Transaction transaction(&db_);
+  if (!transaction.Begin())
+    return OperationResult::kSqlError;
+
+  for (const auto& origin : origins) {
+    if (origin_matcher && !origin_matcher.Run(url::Origin::Create(GURL(origin)),
+                                              special_storage_policy_.get())) {
+      continue;
+    }
+
+    if (!Purge(origin))
+      return OperationResult::kSqlError;
+  }
+
+  if (!transaction.Commit())
+    return OperationResult::kSqlError;
+
+  if (perform_storage_cleanup && !Vacuum())
+    return OperationResult::kSqlError;
+
+  return OperationResult::kSuccess;
+}
+
+SharedStorageDatabase::OperationResult SharedStorageDatabase::PurgeStaleOrigins(
+    base::TimeDelta window_to_be_deemed_active) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_GT(window_to_be_deemed_active, base::TimeDelta());
+
+  if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess) {
+    // We do not return an error if the database doesn't exist, but only if it
+    // pre-exists on disk and yet fails to initialize.
+    if (db_status_ == InitStatus::kUnattempted)
+      return OperationResult::kSuccess;
+    else
+      return OperationResult::kInitFailure;
+  }
+
+  base::Time threshold = clock_->Now() - window_to_be_deemed_active;
+
+  static constexpr char kSelectSql[] =
+      "SELECT context_origin FROM per_origin_mapping "
+      "WHERE last_used_time<? "
+      "ORDER BY last_used_time";
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
+  statement.BindTime(0, threshold);
+
+  std::vector<std::string> stale_origins;
+
+  while (statement.Step())
+    stale_origins.push_back(statement.ColumnString(0));
+
+  if (!statement.Succeeded())
+    return OperationResult::kSqlError;
+
+  if (stale_origins.empty())
+    return OperationResult::kSuccess;
+
+  sql::Transaction transaction(&db_);
+  if (!transaction.Begin())
+    return OperationResult::kSqlError;
+
+  for (const auto& origin : stale_origins) {
+    if (!Purge(origin))
+      return OperationResult::kSqlError;
+  }
+
+  if (!transaction.Commit())
+    return OperationResult::kSqlError;
+  return OperationResult::kSuccess;
+}
+
+std::vector<mojom::StorageUsageInfoPtr> SharedStorageDatabase::FetchOrigins() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess)
+    return {};
+
+  static constexpr char kSelectSql[] =
+      "SELECT context_origin,last_used_time,length FROM per_origin_mapping "
+      "ORDER BY context_origin";
+
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
+  std::vector<mojom::StorageUsageInfoPtr> fetched_origin_infos;
+
+  while (statement.Step()) {
+    fetched_origin_infos.emplace_back(mojom::StorageUsageInfo::New(
+        url::Origin::Create(GURL(statement.ColumnString(0))),
+        statement.ColumnInt64(2) * kSharedStorageEntryTotalBytesMultiplier *
+            max_string_length_,
+        statement.ColumnTime(1)));
+  }
+
+  if (!statement.Succeeded())
+    return {};
+
+  return fetched_origin_infos;
+}
+
+bool SharedStorageDatabase::IsOpenForTesting() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return db_.is_open();
+}
+
+SharedStorageDatabase::InitStatus SharedStorageDatabase::DBStatusForTesting()
+    const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return db_status_;
+}
+
+bool SharedStorageDatabase::OverrideLastUsedTimeForTesting(
+    url::Origin context_origin,
+    base::Time override_last_used_time) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess)
+    return false;
+
+  return SetLastUsedTime(SerializeOrigin(context_origin),
+                         override_last_used_time);
+}
+
+void SharedStorageDatabase::OverrideClockForTesting(base::Clock* clock) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(clock);
+  clock_ = clock;
+}
+
+bool SharedStorageDatabase::OverrideSpecialStoragePolicyForTesting(
+    scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  special_storage_policy_ = std::move(special_storage_policy);
+  return true;
+}
+
+SharedStorageDatabase::InitStatus SharedStorageDatabase::LazyInit(
+    DBCreationPolicy policy) {
+  // Early return in case of previous failure, to prevent an unbounded
+  // number of re-attempts.
+  if (db_status_ != InitStatus::kUnattempted)
+    return db_status_;
+
+  if (policy == DBCreationPolicy::kIgnoreIfAbsent && !DBExists())
+    return InitStatus::kUnattempted;
+
+  for (size_t i = 0; i < max_init_tries_; ++i) {
+    db_status_ = InitImpl();
+    if (db_status_ == InitStatus::kSuccess)
+      return db_status_;
+
+    meta_table_.Reset();
+    db_.Close();
+  }
+
+  return db_status_;
+}
+
+bool SharedStorageDatabase::DBExists() {
+  DCHECK_EQ(InitStatus::kUnattempted, db_status_);
+
+  if (db_file_status_ == DBFileStatus::kNoPreexistingFile)
+    return false;
+
+  // The in-memory case is included in `DBFileStatus::kNoPreexistingFile`.
+  DCHECK(!db_path_.empty());
+
+  // We do not expect `DBExists()` to be called in the case where
+  // `db_file_status_ == DBFileStatus::kPreexistingFile`, as then
+  // `db_status_ != InitStatus::kUnattempted`, which would force an early return
+  // in `LazyInit()`.
+  DCHECK_EQ(DBFileStatus::kNotChecked, db_file_status_);
+
+  // The histogram tag must be set before opening.
+  db_.set_histogram_tag("SharedStorage");
+
+  if (!db_.Open(db_path_)) {
+    db_file_status_ = DBFileStatus::kNoPreexistingFile;
+    return false;
+  }
+
+  static const char kSelectSql[] =
+      "SELECT COUNT(*) FROM sqlite_schema WHERE type=?";
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
+  statement.BindCString(0, "table");
+
+  if (!statement.Step() || statement.ColumnInt(0) == 0) {
+    db_file_status_ = DBFileStatus::kNoPreexistingFile;
+    return false;
+  }
+
+  db_file_status_ = DBFileStatus::kPreexistingFile;
+  return true;
+}
+
+bool SharedStorageDatabase::OpenDatabase() {
+  // If the database is open, the histogram tag will have already been set in
+  // `DBExists()`, since it must be set before opening.
+  if (!db_.is_open())
+    db_.set_histogram_tag("SharedStorage");
+
+  // base::Unretained is safe here because this SharedStorageDatabase owns
+  // the sql::Database instance that stores and uses the callback. So,
+  // `this` is guaranteed to outlive the callback.
+  db_.set_error_callback(base::BindRepeating(
+      &SharedStorageDatabase::DatabaseErrorCallback, base::Unretained(this)));
+
+  if (!db_path_.empty()) {
+    if (!db_.is_open() && !db_.Open(db_path_))
+      return false;
+
+    db_.Preload();
+  } else {
+    if (!db_.OpenInMemory())
+      return false;
+  }
+
+  return true;
+}
+
+void SharedStorageDatabase::DatabaseErrorCallback(int extended_error,
+                                                  sql::Statement* stmt) {
+  base::UmaHistogramSparse("Storage.SharedStorage.Database.Error",
+                           extended_error);
+
+  if (sql::IsErrorCatastrophic(extended_error)) {
+    bool success = Destroy();
+    UMA_HISTOGRAM_BOOLEAN("Storage.SharedStorage.Database.Destruction",
+                          success);
+    if (!success) {
+      DLOG(FATAL) << "Database destruction failed after catastrophic error:\n"
+                  << db_.GetErrorMessage();
+    }
+  }
+
+  // The default handling is to assert on debug and to ignore on release.
+  if (!sql::Database::IsExpectedSqliteError(extended_error))
+    DLOG(FATAL) << db_.GetErrorMessage();
+}
+
+SharedStorageDatabase::InitStatus SharedStorageDatabase::InitImpl() {
+  if (!OpenDatabase())
+    return InitStatus::kError;
+
+  // Database should now be open.
+  DCHECK(db_.is_open());
+
+  // Scope initialization in a transaction so we can't be partially initialized.
+  sql::Transaction transaction(&db_);
+  if (!transaction.Begin()) {
+    LOG(WARNING) << "Shared storage database begin initialization failed.";
+    db_.RazeAndClose();
+    return InitStatus::kError;
+  }
+
+  // Create the tables.
+  if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCurrentVersionNumber) ||
+      !InitSchema(db_)) {
+    return InitStatus::kError;
+  }
+
+  if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
+    LOG(WARNING) << "Shared storage database is too new.";
+    return InitStatus::kTooNew;
+  }
+
+  int cur_version = meta_table_.GetVersionNumber();
+
+  if (cur_version < kCurrentVersionNumber) {
+    LOG(WARNING) << "Shared storage database is too old to be compatible.";
+    db_.RazeAndClose();
+    return InitStatus::kTooOld;
+  }
+
+  // The initialization is complete.
+  if (!transaction.Commit()) {
+    LOG(WARNING) << "Shared storage database initialization commit failed.";
+    db_.RazeAndClose();
+    return InitStatus::kError;
+  }
+
+  return InitStatus::kSuccess;
+}
+
+bool SharedStorageDatabase::Vacuum() {
+  DCHECK_EQ(InitStatus::kSuccess, db_status_);
+  DCHECK_EQ(0, db_.transaction_nesting())
+      << "Can not have a transaction when vacuuming.";
+  return db_.Execute("VACUUM");
+}
+
+bool SharedStorageDatabase::Purge(const std::string& context_origin) {
+  sql::Transaction transaction(&db_);
+  if (!transaction.Begin())
+    return false;
+
+  static constexpr char kDeleteSql[] =
+      "DELETE FROM values_mapping "
+      "WHERE context_origin=?";
+
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kDeleteSql));
+  statement.BindString(0, context_origin);
+
+  if (!statement.Run())
+    return false;
+
+  if (!DeleteFromPerOriginMapping(context_origin))
+    return false;
+
+  return transaction.Commit();
+}
+
+int64_t SharedStorageDatabase::NumEntries(const std::string& context_origin) {
+  // In theory, there ought to be at most one entry found. But we make no
+  // assumption about the state of the disk. In the rare case that multiple
+  // entries are found, we return only the `length` from the first entry found.
+  static constexpr char kSelectSql[] =
+      "SELECT length FROM per_origin_mapping "
+      "WHERE context_origin=? "
+      "LIMIT 1";
+
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
+  statement.BindString(0, context_origin);
+
+  int64_t length = 0;
+  if (statement.Step())
+    length = statement.ColumnInt64(0);
+
+  return length;
+}
+
+bool SharedStorageDatabase::HasEntryFor(const std::string& context_origin,
+                                        const std::u16string& key) {
+  static constexpr char kSelectSql[] =
+      "SELECT 1 FROM values_mapping "
+      "WHERE context_origin=? AND key=? "
+      "LIMIT 1";
+
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
+  statement.BindString(0, context_origin);
+  statement.BindString16(1, key);
+
+  return statement.Step();
+}
+
+bool SharedStorageDatabase::SetLastUsedTime(const std::string& context_origin,
+                                            base::Time new_last_used_time) {
+  int64_t length = NumEntries(context_origin);
+
+  // If length is zero, no need to delete, and don't insert the origin into the
+  // `per_origin_mapping`.
+  if (!length)
+    return true;
+
+  sql::Transaction transaction(&db_);
+  if (!transaction.Begin())
+    return false;
+
+  if (!DeleteFromPerOriginMapping(context_origin))
+    return false;
+
+  if (!InsertIntoPerOriginMapping(context_origin, new_last_used_time, length))
+    return false;
+
+  return transaction.Commit();
+}
+
+bool SharedStorageDatabase::UpdateLastUsedTime(
+    const std::string& context_origin) {
+  return SetLastUsedTime(context_origin, clock_->Now());
+}
+
+bool SharedStorageDatabase::UpdateLength(const std::string& context_origin,
+                                         int64_t delta,
+                                         bool should_update_time) {
+  // In theory, there ought to be at most one entry found. But we make no
+  // assumption about the state of the disk. In the rare case that multiple
+  // entries are found, we retrieve only the `length` (and possibly the `time`)
+  // from the first entry found.
+  static constexpr char kSelectSql[] =
+      "SELECT length,last_used_time FROM per_origin_mapping "
+      "WHERE context_origin=? "
+      "LIMIT 1";
+
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
+  statement.BindString(0, context_origin);
+  int64_t length = 0;
+  base::Time time = clock_->Now();
+
+  if (statement.Step()) {
+    length = statement.ColumnInt64(0);
+    if (!should_update_time)
+      time = statement.ColumnTime(1);
+  }
+
+  sql::Transaction transaction(&db_);
+  if (!transaction.Begin())
+    return false;
+
+  if (!DeleteFromPerOriginMapping(context_origin))
+    return false;
+
+  // If the new length is zero, then don't re-insert the origin into the
+  // `per_origin_mapping`.
+  if (length + delta == 0L)
+    return transaction.Commit();
+
+  if (!InsertIntoPerOriginMapping(context_origin, time, length + delta))
+    return false;
+
+  return transaction.Commit();
+}
+
+bool SharedStorageDatabase::InsertIntoValuesMapping(
+    const std::string& context_origin,
+    const std::u16string& key,
+    const std::u16string& value) {
+  static constexpr char kInsertSql[] =
+      "INSERT INTO values_mapping(context_origin,key,value)"
+      "VALUES(?,?,?)";
+
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kInsertSql));
+  statement.BindString(0, context_origin);
+  statement.BindString16(1, key);
+  statement.BindString16(2, value);
+
+  return statement.Run();
+}
+
+bool SharedStorageDatabase::DeleteFromPerOriginMapping(
+    const std::string& context_origin) {
+  static constexpr char kDeleteSql[] =
+      "DELETE FROM per_origin_mapping "
+      "WHERE context_origin=?";
+
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kDeleteSql));
+  statement.BindString(0, context_origin);
+
+  return statement.Run();
+}
+
+bool SharedStorageDatabase::InsertIntoPerOriginMapping(
+    const std::string& context_origin,
+    base::Time last_used_time,
+    uint64_t length) {
+  static constexpr char kInsertSql[] =
+      "INSERT INTO per_origin_mapping(context_origin,last_used_time,length)"
+      "VALUES(?,?,?)";
+
+  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kInsertSql));
+  statement.BindString(0, context_origin);
+  statement.BindTime(1, last_used_time);
+  statement.BindInt64(2, static_cast<int64_t>(length));
+
+  return statement.Run();
+}
+
+bool SharedStorageDatabase::HasCapacity(const std::string& context_origin) {
+  return NumEntries(context_origin) < max_entries_per_origin_;
+}
+
+}  // namespace storage
diff --git a/components/services/storage/shared_storage/shared_storage_database.h b/components/services/storage/shared_storage/shared_storage_database.h
new file mode 100644
index 0000000..413396a
--- /dev/null
+++ b/components/services/storage/shared_storage/shared_storage_database.h
@@ -0,0 +1,388 @@
+// Copyright 2021 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_SERVICES_STORAGE_SHARED_STORAGE_SHARED_STORAGE_DATABASE_H_
+#define COMPONENTS_SERVICES_STORAGE_SHARED_STORAGE_SHARED_STORAGE_DATABASE_H_
+
+#include <inttypes.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/raw_ptr.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/sequence_checker.h"
+#include "base/thread_annotations.h"
+#include "base/threading/sequence_bound.h"
+#include "base/time/clock.h"
+#include "components/services/storage/public/mojom/storage_usage_info.mojom-forward.h"
+#include "sql/database.h"
+#include "sql/meta_table.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace base {
+class FilePath;
+class Time;
+class TimeDelta;
+}  // namespace base
+
+namespace sql {
+class Statement;
+}
+
+namespace url {
+class Origin;
+}  // namespace url
+
+namespace storage {
+struct SharedStorageDatabaseOptions;
+class SpecialStoragePolicy;
+
+// Multiplier for determining the padded total size in bytes that an origin
+// is using.
+extern const int kSharedStorageEntryTotalBytesMultiplier;
+
+// Wraps its own `sql::Database` instance on behalf of the Shared Storage
+// backend implementation. This object is not sequence-safe and must be
+// instantiated on a sequence which allows use of blocking file operations.
+class SharedStorageDatabase {
+ public:
+  // A callback type to check if a given origin matches a storage policy.
+  // Can be passed empty/null where used, which means the origin will always
+  // match.
+  using OriginMatcherFunction =
+      base::RepeatingCallback<bool(const url::Origin&, SpecialStoragePolicy*)>;
+
+  enum class InitStatus {
+    kUnattempted =
+        0,  // Status if `LazyInit()` has not yet been called or if `LazyInit()`
+            // has early returned due to `DBCreationPolicy::kIgnoreIfAbsent`.
+    kSuccess = 1,  // Status if `LazyInit()` was successful.
+    kError = 2,    // Status if `LazyInit()` failed and a more specific error
+                   // wasn't diagnosed.
+    kTooNew = 3,   // Status if `LazyInit()` failed due to a compatible version
+                   // number being too high.
+    kTooOld = 4,  // Status if `LazyInit()` failed due to a version number being
+                  // too low.
+  };
+
+  enum class DBFileStatus {
+    kNotChecked = 0,  // Status if DB is file-backed and there hasn't been an
+                      // attempt to open the SQL database for the given FilePath
+                      // to see if it exists and contains data.
+    kNoPreexistingFile =
+        1,  // Status if the DB is in-memory or if the DB is file-backed but the
+            // attempt to open it was unsuccessful or any pre-existing file
+            // contained no data.
+    kPreexistingFile =
+        2,  // Status if there was a pre-existing file containing at least one
+            // table that we were able to successfully open.
+  };
+
+  enum class SetBehavior {
+    kDefault = 0,  // Sets entry regardless of whether one previously exists.
+    kIgnoreIfPresent = 1,  // Does not set an entry if one previously exists.
+  };
+
+  enum class OperationResult {
+    kSuccess = 0,      // Result if a non-setting operation is successful.
+    kSet = 1,          // Result if value is set.
+    kIgnored = 2,      // Result if value was present and ignored; no error.
+    kSqlError = 3,     // Result if there is a SQL database error.
+    kInitFailure = 4,  // Result if database initialization failed and a
+                       // database is required.
+    kNoCapacity = 5,   // Result if there was insufficient capacity for the
+    // requesting origin.
+    kInvalidAppend = 6,  // Result if the length of the value after appending
+    // would exceed the maximum allowed length.
+  };
+
+  // Bundles a retrieved string from the database along with a field indicating
+  // whether the transaction was free of SQL errors.
+  struct GetResult {
+    absl::optional<std::u16string> data;
+    OperationResult result = OperationResult::kSqlError;
+    GetResult();
+    GetResult(const GetResult&);
+    GetResult(GetResult&&);
+    ~GetResult();
+    GetResult& operator=(const GetResult&);
+    GetResult& operator=(GetResult&&);
+  };
+
+  // When `db_path` is empty, the database will be opened in memory only.
+  SharedStorageDatabase(
+      base::FilePath db_path,
+      scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
+      std::unique_ptr<SharedStorageDatabaseOptions> options);
+
+  SharedStorageDatabase(const SharedStorageDatabase&) = delete;
+  SharedStorageDatabase(const SharedStorageDatabase&&) = delete;
+
+  ~SharedStorageDatabase();
+
+  SharedStorageDatabase& operator=(const SharedStorageDatabase&) = delete;
+  SharedStorageDatabase& operator=(const SharedStorageDatabase&&) = delete;
+
+  // Deletes the database and returns whether the operation was successful.
+  //
+  // It is OK to call `Destroy()` regardless of whether `Init()` was successful.
+  [[nodiscard]] bool Destroy();
+
+  // Returns a pointer to the database containing the actual data.
+  [[nodiscard]] sql::Database* db() {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    return &db_;
+  }
+
+  // Releases all non-essential memory associated with this database connection.
+  void TrimMemory();
+
+  // Retrieves the `entry` for `context_origin` and `key`. Returns a
+  // struct containing a `value` string if one is found, `absl::nullopt`
+  // otherwise, with a bool `success` indicating whether the transaction was
+  // free of errors.
+  //
+  // Note that `key` is assumed to be of length at most
+  // `max_string_length_`, with the burden on the caller to handle errors for
+  // strings that exceed this length.
+  [[nodiscard]] GetResult Get(url::Origin context_origin, std::u16string key);
+
+  // Sets an entry for `context_origin` and `key` to have `value`.
+  // If `behavior` is `kIgnoreIfPresent` and an entry already exists for
+  // `context_origin` and `key`, then the table is not modified.
+  // Returns an enum indicating whether or not a new entry is added, the request
+  // is ignored, or if there is an error.
+  //
+  // Note that `key` and `value` assumed to be each of length at
+  // most `max_string_length_`, with the burden on the caller to handle errors
+  // for strings that exceed this length. Moreover, if `Length(context_origin)`
+  // equals `max_entries_per_origin_`, `Set()` will return a value of
+  // `OperationResult::kNoCapacity` and the table will not be modified.
+  [[nodiscard]] OperationResult Set(
+      url::Origin context_origin,
+      std::u16string key,
+      std::u16string value,
+      SetBehavior behavior = SetBehavior::kDefault);
+
+  // Appends `tail_value` to the end of the current `value`
+  // for `context_origin` and `key`, if `key` exists. If
+  // `key` does not exist, creates an entry for `key` with value
+  // `tail_value`. Returns an enum indicating whether or not an entry is
+  // added/modified or if there is an error.
+  //
+  // Note that `key` and `value` are assumed to be each of length
+  // at most `max_string_length_`, with the burden on the caller to handle
+  // errors for strings that exceed this length. Moreover, if the length of the
+  // string obtained by concatening the current `value` (if one exists)
+  // and `tail_value` exceeds `max_string_length_`, or if
+  // `Length(context_origin)` equals `max_entries_per_origin_`, `Append()` will
+  // return a value of `OperationResult::kNoCapacity` and the table will not be
+  // modified.
+  [[nodiscard]] OperationResult Append(url::Origin context_origin,
+                                       std::u16string key,
+                                       std::u16string tail_value);
+
+  // Deletes the entry for `context_origin` and `key`. Returns
+  // whether the deletion is successful.
+  //
+  // Note that `key` is assumed to be of length at most
+  // `max_string_length_`, with the burden on the caller to handle errors for
+  // strings that exceed this length.
+  [[nodiscard]] OperationResult Delete(url::Origin context_origin,
+                                       std::u16string key);
+
+  // Clears all entries for `context_origin`. Returns whether the operation is
+  // successful.
+  [[nodiscard]] OperationResult Clear(url::Origin context_origin);
+
+  // Returns the number of entries for `context_origin` in the database, or -1
+  // on error. Note that this call will update the origin's `last_used_time`.
+  // TODO(crbug.com/1277662): Consider renaming to something more descriptive.
+  [[nodiscard]] int64_t Length(url::Origin context_origin);
+
+  // If a list of all the keys for `context_origin` are taken in lexicographic
+  // order, retrieves the `key` at `index` of the list and sets it as
+  // data in the returned struct; otherwise the struct holds `absl::nullopt` if
+  // no such `key` exists.  The `GetResult` struct also has a bool
+  // `success` indicating whether the transaction was free of errors.
+  //
+  // TODO(crbug.com/1247861): Replace with an async iterator.
+  [[nodiscard]] GetResult Key(url::Origin context_origin, uint64_t index);
+
+  // Clears all origins that match `origin_matcher` run on the owning
+  // StoragePartition's `SpecialStoragePolicy` and have `last_used_time` between
+  // the times `begin` and `end`. If `perform_storage_cleanup` is true, vacuums
+  // the database afterwards. Returns whether the transaction was successful.
+  [[nodiscard]] OperationResult PurgeMatchingOrigins(
+      OriginMatcherFunction origin_matcher,
+      base::Time begin,
+      base::Time end,
+      bool perform_storage_cleanup = false);
+
+  // Clear all entries for all origins whose `last_read_time` falls before
+  // `base::Time::Now() - window_to_be_deemed_active`. Returns whether the
+  // transaction was successful.
+  [[nodiscard]] OperationResult PurgeStaleOrigins(
+      base::TimeDelta window_to_be_deemed_active);
+
+  // Fetches a vector of `mojom::StorageUsageInfoPtr`, with one
+  // `mojom::StorageUsageInfoPtr` for each origin currently using shared storage
+  // in this profile.
+  [[nodiscard]] std::vector<mojom::StorageUsageInfoPtr> FetchOrigins();
+
+  // Returns whether the SQLite database is open.
+  [[nodiscard]] bool IsOpenForTesting() const;
+
+  // Returns the `db_status_` for tests.
+  [[nodiscard]] InitStatus DBStatusForTesting() const;
+
+  // Changes `last_used_time` to `override_last_used_time` for `context_origin`.
+  [[nodiscard]] bool OverrideLastUsedTimeForTesting(
+      url::Origin context_origin,
+      base::Time override_last_used_time);
+
+  // Overrides the clock used to check the time.
+  void OverrideClockForTesting(base::Clock* clock);
+
+  // Overrides the `SpecialStoragePolicy` for tests. Returns true.
+  [[nodiscard]] bool OverrideSpecialStoragePolicyForTesting(
+      scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy);
+
+ private:
+  // Policy to tell `LazyInit()` whether or not to create a new database if a
+  // pre-existing on-disk database is not found.
+  enum class DBCreationPolicy {
+    kIgnoreIfAbsent = 0,
+    kCreateIfAbsent = 1,
+  };
+
+  // Called at the start of each public operation, and initializes the database
+  // if it isn't already initialized (unless there is no pre-existing on-disk
+  // database to initialize and `policy` is
+  // `DBCreationPolicy::kIgnoreIfAbsent`).
+  [[nodiscard]] InitStatus LazyInit(DBCreationPolicy policy)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Determines whether or not an uninitialized DB already exists on disk.
+  [[nodiscard]] bool DBExists() VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // If `db_path_` is empty, opens a temporary database in memory; otherwise
+  // opens a persistent database with the absolute path `db_path`, creating the
+  // file if it does not yet exist. Returns whether opening was successful.
+  [[nodiscard]] bool OpenDatabase() VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Callback for database errors. Schedules a call to Destroy() if the
+  // error is catastrophic.
+  void DatabaseErrorCallback(int extended_error, sql::Statement* stmt)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Helper function to implement internals of `Init()`.  This allows
+  // Init() to retry in case of failure, since some failures run
+  // recovery code.
+  [[nodiscard]] InitStatus InitImpl() VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Vacuums the database. This will cause sqlite to defragment and collect
+  // unused space in the file. It can be VERY SLOW. Returns whether the
+  // operation was successful.
+  [[nodiscard]] bool Vacuum() VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Clears all entries for `context_origin`. Returns whether deletion is
+  // successful. Not named `Clear()` to distinguish it from the public method
+  // called via `SequenceBound::AsyncCall()`.
+  [[nodiscard]] bool Purge(const std::string& context_origin)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Returns the number of entries for `context_origin`, i.e. the `length`.
+  // Not named `Length()` to distinguish it from the public method called via
+  // `SequenceBound::AsyncCall()`.
+  [[nodiscard]] int64_t NumEntries(const std::string& context_origin)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Returns whether an entry exists for `context_origin` and `key`.
+  [[nodiscard]] bool HasEntryFor(const std::string& context_origin,
+                                 const std::u16string& key)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Sets `last_used_time` to `new_last_used_time` for `context_origin`.
+  [[nodiscard]] bool SetLastUsedTime(const std::string& context_origin,
+                                     base::Time new_last_used_time)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Updates `last_used_time` to `base::Time::Now()` for `context_origin`.
+  [[nodiscard]] bool UpdateLastUsedTime(const std::string& context_origin)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Updates `length` by `delta` for `context_origin`. If `should_update_time`
+  // is true, also updates `last_used_time` to `base::Time::Now()`.
+  [[nodiscard]] bool UpdateLength(const std::string& context_origin,
+                                  int64_t delta,
+                                  bool should_update_time = true)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Inserts a triple for `(context_origin,key,value)` into
+  // `values_mapping`.
+  [[nodiscard]] bool InsertIntoValuesMapping(const std::string& context_origin,
+                                             const std::u16string& key,
+                                             const std::u16string& value)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Deletes the row for `context_origin` from `per_origin_mapping`.
+  [[nodiscard]] bool DeleteFromPerOriginMapping(
+      const std::string& context_origin)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Inserts the triple for `(context_origin, last_used_time, length)` into
+  // `per_origin_mapping`.
+  [[nodiscard]] bool InsertIntoPerOriginMapping(
+      const std::string& context_origin,
+      base::Time last_used_time,
+      uint64_t length) VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Returns whether the `length` for `context_origin` is less than
+  // `max_entries_per_origin_`.
+  [[nodiscard]] bool HasCapacity(const std::string& context_origin)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // The database containing the actual data.
+  sql::Database db_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // Contains the version information.
+  sql::MetaTable meta_table_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // Initialization status of `db_`.
+  GUARDED_BY_CONTEXT(sequence_checker_)
+  InitStatus db_status_ = InitStatus::kUnattempted;
+
+  // Only set to true if `DBExists()
+  DBFileStatus db_file_status_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // The path to the database, if file-backed.
+  base::FilePath db_path_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // The owning partition's storage policy.
+  scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_
+      GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // The maximum allowed number of entries per origin.
+  const int64_t max_entries_per_origin_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // The maximum size of a string input from any origin's script. Applies
+  // separately to both script keys and script values.
+  size_t max_string_length_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // Maxmium number of times that SQL database attempts to initialize.
+  size_t max_init_tries_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // Clock used to determine current time. Can be overridden in tests.
+  raw_ptr<base::Clock> clock_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  SEQUENCE_CHECKER(sequence_checker_);
+};
+
+}  // namespace storage
+
+#endif  // COMPONENTS_SERVICES_STORAGE_SHARED_STORAGE_SHARED_STORAGE_DATABASE_H_
diff --git a/components/services/storage/shared_storage/shared_storage_database_unittest.cc b/components/services/storage/shared_storage/shared_storage_database_unittest.cc
new file mode 100644
index 0000000..364bead
--- /dev/null
+++ b/components/services/storage/shared_storage/shared_storage_database_unittest.cc
@@ -0,0 +1,835 @@
+// Copyright 2021 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/services/storage/shared_storage/shared_storage_database.h"
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "components/services/storage/public/mojom/storage_usage_info.mojom.h"
+#include "components/services/storage/shared_storage/shared_storage_options.h"
+#include "components/services/storage/shared_storage/shared_storage_test_utils.h"
+#include "sql/database.h"
+#include "storage/browser/quota/special_storage_policy.h"
+#include "storage/browser/test/mock_special_storage_policy.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace storage {
+
+namespace {
+
+using ::testing::ElementsAre;
+using OriginMatcherFunction = SharedStorageDatabase::OriginMatcherFunction;
+using InitStatus = SharedStorageDatabase::InitStatus;
+using SetBehavior = SharedStorageDatabase::SetBehavior;
+using OperationResult = SharedStorageDatabase::OperationResult;
+using GetResult = SharedStorageDatabase::GetResult;
+
+const int kMaxEntriesPerOrigin = 5;
+const int kMaxStringLength = 100;
+
+}  // namespace
+
+class SharedStorageDatabaseTest : public testing::Test {
+ public:
+  SharedStorageDatabaseTest() {
+    special_storage_policy_ = base::MakeRefCounted<MockSpecialStoragePolicy>();
+  }
+
+  ~SharedStorageDatabaseTest() override = default;
+
+  void SetUp() override {
+    InitSharedStorageFeature();
+
+    // Get a temporary directory for the test DB files.
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+    file_name_ = temp_dir_.GetPath().AppendASCII("TestSharedStorage.db");
+  }
+
+  void TearDown() override {
+    db_.reset();
+    EXPECT_TRUE(temp_dir_.Delete());
+  }
+
+  // Initialize a shared storage database instance from the SQL file at
+  // `relative_file_path` in the "storage/" subdirectory of test data.
+  std::unique_ptr<SharedStorageDatabase> LoadFromFile(
+      const char* relative_file_path) {
+    if (!CreateDatabaseFromSQL(file_name_, relative_file_path)) {
+      ADD_FAILURE() << "Failed loading " << relative_file_path;
+      return nullptr;
+    }
+
+    return std::make_unique<SharedStorageDatabase>(
+        file_name_, special_storage_policy_,
+        SharedStorageOptions::Create()->GetDatabaseOptions());
+  }
+
+  sql::Database* SqlDB() { return db_ ? db_->db() : nullptr; }
+
+  virtual void InitSharedStorageFeature() {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        {blink::features::kSharedStorageAPI},
+        {{"MaxSharedStorageInitTries", "1"}});
+  }
+
+ protected:
+  base::ScopedTempDir temp_dir_;
+  base::FilePath file_name_;
+  scoped_refptr<storage::MockSpecialStoragePolicy> special_storage_policy_;
+  std::unique_ptr<SharedStorageDatabase> db_;
+  base::test::ScopedFeatureList scoped_feature_list_;
+  base::SimpleTestClock clock_;
+
+ private:
+  base::test::SingleThreadTaskEnvironment task_environment_;
+};
+
+// Test loading version 1 database.
+TEST_F(SharedStorageDatabaseTest, Version1_LoadFromFile) {
+  db_ = LoadFromFile("shared_storage.v1.sql");
+  ASSERT_TRUE(db_);
+
+  url::Origin google_com = url::Origin::Create(GURL("http://google.com/"));
+  EXPECT_EQ(db_->Get(google_com, u"key1").data, u"value1");
+  EXPECT_EQ(db_->Get(google_com, u"key2").data, u"value2");
+
+  // Because the SQL database is lazy-initialized, wait to verify tables and
+  // columns until after the first call to `Get()`.
+  ASSERT_TRUE(SqlDB());
+  VerifySharedStorageTablesAndColumns(*SqlDB());
+
+  url::Origin youtube_com = url::Origin::Create(GURL("http://youtube.com/"));
+  EXPECT_EQ(1L, db_->Length(youtube_com));
+
+  url::Origin chromium_org = url::Origin::Create(GURL("http://chromium.org/"));
+  EXPECT_EQ(db_->Get(chromium_org, u"a").data, u"");
+  EXPECT_EQ(db_->Key(chromium_org, 2UL).data, u"c");
+
+  url::Origin google_org = url::Origin::Create(GURL("http://google.org/"));
+  EXPECT_EQ(
+      db_->Get(google_org, u"1").data,
+      u"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "fffffffffffffffff");
+  EXPECT_EQ(db_->Get(google_org,
+                     u"ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
+                .data,
+            u"k");
+
+  std::vector<url::Origin> origins;
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(
+      origins,
+      ElementsAre(
+          url::Origin::Create(GURL("http://abc.xyz")), chromium_org, google_com,
+          google_org, url::Origin::Create(GURL("http://growwithgoogle.com")),
+          url::Origin::Create(GURL("http://gv.com")),
+          url::Origin::Create(GURL("http://waymo.com")),
+          url::Origin::Create(GURL("http://withgoogle.com")), youtube_com));
+
+  EXPECT_TRUE(db_->Destroy());
+}
+
+TEST_F(SharedStorageDatabaseTest, Version1_DestroyTooNew) {
+  // Initialization should fail, since the last compatible version number
+  // is too high.
+  db_ = LoadFromFile("shared_storage.v1.init_too_new.sql");
+  ASSERT_TRUE(db_);
+  ASSERT_TRUE(SqlDB());
+
+  // Call an operation so that the database will attempt to be lazy-initialized.
+  const url::Origin kOrigin = url::Origin::Create(GURL("http://www.a.com"));
+  EXPECT_EQ(OperationResult::kInitFailure, db_->Set(kOrigin, u"key", u"value"));
+  ASSERT_FALSE(db_->IsOpenForTesting());
+  EXPECT_EQ(InitStatus::kTooNew, db_->DBStatusForTesting());
+
+  // Test that other operations likewise fail, in order to exercise these code
+  // paths.
+  EXPECT_EQ(OperationResult::kInitFailure, db_->Get(kOrigin, u"key").result);
+  EXPECT_EQ(OperationResult::kInitFailure,
+            db_->Append(kOrigin, u"key", u"value"));
+  EXPECT_EQ(OperationResult::kInitFailure, db_->Delete(kOrigin, u"key"));
+  EXPECT_EQ(OperationResult::kInitFailure, db_->Clear(kOrigin));
+  EXPECT_EQ(-1, db_->Length(kOrigin));
+  EXPECT_EQ(OperationResult::kInitFailure, db_->Key(kOrigin, 0).result);
+  EXPECT_EQ(OperationResult::kInitFailure,
+            db_->PurgeMatchingOrigins(OriginMatcherFunction(),
+                                      base::Time::Min(), base::Time::Max(),
+                                      /*perform_storage_cleanup=*/false));
+  EXPECT_EQ(OperationResult::kInitFailure,
+            db_->PurgeStaleOrigins(base::Seconds(1)));
+
+  // Test that it is still OK to Destroy() the database.
+  EXPECT_TRUE(db_->Destroy());
+}
+
+TEST_F(SharedStorageDatabaseTest, Version0_DestroyTooOld) {
+  // Initialization should fail, since the current version number
+  // is too low and we're forcing there not to be a retry attempt.
+  db_ = LoadFromFile("shared_storage.v0.init_too_old.sql");
+  ASSERT_TRUE(db_);
+  ASSERT_TRUE(SqlDB());
+
+  // Call an operation so that the database will attempt to be lazy-initialized.
+  EXPECT_EQ(OperationResult::kInitFailure,
+            db_->Set(url::Origin::Create(GURL("http://www.a.com")), u"key",
+                     u"value"));
+  ASSERT_FALSE(db_->IsOpenForTesting());
+  EXPECT_EQ(InitStatus::kTooOld, db_->DBStatusForTesting());
+
+  // Test that it is still OK to Destroy() the database.
+  EXPECT_TRUE(db_->Destroy());
+}
+
+class SharedStorageDatabaseParamTest
+    : public SharedStorageDatabaseTest,
+      public testing::WithParamInterface<SharedStorageWrappedBool> {
+ public:
+  void SetUp() override {
+    SharedStorageDatabaseTest::SetUp();
+
+    auto options = SharedStorageOptions::Create()->GetDatabaseOptions();
+    base::FilePath db_path =
+        (GetParam().in_memory_only) ? base::FilePath() : file_name_;
+    db_ = std::make_unique<SharedStorageDatabase>(
+        db_path, special_storage_policy_, std::move(options));
+    db_->OverrideClockForTesting(&clock_);
+  }
+
+  void InitSharedStorageFeature() override {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        {blink::features::kSharedStorageAPI},
+        {{"MaxSharedStorageEntriesPerOrigin",
+          base::NumberToString(kMaxEntriesPerOrigin)},
+         {"MaxSharedStorageStringLength",
+          base::NumberToString(kMaxStringLength)}});
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         SharedStorageDatabaseParamTest,
+                         testing::ValuesIn(GetSharedStorageWrappedBools()),
+                         testing::PrintToStringParamName());
+
+TEST_P(SharedStorageDatabaseParamTest, BasicOperations) {
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"value1");
+
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value2"));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"value2");
+
+  EXPECT_EQ(OperationResult::kSuccess, db_->Delete(kOrigin1, u"key1"));
+  EXPECT_FALSE(db_->Get(kOrigin1, u"key1").data);
+
+  // Check that trying to retrieve the empty key doesn't give an error, even
+  // though the input is invalid and no value is found.
+  GetResult result = db_->Get(kOrigin1, u"");
+  EXPECT_EQ(OperationResult::kSuccess, result.result);
+  EXPECT_FALSE(result.data);
+
+  // Check that trying to delete the empty key doesn't give an error, even
+  // though the input is invalid and no value is found to delete.
+  EXPECT_EQ(OperationResult::kSuccess, db_->Delete(kOrigin1, u""));
+}
+
+TEST_P(SharedStorageDatabaseParamTest, IgnoreIfPresent) {
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"value1");
+
+  // The database does not set a new value for "key1", but retains the
+  // previously set value "value1" because `behavior` is `kIgnoreIfPresent`.
+  EXPECT_EQ(OperationResult::kIgnored,
+            db_->Set(kOrigin1, u"key1", u"value2",
+                     /*behavior=*/SetBehavior::kIgnoreIfPresent));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"value1");
+
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value1"));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key2").data, u"value1");
+
+  // Having `behavior` set to `kDefault` makes `Set()` override any previous
+  // value.
+  EXPECT_EQ(OperationResult::kSet,
+            db_->Set(kOrigin1, u"key2", u"value2",
+                     /*behavior=*/SetBehavior::kDefault));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key2").data, u"value2");
+
+  const url::Origin kOrigin2 =
+      url::Origin::Create(GURL("http://www.example2.test"));
+
+  // If no previous value exists, it makes no difference whether
+  // `behavior` is set to `kDefault` or `kIgnoreIfPresent`.
+  EXPECT_EQ(OperationResult::kSet,
+            db_->Set(kOrigin2, u"key1", u"value1",
+                     /*behavior=*/SetBehavior::kIgnoreIfPresent));
+  EXPECT_EQ(db_->Get(kOrigin2, u"key1").data, u"value1");
+
+  EXPECT_EQ(OperationResult::kSet,
+            db_->Set(kOrigin2, u"key2", u"value2",
+                     /*behavior=*/SetBehavior::kDefault));
+  EXPECT_EQ(db_->Get(kOrigin2, u"key2").data, u"value2");
+}
+
+TEST_P(SharedStorageDatabaseParamTest, Append) {
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Append(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"value1");
+
+  EXPECT_EQ(OperationResult::kSet, db_->Append(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"value1value1");
+
+  EXPECT_EQ(OperationResult::kSet, db_->Append(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"value1value1value1");
+}
+
+TEST_P(SharedStorageDatabaseParamTest, Length) {
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(0L, db_->Length(kOrigin1));
+
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(1L, db_->Length(kOrigin1));
+
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value2"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value3"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  const url::Origin kOrigin2 =
+      url::Origin::Create(GURL("http://www.example2.test"));
+  EXPECT_EQ(0L, db_->Length(kOrigin2));
+
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key1", u"value1"));
+  EXPECT_EQ(1L, db_->Length(kOrigin2));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  EXPECT_EQ(OperationResult::kSuccess, db_->Delete(kOrigin2, u"key1"));
+  EXPECT_EQ(0L, db_->Length(kOrigin2));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key3", u"value3"));
+  EXPECT_EQ(3L, db_->Length(kOrigin1));
+  EXPECT_EQ(0L, db_->Length(kOrigin2));
+}
+
+TEST_P(SharedStorageDatabaseParamTest, Key) {
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_FALSE(db_->Key(kOrigin1, 0UL).data);
+
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value2"));
+  EXPECT_EQ(db_->Key(kOrigin1, 0UL).data, u"key1");
+  EXPECT_EQ(db_->Key(kOrigin1, 1UL).data, u"key2");
+  EXPECT_FALSE(db_->Key(kOrigin1, 2UL).data);
+
+  const url::Origin kOrigin2 =
+      url::Origin::Create(GURL("http://www.example2.test"));
+  EXPECT_FALSE(db_->Key(kOrigin2, 0UL).data);
+
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key2", u"value2"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key1", u"value1"));
+  EXPECT_EQ(db_->Key(kOrigin2, 0UL).data, u"key1");
+  EXPECT_EQ(db_->Key(kOrigin2, 1UL).data, u"key2");
+
+  EXPECT_EQ(OperationResult::kSuccess, db_->Delete(kOrigin2, u"key2"));
+  EXPECT_EQ(db_->Key(kOrigin2, 0UL).data, u"key1");
+
+  // There is no longer a key at this index.
+  EXPECT_FALSE(db_->Key(kOrigin2, 1UL).data);
+}
+
+TEST_P(SharedStorageDatabaseParamTest, Clear) {
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value2"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key3", u"value3"));
+  EXPECT_EQ(3L, db_->Length(kOrigin1));
+
+  const url::Origin kOrigin2 =
+      url::Origin::Create(GURL("http://www.example2.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key2", u"value2"));
+  EXPECT_EQ(2L, db_->Length(kOrigin2));
+
+  EXPECT_EQ(OperationResult::kSuccess, db_->Clear(kOrigin1));
+  EXPECT_EQ(0L, db_->Length(kOrigin1));
+  EXPECT_EQ(2L, db_->Length(kOrigin2));
+
+  EXPECT_EQ(OperationResult::kSuccess, db_->Clear(kOrigin2));
+  EXPECT_EQ(0L, db_->Length(kOrigin2));
+}
+
+TEST_P(SharedStorageDatabaseParamTest, FetchOrigins) {
+  EXPECT_TRUE(db_->FetchOrigins().empty());
+
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value2"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  const url::Origin kOrigin2 =
+      url::Origin::Create(GURL("http://www.example2.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key1", u"value1"));
+  EXPECT_EQ(1L, db_->Length(kOrigin2));
+
+  const url::Origin kOrigin3 =
+      url::Origin::Create(GURL("http://www.example3.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key1", u"value1"));
+  EXPECT_EQ(1L, db_->Length(kOrigin3));
+
+  const url::Origin kOrigin4 =
+      url::Origin::Create(GURL("http://www.example4.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key2", u"value2"));
+  EXPECT_EQ(2L, db_->Length(kOrigin4));
+
+  std::vector<url::Origin> origins;
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin2, kOrigin3, kOrigin4));
+
+  EXPECT_EQ(OperationResult::kSuccess, db_->Clear(kOrigin1));
+  EXPECT_EQ(0L, db_->Length(kOrigin1));
+
+  EXPECT_EQ(OperationResult::kSuccess, db_->Delete(kOrigin2, u"key1"));
+  EXPECT_EQ(0L, db_->Length(kOrigin2));
+
+  origins.clear();
+  EXPECT_TRUE(origins.empty());
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin3, kOrigin4));
+}
+
+class SharedStorageDatabasePurgeMatchingOriginsParamTest
+    : public SharedStorageDatabaseTest,
+      public testing::WithParamInterface<PurgeMatchingOriginsParams> {
+ public:
+  void SetUp() override {
+    SharedStorageDatabaseTest::SetUp();
+
+    auto options = SharedStorageOptions::Create()->GetDatabaseOptions();
+    base::FilePath db_path =
+        (GetParam().in_memory_only) ? base::FilePath() : file_name_;
+    db_ = std::make_unique<SharedStorageDatabase>(
+        db_path, special_storage_policy_, std::move(options));
+    db_->OverrideClockForTesting(&clock_);
+  }
+
+  void InitSharedStorageFeature() override {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        {blink::features::kSharedStorageAPI},
+        {{"MaxSharedStorageEntriesPerOrigin",
+          base::NumberToString(kMaxEntriesPerOrigin)},
+         {"MaxSharedStorageStringLength",
+          base::NumberToString(kMaxStringLength)}});
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         SharedStorageDatabasePurgeMatchingOriginsParamTest,
+                         testing::ValuesIn(GetPurgeMatchingOriginsParams()),
+                         testing::PrintToStringParamName());
+
+TEST_P(SharedStorageDatabasePurgeMatchingOriginsParamTest, AllTime) {
+  EXPECT_TRUE(db_->FetchOrigins().empty());
+
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value2"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  const url::Origin kOrigin2 =
+      url::Origin::Create(GURL("http://www.example2.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key1", u"value1"));
+  EXPECT_EQ(1L, db_->Length(kOrigin2));
+
+  const url::Origin kOrigin3 =
+      url::Origin::Create(GURL("http://www.example3.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key2", u"value2"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key3", u"value3"));
+  EXPECT_EQ(3L, db_->Length(kOrigin3));
+
+  std::vector<url::Origin> origins;
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin2, kOrigin3));
+
+  EXPECT_EQ(
+      OperationResult::kSuccess,
+      db_->PurgeMatchingOrigins(
+          OriginMatcherFunctionUtility::MakeMatcherFunction({kOrigin1}),
+          base::Time(), base::Time::Max(), GetParam().perform_storage_cleanup));
+
+  // `kOrigin1` is cleared. The other origins are not.
+  EXPECT_EQ(0L, db_->Length(kOrigin1));
+  EXPECT_EQ(1L, db_->Length(kOrigin2));
+  EXPECT_EQ(3L, db_->Length(kOrigin3));
+
+  origins.clear();
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin2, kOrigin3));
+
+  EXPECT_EQ(
+      OperationResult::kSuccess,
+      db_->PurgeMatchingOrigins(
+          OriginMatcherFunctionUtility::MakeMatcherFunction(
+              {kOrigin2, kOrigin3}),
+          base::Time(), base::Time::Max(), GetParam().perform_storage_cleanup));
+
+  // All three origins should be cleared.
+  EXPECT_EQ(0L, db_->Length(kOrigin1));
+  EXPECT_EQ(0L, db_->Length(kOrigin2));
+  EXPECT_EQ(0L, db_->Length(kOrigin3));
+
+  EXPECT_TRUE(db_->FetchOrigins().empty());
+
+  // There is no error from trying to clear an origin that isn't in the
+  // database.
+  EXPECT_EQ(
+      OperationResult::kSuccess,
+      db_->PurgeMatchingOrigins(
+          OriginMatcherFunctionUtility::MakeMatcherFunction(
+              {"http://www.example4.test"}),
+          base::Time(), base::Time::Max(), GetParam().perform_storage_cleanup));
+}
+
+TEST_P(SharedStorageDatabasePurgeMatchingOriginsParamTest, SinceThreshold) {
+  EXPECT_TRUE(db_->FetchOrigins().empty());
+
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value2"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  const url::Origin kOrigin2 =
+      url::Origin::Create(GURL("http://www.example2.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key1", u"value1"));
+  EXPECT_EQ(1L, db_->Length(kOrigin2));
+
+  const url::Origin kOrigin3 =
+      url::Origin::Create(GURL("http://www.example3.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key2", u"value2"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key3", u"value3"));
+  EXPECT_EQ(3L, db_->Length(kOrigin3));
+
+  const url::Origin kOrigin4 =
+      url::Origin::Create(GURL("http://www.example4.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key2", u"value2"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key3", u"value3"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key4", u"value4"));
+  EXPECT_EQ(4L, db_->Length(kOrigin4));
+
+  clock_.SetNow(base::Time::Now());
+  clock_.Advance(base::Milliseconds(50));
+
+  // Time threshold that will be used as a starting point for deletion.
+  base::Time threshold = clock_.Now();
+
+  std::vector<url::Origin> origins;
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin2, kOrigin3, kOrigin4));
+
+  // Read from `kOrigin1`.
+  EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"value1");
+
+  EXPECT_EQ(
+      OperationResult::kSuccess,
+      db_->PurgeMatchingOrigins(
+          OriginMatcherFunctionUtility::MakeMatcherFunction(
+              {kOrigin1, kOrigin2}),
+          threshold, base::Time::Max(), GetParam().perform_storage_cleanup));
+
+  // `kOrigin1` is cleared. The other origins are not.
+  EXPECT_EQ(0L, db_->Length(kOrigin1));
+  EXPECT_EQ(1L, db_->Length(kOrigin2));
+  EXPECT_EQ(3L, db_->Length(kOrigin3));
+  EXPECT_EQ(4L, db_->Length(kOrigin4));
+
+  clock_.Advance(base::Milliseconds(50));
+
+  // Time threshold that will be used as a starting point for deletion.
+  threshold = clock_.Now();
+
+  // Write to `kOrigin3`.
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key4", u"value4"));
+  EXPECT_EQ(4L, db_->Length(kOrigin3));
+
+  origins.clear();
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin2, kOrigin3, kOrigin4));
+
+  EXPECT_EQ(
+      OperationResult::kSuccess,
+      db_->PurgeMatchingOrigins(
+          OriginMatcherFunctionUtility::MakeMatcherFunction(
+              {kOrigin2, kOrigin3, kOrigin4}),
+          threshold, base::Time::Max(), GetParam().perform_storage_cleanup));
+
+  // `kOrigin3` is cleared. The others weren't modified within the given time
+  // period.
+  EXPECT_EQ(0L, db_->Length(kOrigin1));
+  EXPECT_EQ(1L, db_->Length(kOrigin2));
+  EXPECT_EQ(0L, db_->Length(kOrigin3));
+  EXPECT_EQ(4L, db_->Length(kOrigin4));
+
+  origins.clear();
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin2, kOrigin4));
+
+  // There is no error from trying to clear an origin that isn't in the
+  // database.
+  EXPECT_EQ(
+      OperationResult::kSuccess,
+      db_->PurgeMatchingOrigins(
+          OriginMatcherFunctionUtility::MakeMatcherFunction(
+              {"http://www.example5.test"}),
+          threshold, base::Time::Max(), GetParam().perform_storage_cleanup));
+}
+
+TEST_P(SharedStorageDatabaseParamTest, PurgeStaleOrigins) {
+  EXPECT_TRUE(db_->FetchOrigins().empty());
+
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value2"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"value1");
+  EXPECT_EQ(db_->Get(kOrigin1, u"key2").data, u"value2");
+
+  const url::Origin kOrigin2 =
+      url::Origin::Create(GURL("http://www.example2.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key1", u"value1"));
+  EXPECT_EQ(1L, db_->Length(kOrigin2));
+  EXPECT_EQ(db_->Get(kOrigin2, u"key1").data, u"value1");
+
+  const url::Origin kOrigin3 =
+      url::Origin::Create(GURL("http://www.example3.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key2", u"value2"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key3", u"value3"));
+  EXPECT_EQ(3L, db_->Length(kOrigin3));
+
+  const url::Origin kOrigin4 =
+      url::Origin::Create(GURL("http://www.example4.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key2", u"value2"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key3", u"value3"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key4", u"value4"));
+  EXPECT_EQ(4L, db_->Length(kOrigin4));
+
+  std::vector<url::Origin> origins;
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin2, kOrigin3, kOrigin4));
+
+  clock_.SetNow(base::Time::Now());
+  clock_.Advance(base::Milliseconds(50));
+
+  // Time threshold after which an origin must be read from or written to in
+  // order to be considered active.
+  base::Time threshold = clock_.Now();
+  clock_.Advance(base::Milliseconds(50));
+
+  // Read from `kOrigin1`.
+  EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"value1");
+
+  // Write to `kOrigin3`.
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key4", u"value4"));
+  EXPECT_EQ(4L, db_->Length(kOrigin3));
+
+  EXPECT_EQ(OperationResult::kSuccess,
+            db_->PurgeStaleOrigins(clock_.Now() - threshold));
+
+  // `kOrigin1` was active.
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  // `kOrigin2` was inactive.
+  EXPECT_EQ(0L, db_->Length(kOrigin2));
+
+  // `kOrigin3` was active.
+  EXPECT_EQ(4L, db_->Length(kOrigin3));
+
+  // `kOrigin4` was inactive.
+  EXPECT_EQ(0L, db_->Length(kOrigin4));
+
+  origins.clear();
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin3));
+}
+
+TEST_P(SharedStorageDatabaseParamTest, TrimMemory) {
+  EXPECT_TRUE(db_->FetchOrigins().empty());
+
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value2"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  const url::Origin kOrigin2 =
+      url::Origin::Create(GURL("http://www.example2.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key1", u"value1"));
+  EXPECT_EQ(1L, db_->Length(kOrigin2));
+
+  const url::Origin kOrigin3 =
+      url::Origin::Create(GURL("http://www.example3.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key1", u"value1"));
+  EXPECT_EQ(1L, db_->Length(kOrigin3));
+
+  const url::Origin kOrigin4 =
+      url::Origin::Create(GURL("http://www.example4.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key1", u"value1"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin4, u"key2", u"value2"));
+  EXPECT_EQ(2L, db_->Length(kOrigin4));
+
+  std::vector<url::Origin> origins;
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin2, kOrigin3, kOrigin4));
+
+  EXPECT_EQ(OperationResult::kSuccess, db_->Clear(kOrigin1));
+  EXPECT_EQ(0L, db_->Length(kOrigin1));
+
+  EXPECT_EQ(OperationResult::kSuccess, db_->Delete(kOrigin2, u"key1"));
+  EXPECT_EQ(0L, db_->Length(kOrigin2));
+
+  origins.clear();
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin3, kOrigin4));
+
+  // Release nonessential memory.
+  db_->TrimMemory();
+
+  // Check that the database is still intact.
+  origins.clear();
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->origin);
+  EXPECT_THAT(origins, ElementsAre(kOrigin3, kOrigin4));
+
+  EXPECT_EQ(1L, db_->Length(kOrigin3));
+  EXPECT_EQ(2L, db_->Length(kOrigin4));
+
+  EXPECT_EQ(db_->Get(kOrigin3, u"key1").data, u"value1");
+  EXPECT_EQ(db_->Get(kOrigin4, u"key1").data, u"value1");
+  EXPECT_EQ(db_->Get(kOrigin4, u"key2").data, u"value2");
+}
+
+TEST_P(SharedStorageDatabaseParamTest, MaxEntriesPerOrigin) {
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  EXPECT_EQ(1L, db_->Length(kOrigin1));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value2"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key3", u"value3"));
+  EXPECT_EQ(3L, db_->Length(kOrigin1));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key4", u"value4"));
+  EXPECT_EQ(4L, db_->Length(kOrigin1));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key5", u"value5"));
+  EXPECT_EQ(5L, db_->Length(kOrigin1));
+
+  // `kOrigin1` should have hit capacity, and hence this value will not be set.
+  EXPECT_EQ(OperationResult::kNoCapacity,
+            db_->Set(kOrigin1, u"key6", u"value6"));
+
+  EXPECT_EQ(5L, db_->Length(kOrigin1));
+  EXPECT_EQ(OperationResult::kSuccess, db_->Delete(kOrigin1, u"key5"));
+  EXPECT_EQ(4L, db_->Length(kOrigin1));
+
+  // There should now be capacity and the value will be set.
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key6", u"value6"));
+  EXPECT_EQ(5L, db_->Length(kOrigin1));
+}
+
+TEST_P(SharedStorageDatabaseParamTest, MaxStringLength) {
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  const std::u16string kLongString(kMaxStringLength, u'g');
+
+  // This value has the maximum allowed length.
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", kLongString));
+  EXPECT_EQ(1L, db_->Length(kOrigin1));
+
+  // Appending to the value would exceed the allowed length and so won't
+  // succeed.
+  EXPECT_EQ(OperationResult::kInvalidAppend,
+            db_->Append(kOrigin1, u"key1", u"h"));
+
+  EXPECT_EQ(1L, db_->Length(kOrigin1));
+
+  // This key has the maximum allowed length.
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, kLongString, u"value1"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+}
+
+}  // namespace storage
diff --git a/components/services/storage/shared_storage/shared_storage_options.cc b/components/services/storage/shared_storage/shared_storage_options.cc
new file mode 100644
index 0000000..fcbb0343
--- /dev/null
+++ b/components/services/storage/shared_storage/shared_storage_options.cc
@@ -0,0 +1,80 @@
+// Copyright 2021 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/services/storage/shared_storage/shared_storage_options.h"
+
+#include "base/bits.h"
+#include "third_party/blink/public/common/features.h"
+
+namespace storage {
+
+namespace {
+
+bool IsValidPageSize(int page_size) {
+  if (page_size < 512 || page_size > 65536)
+    return false;
+  return base::bits::IsPowerOfTwo(page_size);
+}
+
+}  // namespace
+
+// static
+std::unique_ptr<SharedStorageOptions> SharedStorageOptions::Create() {
+  return std::make_unique<SharedStorageOptions>(
+      blink::features::kMaxSharedStoragePageSize.Get(),
+      blink::features::kMaxSharedStorageCacheSize.Get(),
+      blink::features::kMaxSharedStorageEntriesPerOrigin.Get(),
+      blink::features::kMaxSharedStorageStringLength.Get(),
+      blink::features::kMaxSharedStorageInitTries.Get(),
+      blink::features::kMaxSharedStorageConsecutiveOperationErrorsAllowed.Get(),
+      blink::features::kSharedStorageStaleOriginPurgeInitialInterval.Get(),
+      blink::features::kSharedStorageStaleOriginPurgeRecurringInterval.Get(),
+      blink::features::kSharedStorageOriginStalenessThreshold.Get());
+}
+
+SharedStorageOptions::SharedStorageOptions(
+    int max_page_size,
+    int max_cache_size,
+    int max_entries_per_origin,
+    int max_string_length,
+    int max_init_tries,
+    int max_allowed_consecutive_errors,
+    base::TimeDelta stale_origin_purge_initial_interval,
+    base::TimeDelta stale_origin_purge_recurring_interval,
+    base::TimeDelta origin_staleness_threshold)
+    : max_page_size(max_page_size),
+      max_cache_size(max_cache_size),
+      max_entries_per_origin(max_entries_per_origin),
+      max_string_length(max_string_length),
+      max_init_tries(max_init_tries),
+      max_allowed_consecutive_errors(max_allowed_consecutive_errors),
+      stale_origin_purge_initial_interval(stale_origin_purge_initial_interval),
+      stale_origin_purge_recurring_interval(
+          stale_origin_purge_recurring_interval),
+      origin_staleness_threshold(origin_staleness_threshold) {
+  DCHECK(IsValidPageSize(max_page_size));
+}
+
+std::unique_ptr<SharedStorageDatabaseOptions>
+SharedStorageOptions::GetDatabaseOptions() {
+  return std::make_unique<SharedStorageDatabaseOptions>(
+      max_page_size, max_cache_size, max_entries_per_origin, max_string_length,
+      max_init_tries);
+}
+
+SharedStorageDatabaseOptions::SharedStorageDatabaseOptions(
+    int max_page_size,
+    int max_cache_size,
+    int max_entries_per_origin,
+    int max_string_length,
+    int max_init_tries)
+    : max_page_size(max_page_size),
+      max_cache_size(max_cache_size),
+      max_entries_per_origin(max_entries_per_origin),
+      max_string_length(max_string_length),
+      max_init_tries(max_init_tries) {
+  DCHECK(IsValidPageSize(max_page_size));
+}
+
+}  // namespace storage
diff --git a/components/services/storage/shared_storage/shared_storage_options.h b/components/services/storage/shared_storage/shared_storage_options.h
new file mode 100644
index 0000000..751662e
--- /dev/null
+++ b/components/services/storage/shared_storage/shared_storage_options.h
@@ -0,0 +1,104 @@
+// Copyright 2021 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_SERVICES_STORAGE_SHARED_STORAGE_SHARED_STORAGE_OPTIONS_H_
+#define COMPONENTS_SERVICES_STORAGE_SHARED_STORAGE_SHARED_STORAGE_OPTIONS_H_
+
+#include <memory>
+
+#include "base/time/time.h"
+
+namespace storage {
+
+struct SharedStorageDatabaseOptions;
+
+// Bundles Finch-configurable constants for the `SharedStorageManager`,
+// `AsyncSharedStorageDatabase`, and `SharedStorageDatabase` classes.
+struct SharedStorageOptions {
+  // The static `Create()` method accesses field trial params to populate one or
+  // more attributes, and so must be called on the main thread.
+  static std::unique_ptr<SharedStorageOptions> Create();
+
+  SharedStorageOptions(int max_page_size,
+                       int max_cache_size,
+                       int max_entries_per_origin,
+                       int max_string_length,
+                       int max_init_tries,
+                       int max_allowed_consecutive_errors,
+                       base::TimeDelta stale_origin_purge_initial_interval,
+                       base::TimeDelta stale_origin_purge_recurring_interval,
+                       base::TimeDelta origin_staleness_threshold);
+
+  // Creates a pointer to a smaller bundle of just the constants that need to
+  // be forwarded to `AsyncSharedStorageDatabase` and `SharedStorageDatabase`.
+  std::unique_ptr<SharedStorageDatabaseOptions> GetDatabaseOptions();
+
+  // The max size of a database page, in bytes. Must be a power of 2 between
+  // 512 and 65536 inclusive.
+  const int max_page_size;
+
+  // The max size of the database cache, in pages.
+  const int max_cache_size;
+
+  // The maximum number of entries allowed per origin.
+  const int max_entries_per_origin;
+
+  // The maximum allowed string length for each script key or script value.
+  const int max_string_length;
+
+  // The maximum number of times that `SharedStorageDatabase` will try to
+  // initialize the SQL database.
+  const int max_init_tries;
+
+  // Maximum number of consecutive operation errors allowed before the database
+  // is deleted and recreated.
+  const int max_allowed_consecutive_errors;
+
+  // The initial interval at which stale origins are purged.
+  const base::TimeDelta stale_origin_purge_initial_interval;
+
+  // The recurring interval at which stale origins are purged. May differ from
+  // the initial interval.
+  const base::TimeDelta stale_origin_purge_recurring_interval;
+
+  // The amount of time that an origin needs to be inactive in order for it to
+  // be deemed stale.
+  const base::TimeDelta origin_staleness_threshold;
+};
+
+// Bundles Finch-configurable constants for the `AsyncSharedStorageDatabase`
+// and `SharedStorageDatabase` classes. This smaller class is separate from the
+// larger `SharedStorageOptions` (which has the ability to create an instance of
+// `SharedStorageDatabaseOptions` from a subset of its members) so that the
+// smaller `SharedStorageDatabaseOptions` bundle can be read on an alternate
+// thread while the larger class's bundle can continue to be accessed on the
+// main thread.
+struct SharedStorageDatabaseOptions {
+  SharedStorageDatabaseOptions(int max_page_size,
+                               int max_cache_size,
+                               int max_entries_per_origin,
+                               int max_string_length,
+                               int max_init_tries);
+
+  // The max size of a database page, in bytes. Must be a power of 2 between
+  // 512 and 65536 inclusive.
+  const int max_page_size;
+
+  // The max size of the database cache, in pages.
+  const int max_cache_size;
+
+  // The maximum number of entries allowed per origin.
+  const int max_entries_per_origin;
+
+  // The maximum allowed string length for each script key or script value.
+  const int max_string_length;
+
+  // The maximum number of times that `SharedStorageDatabase` will try to
+  // initialize the SQL database.
+  const int max_init_tries;
+};
+
+}  // namespace storage
+
+#endif  // COMPONENTS_SERVICES_STORAGE_SHARED_STORAGE_SHARED_STORAGE_OPTIONS_H_
diff --git a/components/services/storage/shared_storage/shared_storage_test_utils.cc b/components/services/storage/shared_storage/shared_storage_test_utils.cc
new file mode 100644
index 0000000..2c13bbf
--- /dev/null
+++ b/components/services/storage/shared_storage/shared_storage_test_utils.cc
@@ -0,0 +1,369 @@
+// Copyright 2021 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/services/storage/shared_storage/shared_storage_test_utils.h"
+
+#include <queue>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/containers/contains.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/services/storage/public/mojom/storage_usage_info.mojom.h"
+#include "sql/database.h"
+#include "sql/test/test_helpers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace storage {
+
+TestDatabaseOperationReceiver::DBOperation::DBOperation(Type type)
+    : type(type) {
+  DCHECK(type == Type::DB_IS_OPEN || type == Type::DB_STATUS ||
+         type == Type::DB_DESTROY || type == Type::DB_TRIM_MEMORY ||
+         type == Type::DB_FETCH_ORIGINS);
+}
+
+TestDatabaseOperationReceiver::DBOperation::DBOperation(Type type,
+                                                        url::Origin origin)
+    : type(type), origin(std::move(origin)) {
+  DCHECK(type == Type::DB_LENGTH || type == Type::DB_CLEAR);
+}
+
+TestDatabaseOperationReceiver::DBOperation::DBOperation(
+    Type type,
+    url::Origin origin,
+    std::vector<std::u16string> params)
+    : type(type), origin(std::move(origin)), params(std::move(params)) {
+  DCHECK(type == Type::DB_GET || type == Type::DB_SET ||
+         type == Type::DB_APPEND || type == Type::DB_DELETE ||
+         type == Type::DB_KEY || type == Type::DB_OVERRIDE_TIME);
+}
+
+TestDatabaseOperationReceiver::DBOperation::DBOperation(
+    Type type,
+    std::vector<std::u16string> params)
+    : type(type), params(std::move(params)) {
+  DCHECK(type == Type::DB_PURGE_MATCHING || type == Type::DB_PURGE_STALE);
+}
+
+TestDatabaseOperationReceiver::DBOperation::~DBOperation() = default;
+
+TestDatabaseOperationReceiver::DBOperation::DBOperation(const DBOperation&) =
+    default;
+
+bool TestDatabaseOperationReceiver::DBOperation::operator==(
+    const DBOperation& operation) const {
+  if (type != operation.type || params != operation.params)
+    return false;
+
+  if (origin.opaque() && operation.origin.opaque())
+    return true;
+
+  return origin == operation.origin;
+}
+
+bool TestDatabaseOperationReceiver::DBOperation::operator!=(
+    const DBOperation& operation) const {
+  if (type != operation.type || params != operation.params)
+    return true;
+
+  if (origin.opaque() && operation.origin.opaque())
+    return false;
+
+  return origin != operation.origin;
+}
+
+std::string TestDatabaseOperationReceiver::DBOperation::Serialize() const {
+  std::string serialization(
+      base::StrCat({"type: ", base::NumberToString(static_cast<int>(type)),
+                    "; origin: ", origin.Serialize(), "; params: {"}));
+  for (int i = 0; i < static_cast<int>(params.size()) - 1; i++) {
+    serialization =
+        base::StrCat({serialization, base::UTF16ToUTF8(params[i]), ","});
+  }
+  serialization = params.empty()
+                      ? base::StrCat({serialization, "}"})
+                      : base::StrCat({serialization,
+                                      base::UTF16ToUTF8(params.back()), "}"});
+  return serialization;
+}
+
+TestDatabaseOperationReceiver::TestDatabaseOperationReceiver() = default;
+
+TestDatabaseOperationReceiver::~TestDatabaseOperationReceiver() = default;
+
+// static
+std::u16string TestDatabaseOperationReceiver::SerializeTime(base::Time time) {
+  return SerializeTimeDelta(time.ToDeltaSinceWindowsEpoch());
+}
+
+// static
+
+std::u16string TestDatabaseOperationReceiver::SerializeTimeDelta(
+    base::TimeDelta delta) {
+  return base::StrCat({base::NumberToString16(delta.InMicroseconds()), u"us"});
+}
+
+// static
+std::u16string TestDatabaseOperationReceiver::SerializeBool(bool b) {
+  return b ? u"true" : u"false";
+}
+
+// static
+std::u16string TestDatabaseOperationReceiver::SerializeSetBehavior(
+    SetBehavior behavior) {
+  return base::NumberToString16(static_cast<int>(behavior));
+}
+
+void TestDatabaseOperationReceiver::WaitForOperations() {
+  finished_ = false;
+  loop_.Run();
+  if (expected_operations_.empty())
+    Finish();
+}
+
+void TestDatabaseOperationReceiver::GetResultCallbackBase(
+    const DBOperation& current_operation,
+    GetResult* out_result,
+    GetResult result) {
+  DCHECK(out_result);
+  *out_result = std::move(result);
+
+  if (ExpectationsMet(current_operation) && loop_.running())
+    Finish();
+}
+
+base::OnceCallback<void(GetResult)>
+TestDatabaseOperationReceiver::MakeGetResultCallback(
+    const DBOperation& current_operation,
+    GetResult* out_result) {
+  return base::BindOnce(&TestDatabaseOperationReceiver::GetResultCallbackBase,
+                        base::Unretained(this), current_operation, out_result);
+}
+
+void TestDatabaseOperationReceiver::OperationResultCallbackBase(
+    const DBOperation& current_operation,
+    OperationResult* out_result,
+    OperationResult result) {
+  DCHECK(out_result);
+  *out_result = result;
+
+  if (ExpectationsMet(current_operation) && loop_.running())
+    Finish();
+}
+
+base::OnceCallback<void(OperationResult)>
+TestDatabaseOperationReceiver::MakeOperationResultCallback(
+    const DBOperation& current_operation,
+    OperationResult* out_result) {
+  return base::BindOnce(
+      &TestDatabaseOperationReceiver::OperationResultCallbackBase,
+      base::Unretained(this), current_operation, out_result);
+}
+
+void TestDatabaseOperationReceiver::IntCallbackBase(
+    const DBOperation& current_operation,
+    int* out_length,
+    int length) {
+  DCHECK(out_length);
+  *out_length = length;
+
+  if (ExpectationsMet(current_operation) && loop_.running())
+    Finish();
+}
+
+base::OnceCallback<void(int)> TestDatabaseOperationReceiver::MakeIntCallback(
+    const DBOperation& current_operation,
+    int* out_length) {
+  return base::BindOnce(&TestDatabaseOperationReceiver::IntCallbackBase,
+                        base::Unretained(this), current_operation, out_length);
+}
+
+void TestDatabaseOperationReceiver::BoolCallbackBase(
+    const DBOperation& current_operation,
+    bool* out_boolean,
+    bool boolean) {
+  DCHECK(out_boolean);
+  *out_boolean = boolean;
+
+  if (ExpectationsMet(current_operation) && loop_.running())
+    Finish();
+}
+
+base::OnceCallback<void(bool)> TestDatabaseOperationReceiver::MakeBoolCallback(
+    const DBOperation& current_operation,
+    bool* out_boolean) {
+  return base::BindOnce(&TestDatabaseOperationReceiver::BoolCallbackBase,
+                        base::Unretained(this), current_operation, out_boolean);
+}
+
+void TestDatabaseOperationReceiver::StatusCallbackBase(
+    const DBOperation& current_operation,
+    InitStatus* out_status,
+    InitStatus status) {
+  DCHECK(out_status);
+  *out_status = status;
+
+  if (ExpectationsMet(current_operation) && loop_.running())
+    Finish();
+}
+
+base::OnceCallback<void(InitStatus)>
+TestDatabaseOperationReceiver::MakeStatusCallback(
+    const DBOperation& current_operation,
+    InitStatus* out_status) {
+  return base::BindOnce(&TestDatabaseOperationReceiver::StatusCallbackBase,
+                        base::Unretained(this), current_operation, out_status);
+}
+
+void TestDatabaseOperationReceiver::InfosCallbackBase(
+    const DBOperation& current_operation,
+    std::vector<mojom::StorageUsageInfoPtr>* out_infos,
+    std::vector<mojom::StorageUsageInfoPtr> infos) {
+  DCHECK(out_infos);
+  *out_infos = std::move(infos);
+
+  if (ExpectationsMet(current_operation) && loop_.running())
+    Finish();
+}
+
+base::OnceCallback<void(std::vector<mojom::StorageUsageInfoPtr>)>
+TestDatabaseOperationReceiver::MakeInfosCallback(
+    const DBOperation& current_operation,
+    std::vector<mojom::StorageUsageInfoPtr>* out_infos) {
+  return base::BindOnce(&TestDatabaseOperationReceiver::InfosCallbackBase,
+                        base::Unretained(this), current_operation, out_infos);
+}
+
+void TestDatabaseOperationReceiver::OnceClosureBase(
+    const DBOperation& current_operation) {
+  if (ExpectationsMet(current_operation) && loop_.running())
+    Finish();
+}
+
+base::OnceClosure TestDatabaseOperationReceiver::MakeOnceClosure(
+    const DBOperation& current_operation) {
+  return base::BindOnce(&TestDatabaseOperationReceiver::OnceClosureBase,
+                        base::Unretained(this), current_operation);
+}
+
+bool TestDatabaseOperationReceiver::ExpectationsMet(
+    const DBOperation& current_operation) {
+  EXPECT_FALSE(expected_operations_.empty());
+
+  if (expected_operations_.empty())
+    return false;
+
+  EXPECT_EQ(expected_operations_.front(), current_operation)
+      << "expected operation: " << expected_operations_.front().Serialize()
+      << std::endl
+      << "actual operation: " << current_operation.Serialize() << std::endl;
+
+  if (expected_operations_.front() != current_operation) {
+    return false;
+  } else {
+    expected_operations_.pop();
+    return expected_operations_.empty();
+  }
+}
+
+void TestDatabaseOperationReceiver::Finish() {
+  finished_ = true;
+  loop_.Quit();
+}
+
+OriginMatcherFunctionUtility::OriginMatcherFunctionUtility() = default;
+OriginMatcherFunctionUtility::~OriginMatcherFunctionUtility() = default;
+
+OriginMatcherFunction OriginMatcherFunctionUtility::MakeMatcherFunction(
+    std::vector<url::Origin> origins_to_match) {
+  return base::BindRepeating(
+      [](std::vector<url::Origin> origins_to_match, const url::Origin& origin,
+         SpecialStoragePolicy* policy) {
+        return base::Contains(origins_to_match, origin);
+      },
+      origins_to_match);
+}
+
+OriginMatcherFunction OriginMatcherFunctionUtility::MakeMatcherFunction(
+    std::vector<std::string> origin_strs_to_match) {
+  std::vector<url::Origin> origins_to_match;
+  for (const auto& str : origin_strs_to_match)
+    origins_to_match.push_back(url::Origin::Create(GURL(str)));
+  return MakeMatcherFunction(origins_to_match);
+}
+
+size_t OriginMatcherFunctionUtility::RegisterMatcherFunction(
+    std::vector<url::Origin> origins_to_match) {
+  matcher_table_.emplace_back(MakeMatcherFunction(origins_to_match));
+  return matcher_table_.size() - 1;
+}
+
+OriginMatcherFunction OriginMatcherFunctionUtility::TakeMatcherFunctionForId(
+    size_t id) {
+  DCHECK_LT(id, matcher_table_.size());
+  return std::move(matcher_table_[id]);
+}
+
+std::vector<SharedStorageWrappedBool> GetSharedStorageWrappedBools() {
+  return std::vector<SharedStorageWrappedBool>({{true}, {false}});
+}
+
+std::string PrintToString(const SharedStorageWrappedBool& b) {
+  return b.in_memory_only ? "InMemoryOnly" : "FileBacked";
+}
+
+std::vector<PurgeMatchingOriginsParams> GetPurgeMatchingOriginsParams() {
+  return std::vector<PurgeMatchingOriginsParams>(
+      {{true, true}, {true, false}, {false, true}, {false, false}});
+}
+
+std::string PrintToString(const PurgeMatchingOriginsParams& p) {
+  return base::StrCat({(p.in_memory_only ? "InMemoryOnly" : "FileBacked"),
+                       "_With", (p.perform_storage_cleanup ? "" : "out"),
+                       "Cleanup"});
+}
+
+void VerifySharedStorageTablesAndColumns(sql::Database& db) {
+  // `meta`, `values_mapping`, and `per_origin_mapping`.
+  EXPECT_EQ(3u, sql::test::CountSQLTables(&db));
+
+  // Implicit index on `meta` and `per_origin_mapping_last_used_time_idx`.
+  EXPECT_EQ(2u, sql::test::CountSQLIndices(&db));
+
+  // `key` and `value`.
+  EXPECT_EQ(2u, sql::test::CountTableColumns(&db, "meta"));
+
+  // `context_origin`, `script_key`, and `script_value`.
+  EXPECT_EQ(3u, sql::test::CountTableColumns(&db, "values_mapping"));
+
+  // `context_origin`, `last_used_time`, and `length`.
+  EXPECT_EQ(3u, sql::test::CountTableColumns(&db, "per_origin_mapping"));
+}
+
+bool GetTestDataSharedStorageDir(base::FilePath* dir) {
+  if (!base::PathService::Get(base::DIR_SOURCE_ROOT, dir))
+    return false;
+  *dir = dir->AppendASCII("components");
+  *dir = dir->AppendASCII("test");
+  *dir = dir->AppendASCII("data");
+  *dir = dir->AppendASCII("storage");
+  return true;
+}
+
+bool CreateDatabaseFromSQL(const base::FilePath& db_path,
+                           const char* ascii_path) {
+  base::FilePath dir;
+  if (!GetTestDataSharedStorageDir(&dir))
+    return false;
+  return sql::test::CreateDatabaseFromSQL(db_path, dir.AppendASCII(ascii_path));
+}
+
+}  // namespace storage
diff --git a/components/services/storage/shared_storage/shared_storage_test_utils.h b/components/services/storage/shared_storage/shared_storage_test_utils.h
new file mode 100644
index 0000000..b518d06
--- /dev/null
+++ b/components/services/storage/shared_storage/shared_storage_test_utils.h
@@ -0,0 +1,210 @@
+// Copyright 2021 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_SERVICES_STORAGE_SHARED_STORAGE_SHARED_STORAGE_TEST_UTILS_H_
+#define COMPONENTS_SERVICES_STORAGE_SHARED_STORAGE_SHARED_STORAGE_TEST_UTILS_H_
+
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "components/services/storage/public/mojom/storage_usage_info.mojom-forward.h"
+#include "components/services/storage/shared_storage/shared_storage_database.h"
+#include "url/origin.h"
+
+namespace base {
+class FilePath;
+}  // namespace base
+
+namespace sql {
+class Database;
+}  // namespace sql
+
+namespace storage {
+
+using OriginMatcherFunction = SharedStorageDatabase::OriginMatcherFunction;
+using InitStatus = SharedStorageDatabase::InitStatus;
+using SetBehavior = SharedStorageDatabase::SetBehavior;
+using OperationResult = SharedStorageDatabase::OperationResult;
+using GetResult = SharedStorageDatabase::GetResult;
+
+// Helper class for testing async operations, accessible here for unit tests
+// of both `AsyncSharedStorageDatabase` and `SharedStorageManager`.
+class TestDatabaseOperationReceiver {
+ public:
+  struct DBOperation {
+    enum class Type {
+      DB_DESTROY = 0,
+      DB_TRIM_MEMORY = 1,
+      DB_GET = 2,
+      DB_SET = 3,
+      DB_APPEND = 4,
+      DB_DELETE = 5,
+      DB_CLEAR = 6,
+      DB_LENGTH = 7,
+      DB_KEY = 8,
+      DB_PURGE_MATCHING = 9,
+      DB_PURGE_STALE = 10,
+      DB_FETCH_ORIGINS = 11,
+      DB_IS_OPEN = 12,
+      DB_STATUS = 13,
+      DB_OVERRIDE_TIME = 14,
+    } type;
+    url::Origin origin;
+    std::vector<std::u16string> params;
+    explicit DBOperation(Type type);
+    DBOperation(Type type, url::Origin origin);
+    DBOperation(Type type,
+                url::Origin origin,
+                std::vector<std::u16string> params);
+    DBOperation(Type type, std::vector<std::u16string> params);
+    DBOperation(const DBOperation&);
+    ~DBOperation();
+    bool operator==(const DBOperation& operation) const;
+    bool operator!=(const DBOperation& operation) const;
+    std::string Serialize() const;
+  };
+
+  TestDatabaseOperationReceiver();
+
+  ~TestDatabaseOperationReceiver();
+
+  // For serializing parameters to insert into `params` when creating a
+  // `DBOperation` struct.
+  static std::u16string SerializeTime(base::Time time);
+  static std::u16string SerializeTimeDelta(base::TimeDelta delta);
+  static std::u16string SerializeBool(bool b);
+  static std::u16string SerializeSetBehavior(SetBehavior behavior);
+
+  bool is_finished() const { return finished_; }
+
+  void set_expected_operations(std::queue<DBOperation> expected_operations) {
+    expected_operations_ = std::move(expected_operations);
+  }
+
+  void WaitForOperations();
+
+  void GetResultCallbackBase(const DBOperation& current_operation,
+                             GetResult* out_result,
+                             GetResult result);
+  base::OnceCallback<void(GetResult)> MakeGetResultCallback(
+      const DBOperation& current_operation,
+      GetResult* out_result);
+
+  void OperationResultCallbackBase(const DBOperation& current_operation,
+                                   OperationResult* out_result,
+                                   OperationResult result);
+  base::OnceCallback<void(OperationResult)> MakeOperationResultCallback(
+      const DBOperation& current_operation,
+      OperationResult* out_result);
+
+  void IntCallbackBase(const DBOperation& current_operation,
+                       int* out_length,
+                       int length);
+  base::OnceCallback<void(int)> MakeIntCallback(
+      const DBOperation& current_operation,
+      int* out_length);
+
+  void BoolCallbackBase(const DBOperation& current_operation,
+                        bool* out_boolean,
+                        bool boolean);
+  base::OnceCallback<void(bool)> MakeBoolCallback(
+      const DBOperation& current_operation,
+      bool* out_boolean);
+
+  void StatusCallbackBase(const DBOperation& current_operation,
+                          InitStatus* out_status,
+                          InitStatus status);
+  base::OnceCallback<void(InitStatus)> MakeStatusCallback(
+      const DBOperation& current_operation,
+      InitStatus* out_status);
+
+  void InfosCallbackBase(const DBOperation& current_operation,
+                         std::vector<mojom::StorageUsageInfoPtr>* out_infos,
+                         std::vector<mojom::StorageUsageInfoPtr> infos);
+  base::OnceCallback<void(std::vector<mojom::StorageUsageInfoPtr>)>
+  MakeInfosCallback(const DBOperation& current_operation,
+                    std::vector<mojom::StorageUsageInfoPtr>* out_infos);
+
+  void OnceClosureBase(const DBOperation& current_operation);
+  base::OnceClosure MakeOnceClosure(const DBOperation& current_operation);
+
+ private:
+  bool ExpectationsMet(const DBOperation& current_operation);
+  void Finish();
+
+  base::RunLoop loop_;
+  bool finished_ = true;
+  std::queue<DBOperation> expected_operations_;
+};
+
+class OriginMatcherFunctionUtility {
+ public:
+  OriginMatcherFunctionUtility();
+  ~OriginMatcherFunctionUtility();
+
+  [[nodiscard]] static OriginMatcherFunction MakeMatcherFunction(
+      std::vector<url::Origin> origins_to_match);
+
+  [[nodiscard]] static OriginMatcherFunction MakeMatcherFunction(
+      std::vector<std::string> origin_strs_to_match);
+
+  [[nodiscard]] size_t RegisterMatcherFunction(
+      std::vector<url::Origin> origins_to_match);
+
+  [[nodiscard]] OriginMatcherFunction TakeMatcherFunctionForId(size_t id);
+
+  [[nodiscard]] bool is_empty() const { return matcher_table_.empty(); }
+
+  [[nodiscard]] size_t size() const { return matcher_table_.size(); }
+
+ private:
+  std::vector<OriginMatcherFunction> matcher_table_;
+};
+
+// Wraps a bool indicating if the database is in memory only,
+// for the purpose of customizing a `PrintToString()` method below, which will
+// be used in the parameterized test names via
+// `testing::PrintToStringParamName()`.
+struct SharedStorageWrappedBool {
+  bool in_memory_only;
+};
+
+// Wraps bools indicating if the database is in memory only and if storage
+// cleanup should be performed after purging, for the purpose of customizing a
+// `PrintToString()` method below, which will be used in the parameterized test
+// names via `testing::PrintToStringParamName()`.
+struct PurgeMatchingOriginsParams {
+  bool in_memory_only;
+  bool perform_storage_cleanup;
+};
+
+[[nodiscard]] std::vector<SharedStorageWrappedBool>
+GetSharedStorageWrappedBools();
+
+// Used by `testing::PrintToStringParamName()`.
+[[nodiscard]] std::string PrintToString(const SharedStorageWrappedBool& b);
+
+[[nodiscard]] std::vector<PurgeMatchingOriginsParams>
+GetPurgeMatchingOriginsParams();
+
+// Used by testing::PrintToStringParamName().
+[[nodiscard]] std::string PrintToString(const PurgeMatchingOriginsParams& p);
+
+// Verify that the up-to-date SQL Shared Storage database has the expected
+// tables and columns. Functional tests only check whether the things which
+// should be there are, but do not check if extraneous items are
+// present. Any extraneous items have the potential to interact
+// negatively with future schema changes.
+void VerifySharedStorageTablesAndColumns(sql::Database& db);
+
+[[nodiscard]] bool GetTestDataSharedStorageDir(base::FilePath* dir);
+
+[[nodiscard]] bool CreateDatabaseFromSQL(const base::FilePath& db_path,
+                                         const char* ascii_path);
+
+}  // namespace storage
+
+#endif  // COMPONENTS_SERVICES_STORAGE_SHARED_STORAGE_SHARED_STORAGE_TEST_UTILS_H_
diff --git a/components/signin/ios/browser/account_consistency_service.h b/components/signin/ios/browser/account_consistency_service.h
index 6f72ce6f..04b9fa5 100644
--- a/components/signin/ios/browser/account_consistency_service.h
+++ b/components/signin/ios/browser/account_consistency_service.h
@@ -51,7 +51,7 @@
   // Sets the handler for |web_state| that reacts on Gaia responses with the
   // X-Chrome-Manage-Accounts header and notifies |delegate|.
   void SetWebStateHandler(web::WebState* web_state,
-                          id<ManageAccountsDelegate> delegate);
+                          ManageAccountsDelegate* delegate);
   // Removes the handler associated with |web_state|.
   void RemoveWebStateHandler(web::WebState* web_state);
 
diff --git a/components/signin/ios/browser/account_consistency_service.mm b/components/signin/ios/browser/account_consistency_service.mm
index de8d047f..03de401f 100644
--- a/components/signin/ios/browser/account_consistency_service.mm
+++ b/components/signin/ios/browser/account_consistency_service.mm
@@ -107,7 +107,7 @@
                             AccountConsistencyService* service,
                             AccountReconcilor* account_reconcilor,
                             signin::IdentityManager* identity_manager,
-                            id<ManageAccountsDelegate> delegate);
+                            ManageAccountsDelegate* delegate);
 
   void WebStateDestroyed(web::WebState* web_state) override;
 
@@ -145,7 +145,7 @@
   AccountReconcilor* account_reconcilor_;                   // Weak.
   signin::IdentityManager* identity_manager_;
   web::WebState* web_state_;
-  __weak id<ManageAccountsDelegate> delegate_;
+  ManageAccountsDelegate* delegate_;  // Weak.
   base::WeakPtrFactory<AccountConsistencyHandler> weak_ptr_factory_;
 };
 
@@ -154,7 +154,7 @@
     AccountConsistencyService* service,
     AccountReconcilor* account_reconcilor,
     signin::IdentityManager* identity_manager,
-    id<ManageAccountsDelegate> delegate)
+    ManageAccountsDelegate* delegate)
     : web::WebStatePolicyDecider(web_state),
       account_consistency_service_(service),
       account_reconcilor_(account_reconcilor),
@@ -232,7 +232,8 @@
       GURL continue_url = GURL(params.continue_url);
       DLOG_IF(ERROR, !params.continue_url.empty() && !continue_url.is_valid())
           << "Invalid continuation URL: \"" << continue_url << "\"";
-      [delegate_ onGoIncognito:continue_url];
+      if (delegate_)
+        delegate_->OnGoIncognito(continue_url);
       break;
     }
     case signin::GAIA_SERVICE_TYPE_SIGNUP:
@@ -253,11 +254,13 @@
           return;
         }
       }
-      [delegate_ onAddAccount];
+      if (delegate_)
+        delegate_->OnAddAccount();
       break;
     case signin::GAIA_SERVICE_TYPE_SIGNOUT:
     case signin::GAIA_SERVICE_TYPE_DEFAULT:
-      [delegate_ onManageAccounts];
+      if (delegate_)
+        delegate_->OnManageAccounts();
       break;
     case signin::GAIA_SERVICE_TYPE_NONE:
       NOTREACHED();
@@ -281,13 +284,15 @@
     // is not in an inconsistent state (where the identities on the device
     // are different than those on the web). Fallback to asking the user to
     // add an account.
-    [delegate_ onAddAccount];
+    if (delegate_)
+      delegate_->OnAddAccount();
     return;
   }
   web_state_->OpenURL(web::WebState::OpenURLParams(
       url, web::Referrer(), WindowOpenDisposition::CURRENT_TAB,
       ui::PAGE_TRANSITION_AUTO_TOPLEVEL, false));
-  [delegate_ onRestoreGaiaCookies];
+  if (delegate_)
+    delegate_->OnRestoreGaiaCookies();
   LogIOSGaiaCookiesState(
       GaiaCookieStateOnSignedInNavigation::kGaiaCookieRestoredOnShowInfobar);
 }
@@ -303,9 +308,9 @@
     return;
   }
 
-  if (show_consistency_web_signin_ &&
+  if (delegate_ && show_consistency_web_signin_ &&
       gaia::IsGaiaSignonRealm(url.DeprecatedGetOriginAsURL())) {
-    [delegate_ onShowConsistencyPromo:url webState:web_state];
+    delegate_->OnShowConsistencyPromo(url, web_state);
   }
   show_consistency_web_signin_ = false;
 }
@@ -397,7 +402,7 @@
 
 void AccountConsistencyService::SetWebStateHandler(
     web::WebState* web_state,
-    id<ManageAccountsDelegate> delegate) {
+    ManageAccountsDelegate* delegate) {
   DCHECK(!is_shutdown_) << "SetWebStateHandler called after Shutdown";
   DCHECK(handlers_map_.find(web_state) == handlers_map_.end());
   handlers_map_.insert(std::make_pair(
diff --git a/components/signin/ios/browser/account_consistency_service_unittest.mm b/components/signin/ios/browser/account_consistency_service_unittest.mm
index 21906c9..4621cd6 100644
--- a/components/signin/ios/browser/account_consistency_service_unittest.mm
+++ b/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -44,6 +44,8 @@
 #error "This file requires ARC support."
 #endif
 
+using testing::NiceMock;
+
 namespace {
 // Fake identity email.
 const char* kFakeEmail = "janedoe@gmail.com";
@@ -94,6 +96,34 @@
   MOCK_METHOD1(OnReceivedManageAccountsResponse, void(signin::GAIAServiceType));
 };
 
+// Fake delegate implementation; all it does it count delegate calls.
+class FakeManageAccountsDelegate : public ManageAccountsDelegate {
+ public:
+  FakeManageAccountsDelegate() {}
+  ~FakeManageAccountsDelegate() override {}
+
+  void OnRestoreGaiaCookies() override { restore_cookies_call_count_++; }
+  void OnManageAccounts() override { manage_accounts_call_count_++; }
+  void OnAddAccount() override { add_account_call_count_++; }
+  void OnShowConsistencyPromo(const GURL& url,
+                              web::WebState* webState) override {
+    show_promo_call_count_++;
+  }
+  void OnGoIncognito(const GURL& url) override { go_incognito_call_count_++; }
+
+  int total_call_count() {
+    return restore_cookies_call_count_ + manage_accounts_call_count_ +
+           add_account_call_count_ + show_promo_call_count_ +
+           go_incognito_call_count_;
+  }
+
+  int restore_cookies_call_count_ = 0;
+  int manage_accounts_call_count_ = 0;
+  int add_account_call_count_ = 0;
+  int show_promo_call_count_ = 0;
+  int go_incognito_call_count_ = 0;
+};
+
 // FakeWebState that allows control over its policy decider.
 class FakeWebState : public web::FakeWebState {
  public:
@@ -155,8 +185,9 @@
         false /* restore_session */);
     cookie_settings_ = new content_settings::CookieSettings(settings_map_.get(),
                                                             &prefs_, false, "");
+    // Use a NiceMock here to suppress "uninteresting call" warnings.
     account_reconcilor_ =
-        std::make_unique<MockAccountReconcilor>(signin_client_.get());
+        std::make_unique<NiceMock<MockAccountReconcilor>>(signin_client_.get());
     ResetAccountConsistencyService();
   }
 
@@ -230,7 +261,7 @@
 
   // Navigation APIs.
   void SimulateNavigateToURL(NSURLResponse* response,
-                             id<ManageAccountsDelegate> delegate) {
+                             ManageAccountsDelegate* delegate) {
     SimulateNavigateToURL(response, delegate,
                           web::PageLoadCompletionStatus::SUCCESS,
                           /* expected_allowed_response=*/true);
@@ -238,15 +269,14 @@
 
   void SimulateNavigateToURLWithPageLoadFailure(
       NSURLResponse* response,
-      id<ManageAccountsDelegate> delegate) {
+      ManageAccountsDelegate* delegate) {
     SimulateNavigateToURL(response, delegate,
                           web::PageLoadCompletionStatus::FAILURE,
                           /* expected_allowed_response=*/true);
   }
 
-  void SimulateNavigateToURLWithInterruption(
-      NSURLResponse* response,
-      id<ManageAccountsDelegate> delegate) {
+  void SimulateNavigateToURLWithInterruption(NSURLResponse* response,
+                                             ManageAccountsDelegate* delegate) {
     SimulateNavigateToURL(response, delegate,
                           web::PageLoadCompletionStatus::SUCCESS,
                           /* expected_allowed_response=*/false);
@@ -283,7 +313,7 @@
                                   base::OnceCallback<void(uint)>());
   }
 
-  void SetWebStateHandler(id<ManageAccountsDelegate> delegate) {
+  void SetWebStateHandler(ManageAccountsDelegate* delegate) {
     // If we have already added the |web_state_| with a previous |delegate|,
     // remove it to enforce a one-to-one mapping between web state handler and
     // web state.
@@ -301,6 +331,7 @@
   web::FakeBrowserState browser_state_;
   sync_preferences::TestingPrefServiceSyncable prefs_;
   FakeWebState web_state_;
+  FakeManageAccountsDelegate delegate_;
   network::TestURLLoaderFactory test_url_loader_factory_;
 
   std::unique_ptr<signin::IdentityTestEnvironment> identity_test_env_;
@@ -309,7 +340,7 @@
 
  private:
   void SimulateNavigateToURL(NSURLResponse* response,
-                             id<ManageAccountsDelegate> delegate,
+                             ManageAccountsDelegate* delegate,
                              web::PageLoadCompletionStatus page_status,
                              bool expect_allowed_response) {
     SetWebStateHandler(delegate);
@@ -361,8 +392,6 @@
   CheckDomainHasChromeConnectedCookie(kYoutubeDomain);
   CheckNoChromeConnectedCookieForDomain(kCountryGoogleDomain);
 
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
   NSDictionary* headers = [NSDictionary dictionary];
 
   NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
@@ -371,7 +400,7 @@
        HTTPVersion:@"HTTP/1.1"
       headerFields:headers];
 
-  SimulateNavigateToURL(response, delegate);
+  SimulateNavigateToURL(response, &delegate_);
 
   // Check that cookies was also added for |kCountryGoogleDomain|.
   CheckDomainHasChromeConnectedCookie(kGoogleDomain);
@@ -393,8 +422,6 @@
 // Tests that the X-Chrome-Manage-Accounts header is ignored unless it comes
 // from Gaia signon realm.
 TEST_F(AccountConsistencyServiceTest, ChromeManageAccountsNotOnGaia) {
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
   NSDictionary* headers =
       [NSDictionary dictionaryWithObject:@"action=DEFAULT"
                                   forKey:@"X-Chrome-Manage-Accounts"];
@@ -404,17 +431,13 @@
        HTTPVersion:@"HTTP/1.1"
       headerFields:headers];
 
-  SimulateNavigateToURL(response, delegate);
-
-  EXPECT_OCMOCK_VERIFY(delegate);
+  SimulateNavigateToURL(response, &delegate_);
+  EXPECT_EQ(0, delegate_.total_call_count());
 }
 
 // Tests that navigation to Gaia signon realm with no X-Chrome-Manage-Accounts
 // header in the response are simply untouched.
 TEST_F(AccountConsistencyServiceTest, ChromeManageAccountsNoHeader) {
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
-
   NSDictionary* headers = [NSDictionary dictionary];
   NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
        initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"]
@@ -422,20 +445,14 @@
        HTTPVersion:@"HTTP/1.1"
       headerFields:headers];
 
-  SimulateNavigateToURL(response, delegate);
-
-  EXPECT_OCMOCK_VERIFY(delegate);
+  SimulateNavigateToURL(response, &delegate_);
+  EXPECT_EQ(0, delegate_.total_call_count());
 }
 
 // Tests that the ManageAccountsDelegate is notified when a navigation on Gaia
 // signon realm returns with a X-Chrome-Manage-Accounts header with action
 // DEFAULT.
 TEST_F(AccountConsistencyServiceTest, ChromeManageAccountsDefault) {
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
-  // Default action is |onManageAccounts|.
-  [[delegate expect] onManageAccounts];
-
   NSDictionary* headers =
       [NSDictionary dictionaryWithObject:@"action=DEFAULT"
                                   forKey:@"X-Chrome-Manage-Accounts"];
@@ -448,19 +465,15 @@
                                         signin::GAIA_SERVICE_TYPE_DEFAULT))
       .Times(1);
 
-  SimulateNavigateToURLWithInterruption(response, delegate);
+  SimulateNavigateToURLWithInterruption(response, &delegate_);
 
-  EXPECT_OCMOCK_VERIFY(delegate);
+  EXPECT_EQ(1, delegate_.total_call_count());
+  EXPECT_EQ(1, delegate_.manage_accounts_call_count_);
 }
 
 // Tests that the ManageAccountsDelegate is notified when a navigation on Gaia
 // signon realm returns with a X-Auto-Login header.
 TEST_F(AccountConsistencyServiceTest, ChromeShowConsistencyPromo) {
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
-  [[[delegate expect] ignoringNonObjectArgs] onShowConsistencyPromo:GURL()
-                                                           webState:nullptr];
-
   NSDictionary* headers = [NSDictionary dictionaryWithObject:@"args=unused"
                                                       forKey:@"X-Auto-Login"];
   NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
@@ -469,19 +482,15 @@
        HTTPVersion:@"HTTP/1.1"
       headerFields:headers];
 
-  SimulateNavigateToURL(response, delegate);
+  SimulateNavigateToURL(response, &delegate_);
 
-  EXPECT_OCMOCK_VERIFY(delegate);
+  EXPECT_EQ(1, delegate_.total_call_count());
+  EXPECT_EQ(1, delegate_.show_promo_call_count_);
 }
 
 // Tests that the consistency promo is not displayed when a page fails to load.
 TEST_F(AccountConsistencyServiceTest,
        ChromeNotShowConsistencyPromoOnPageLoadFailure) {
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
-  [[[delegate reject] ignoringNonObjectArgs] onShowConsistencyPromo:GURL()
-                                                           webState:nullptr];
-
   NSDictionary* headers = [NSDictionary dictionaryWithObject:@"args=unused"
                                                       forKey:@"X-Auto-Login"];
   NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
@@ -490,21 +499,14 @@
        HTTPVersion:@"HTTP/1.1"
       headerFields:headers];
 
-  SimulateNavigateToURLWithPageLoadFailure(response, delegate);
-
-  EXPECT_OCMOCK_VERIFY(delegate);
+  SimulateNavigateToURLWithPageLoadFailure(response, &delegate_);
+  EXPECT_EQ(0, delegate_.total_call_count());
 }
 
 // Tests that the consistency promo is not displayed when a page fails to load
 // and user chooses another action.
 TEST_F(AccountConsistencyServiceTest,
        ChromeNotShowConsistencyPromoOnPageLoadFailureRedirect) {
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
-  [[delegate expect] onAddAccount];
-  [[[delegate reject] ignoringNonObjectArgs] onShowConsistencyPromo:GURL()
-                                                           webState:nullptr];
-
   EXPECT_CALL(*account_reconcilor_, OnReceivedManageAccountsResponse(
                                         signin::GAIA_SERVICE_TYPE_ADDSESSION));
 
@@ -516,7 +518,7 @@
        HTTPVersion:@"HTTP/1.1"
       headerFields:headers];
 
-  SimulateNavigateToURLWithPageLoadFailure(responseSignin, delegate);
+  SimulateNavigateToURLWithPageLoadFailure(responseSignin, &delegate_);
 
   NSDictionary* headersAddAccount =
       [NSDictionary dictionaryWithObject:@"action=ADDSESSION"
@@ -527,19 +529,17 @@
        HTTPVersion:@"HTTP/1.1"
       headerFields:headersAddAccount];
 
-  SimulateNavigateToURLWithInterruption(responseAddAccount, delegate);
+  SimulateNavigateToURLWithInterruption(responseAddAccount, &delegate_);
 
-  EXPECT_OCMOCK_VERIFY(delegate);
+  EXPECT_EQ(1, delegate_.total_call_count());
+  EXPECT_EQ(1, delegate_.add_account_call_count_);
+  EXPECT_EQ(0, delegate_.show_promo_call_count_);
 }
 
 // Tests that the ManageAccountsDelegate is notified when a navigation on Gaia
 // signon realm returns with a X-Chrome-Manage-Accounts header with ADDSESSION
 // action.
 TEST_F(AccountConsistencyServiceTest, ChromeManageAccountsShowAddAccount) {
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
-  [[delegate expect] onAddAccount];
-
   NSDictionary* headers =
       [NSDictionary dictionaryWithObject:@"action=ADDSESSION"
                                   forKey:@"X-Chrome-Manage-Accounts"];
@@ -552,9 +552,9 @@
                                         signin::GAIA_SERVICE_TYPE_ADDSESSION))
       .Times(1);
 
-  SimulateNavigateToURLWithInterruption(response, delegate);
-
-  EXPECT_OCMOCK_VERIFY(delegate);
+  SimulateNavigateToURLWithInterruption(response, &delegate_);
+  EXPECT_EQ(1, delegate_.total_call_count());
+  EXPECT_EQ(1, delegate_.add_account_call_count_);
 }
 
 // Tests that domains with cookie are correctly loaded from the prefs on service
@@ -619,8 +619,6 @@
 TEST_F(AccountConsistencyServiceTest, SetChromeConnectedCookie) {
   SignIn();
 
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
   NSDictionary* headers = [NSDictionary dictionary];
 
   // HTTP response URL is eligible for Mirror (the test does not use google.com
@@ -631,10 +629,10 @@
        HTTPVersion:@"HTTP/1.1"
       headerFields:headers];
 
-  SimulateNavigateToURL(response, delegate);
+  SimulateNavigateToURL(response, &delegate_);
   SimulateExternalSourceRemovesAllGoogleDomainCookies();
 
-  SimulateNavigateToURL(response, delegate);
+  SimulateNavigateToURL(response, &delegate_);
 
   CheckDomainHasChromeConnectedCookie(kGoogleDomain);
   CheckDomainHasChromeConnectedCookie(kYoutubeDomain);
@@ -645,10 +643,6 @@
 TEST_F(AccountConsistencyServiceTest, GAIACookieMissingOnSignin) {
   SignIn();
 
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
-  [[delegate expect] onAddAccount];
-
   NSDictionary* headers =
       [NSDictionary dictionaryWithObject:@"action=ADDSESSION"
                                   forKey:@"X-Chrome-Manage-Accounts"];
@@ -661,17 +655,18 @@
                                         signin::GAIA_SERVICE_TYPE_ADDSESSION))
       .Times(2);
 
-  SimulateNavigateToURL(response, delegate);
+  SimulateNavigateToURL(response, &delegate_);
   base::HistogramTester histogram_tester;
   histogram_tester.ExpectTotalCount(kGAIACookieOnNavigationHistogram, 0);
 
   SimulateExternalSourceRemovesAllGoogleDomainCookies();
 
   // Gaia cookie is not restored due to one-hour time restriction.
-  SimulateNavigateToURLWithInterruption(response, delegate);
+  SimulateNavigateToURLWithInterruption(response, &delegate_);
   histogram_tester.ExpectTotalCount(kGAIACookieOnNavigationHistogram, 1);
 
-  EXPECT_OCMOCK_VERIFY(delegate);
+  EXPECT_EQ(1, delegate_.total_call_count());
+  EXPECT_EQ(1, delegate_.add_account_call_count_);
 }
 
 // Ensures that set and remove cookie operations are handled in the order
@@ -716,9 +711,6 @@
 // is signed out and navigating to google.com.
 TEST_F(AccountConsistencyServiceTest,
        SetChromeConnectedCookiesSignedOutGoogleVisitor) {
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
-
   NSDictionary* headers =
       [NSDictionary dictionaryWithObject:@"action=ADDSESSION"
                                   forKey:@"X-Chrome-Manage-Accounts"];
@@ -730,21 +722,16 @@
 
   CheckNoChromeConnectedCookies();
 
-  SimulateNavigateToURL(response, delegate);
+  SimulateNavigateToURL(response, &delegate_);
 
   CheckNoChromeConnectedCookies();
-  EXPECT_OCMOCK_VERIFY(delegate);
+  EXPECT_EQ(0, delegate_.total_call_count());
 }
 
 // Ensures that CHROME_CONNECTED cookies are not set when the user is signed out
 // after the sign-in promo is shown.
 TEST_F(AccountConsistencyServiceTest,
        SetChromeConnectedCookiesSignedOutGaiaVisitor) {
-  id delegate =
-      [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
-  [[[delegate expect] ignoringNonObjectArgs] onShowConsistencyPromo:GURL()
-                                                           webState:nullptr];
-
   NSDictionary* headers = [NSDictionary dictionaryWithObject:@"args=unused"
                                                       forKey:@"X-Auto-Login"];
   NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
@@ -753,7 +740,7 @@
        HTTPVersion:@"HTTP/1.1"
       headerFields:headers];
 
-  SetWebStateHandler(delegate);
+  SetWebStateHandler(&delegate_);
   EXPECT_TRUE(web_state_.ShouldAllowResponse(response,
                                              /* for_main_frame = */ true));
 
@@ -761,7 +748,8 @@
   web_state_.OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS);
 
   CheckNoChromeConnectedCookies();
-  EXPECT_OCMOCK_VERIFY(delegate);
+  EXPECT_EQ(1, delegate_.total_call_count());
+  EXPECT_EQ(1, delegate_.show_promo_call_count_);
 }
 
 TEST_F(AccountConsistencyServiceTest, SetGaiaCookieUpdateBeforeDelay) {
@@ -781,7 +769,7 @@
   // Advance clock, but stay within the one-hour Gaia update time.
   base::TimeDelta oneMinuteDelta = base::Minutes(1);
   task_environment_.FastForwardBy(oneMinuteDelta);
-  SimulateNavigateToURLWithInterruption(response, nil);
+  SimulateNavigateToURLWithInterruption(response, nullptr);
 
   // Does not process the second Gaia restore event.
   CheckGaiaCookieWithUpdateTime(base::Time::Now() - oneMinuteDelta);
diff --git a/components/signin/ios/browser/manage_accounts_delegate.h b/components/signin/ios/browser/manage_accounts_delegate.h
index 878f3e0..4a4c4ac 100644
--- a/components/signin/ios/browser/manage_accounts_delegate.h
+++ b/components/signin/ios/browser/manage_accounts_delegate.h
@@ -10,34 +10,40 @@
 class WebState;
 }
 
-// TODO(crbug.com/1293395): Refactor ManageAccountsDelegate into a C++ abstract
-// class.
-@protocol ManageAccountsDelegate<NSObject>
+class ManageAccountsDelegate {
+ public:
+  ManageAccountsDelegate(const ManageAccountsDelegate&) = delete;
+  ManageAccountsDelegate& operator=(const ManageAccountsDelegate&) = delete;
 
-// Called when Gaia cookies have been regenerated for a specific user sign-in.
-// This occurs when a SAPISID cookie has been deleted by the operating system.
-- (void)onRestoreGaiaCookies;
+  virtual ~ManageAccountsDelegate() = default;
 
-// Called when the user taps on a manage accounts button in a Google web
-// property.
-- (void)onManageAccounts;
+  // Called when Gaia cookies have been regenerated for a specific user sign-in.
+  // This occurs when a SAPISID cookie has been deleted by the operating system.
+  virtual void OnRestoreGaiaCookies() = 0;
 
-// Called when the user taps on an add account button in a Google web property.
-- (void)onAddAccount;
+  // Called when the user taps on a manage accounts button in a Google web
+  // property.
+  virtual void OnManageAccounts() = 0;
 
-// Called when the user taps a sign-in or add account button in a Google web
-// property.
-// |url| is the continuation URL received from the server. If it is valid,
-// then this delegate should navigate to |url|.
-- (void)onShowConsistencyPromo:(const GURL&)url
-                      webState:(web::WebState*)webState;
+  // Called when the user taps on an add account button in a Google web
+  // property.
+  virtual void OnAddAccount() = 0;
 
-// Called when the user taps on go incognito button in a Google web property.
-// |url| is the continuation URL received from the server. If it is valid,
-// then this delegate should open an incognito tab and navigate to |url|.
-// If it is not valid, then this delegate should open a new incognito tab.
-- (void)onGoIncognito:(const GURL&)url;
+  // Called when the user taps a sign-in or add account button in a Google web
+  // property.
+  // |url| is the continuation URL received from the server. If it is valid,
+  // then this delegate should navigate to |url|.
+  virtual void OnShowConsistencyPromo(const GURL& url,
+                                      web::WebState* webState) = 0;
 
-@end
+  // Called when the user taps on go incognito button in a Google web property.
+  // |url| is the continuation URL received from the server. If it is valid,
+  // then this delegate should open an incognito tab and navigate to |url|.
+  // If it is not valid, then this delegate should open a new incognito tab.
+  virtual void OnGoIncognito(const GURL& url) = 0;
+
+ protected:
+  ManageAccountsDelegate() = default;
+};
 
 #endif  // COMPONENTS_SIGNIN_IOS_BROWSER_MANAGE_ACCOUNTS_DELEGATE_H_
diff --git a/components/test/data/storage/shared_storage.v0.init_too_old.sql b/components/test/data/storage/shared_storage.v0.init_too_old.sql
new file mode 100644
index 0000000..9df082d
--- /dev/null
+++ b/components/test/data/storage/shared_storage.v0.init_too_old.sql
@@ -0,0 +1,15 @@
+-- components_unittests --gtest_filter=SharedStorageDatabaseTest.Version1_DestroyTooOld
+--
+-- .dump of a version 1 Shared Storage database (although erroneously marked as version 0).
+-- intentionally set up to fail initialization with error SharedStorageDatabase::InitStatus::kTooOld
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','0');
+INSERT INTO "meta" VALUES('last_compatible_version','0');
+CREATE TABLE values_mapping(context_origin TEXT NOT NULL,key TEXT NOT NULL,value TEXT,PRIMARY KEY(context_origin,key)) WITHOUT ROWID;
+INSERT INTO "values_mapping" VALUES ('http://google.com','key1','value1');
+INSERT INTO "values_mapping" VALUES ('http://google.com','key2','value2');
+CREATE TABLE per_origin_mapping(context_origin TEXT NOT NULL PRIMARY KEY,last_used_time INTEGER NOT NULL,length INTEGER NOT NULL) WITHOUT ROWID;
+INSERT INTO "per_origin_mapping" VALUES ('http://google.com',13266954476192362,2);
+CREATE INDEX IF NOT EXISTS per_origin_mapping_last_used_time_idx ON per_origin_mapping(last_used_time);
+COMMIT;
diff --git a/components/test/data/storage/shared_storage.v1.init_too_new.sql b/components/test/data/storage/shared_storage.v1.init_too_new.sql
new file mode 100644
index 0000000..c4b82ae
--- /dev/null
+++ b/components/test/data/storage/shared_storage.v1.init_too_new.sql
@@ -0,0 +1,15 @@
+-- components_unittests --gtest_filter=SharedStorageDatabaseTest.Version1_DestroyTooNew
+--
+-- .dump of a version 1 Shared Storage database.
+-- intentionally set up to fail initialization with error SharedStorageDatabase::InitStatus::kTooNew
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','1');
+INSERT INTO "meta" VALUES('last_compatible_version','2');
+CREATE TABLE values_mapping(context_origin TEXT NOT NULL,key TEXT NOT NULL,value TEXT,PRIMARY KEY(context_origin,key)) WITHOUT ROWID;
+INSERT INTO "values_mapping" VALUES ('http://google.com','key1','value1');
+INSERT INTO "values_mapping" VALUES ('http://google.com','key2','value2');
+CREATE TABLE per_origin_mapping(context_origin TEXT NOT NULL PRIMARY KEY,last_used_time INTEGER NOT NULL,length INTEGER NOT NULL) WITHOUT ROWID;
+INSERT INTO "per_origin_mapping" VALUES ('http://google.com',13266954476192362,2);
+CREATE INDEX IF NOT EXISTS per_origin_mapping_last_used_time_idx ON per_origin_mapping(last_used_time);
+COMMIT;
diff --git a/components/test/data/storage/shared_storage.v1.sql b/components/test/data/storage/shared_storage.v1.sql
new file mode 100644
index 0000000..2921a32
--- /dev/null
+++ b/components/test/data/storage/shared_storage.v1.sql
@@ -0,0 +1,38 @@
+-- components_unittests --gtest_filter=SharedStorageDatabaseTest.Version1_LoadFromFile
+--
+-- .dump of a version 1 Shared Storage database.
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','1');
+INSERT INTO "meta" VALUES('last_compatible_version','1');
+CREATE TABLE values_mapping(context_origin TEXT NOT NULL,key TEXT NOT NULL,value TEXT,PRIMARY KEY(context_origin,key)) WITHOUT ROWID;
+INSERT INTO "values_mapping" VALUES ('http://google.com','key1','value1');
+INSERT INTO "values_mapping" VALUES ('http://google.com','key2','value2');
+INSERT INTO "values_mapping" VALUES ('http://youtube.com','visited','1111111');
+INSERT INTO "values_mapping" VALUES ('http://chromium.org','a','');
+INSERT INTO "values_mapping" VALUES ('http://chromium.org','b','hello');
+INSERT INTO "values_mapping" VALUES ('http://chromium.org','c','goodbye');
+INSERT INTO "values_mapping" VALUES ('http://gv.com','cookie','13268941793856733');
+INSERT INTO "values_mapping" VALUES ('http://abc.xyz','seed','387562094');
+INSERT INTO "values_mapping" VALUES ('http://abc.xyz','bucket','1276');
+INSERT INTO "values_mapping" VALUES ('http://withgoogle.com','count','389');
+INSERT INTO "values_mapping" VALUES ('http://waymo.com','key','value');
+INSERT INTO "values_mapping" VALUES ('http://google.org','1','ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
+INSERT INTO "values_mapping" VALUES ('http://google.org','2',';');
+INSERT INTO "values_mapping" VALUES ('http://google.org','#','[]');
+INSERT INTO "values_mapping" VALUES ('http://google.org','ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff','k');
+INSERT INTO "values_mapping" VALUES ('http://growwithgoogle.com','_','down');
+INSERT INTO "values_mapping" VALUES ('http://growwithgoogle.com','<','left');
+INSERT INTO "values_mapping" VALUES ('http://growwithgoogle.com','>','right');
+CREATE TABLE per_origin_mapping(context_origin TEXT NOT NULL PRIMARY KEY,last_used_time INTEGER NOT NULL,length INTEGER NOT NULL) WITHOUT ROWID;
+INSERT INTO "per_origin_mapping" VALUES ('http://google.com',13266954476192362,2);
+INSERT INTO "per_origin_mapping" VALUES ('http://youtube.com',13266954593856733,1);
+INSERT INTO "per_origin_mapping" VALUES ('http://chromium.org',13268941676192362,3);
+INSERT INTO "per_origin_mapping" VALUES ('http://gv.com',13268941793856733,1);
+INSERT INTO "per_origin_mapping" VALUES ('http://abc.xyz',13269481776356965,2);
+INSERT INTO "per_origin_mapping" VALUES ('http://withgoogle.com',13269545986263676,1);
+INSERT INTO "per_origin_mapping" VALUES ('http://waymo.com',13269546064355176,1);
+INSERT INTO "per_origin_mapping" VALUES ('http://google.org',13269546476192362,4);
+INSERT INTO "per_origin_mapping" VALUES ('http://growwithgoogle.com',13269546593856733,3);
+CREATE INDEX IF NOT EXISTS per_origin_mapping_last_used_time_idx ON per_origin_mapping(last_used_time);
+COMMIT;
diff --git a/components/web_app_resources/web_app_default_offline.css b/components/web_app_resources/web_app_default_offline.css
index 7729554f..ce3e4899 100644
--- a/components/web_app_resources/web_app_default_offline.css
+++ b/components/web_app_resources/web_app_default_offline.css
@@ -1,16 +1,31 @@
 /* Copyright 2022 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. */
- body {
+
+@media (prefers-color-scheme: light) {
+  body {
     background-color: var(--customized-background-color);
   }
   h2 {
     color: var(--theme-color);
-    height: 200px;
-    left: 50%;
-    margin-inline-start: -200px;
-    margin-top: -100px;
-    position: fixed;
-    top: 50%;
-    width: 400px;
-  }
\ No newline at end of file
+  }
+ }
+
+@media (prefers-color-scheme: dark) {
+  body {
+    background-color: var(--dark-mode-background-color);
+  }
+  h2 {
+    color: var(--dark-mode-theme-color);
+  }
+}
+
+h2 {
+  height: 200px;
+  left: 50%;
+  margin-inline-start: -200px;
+  margin-top: -100px;
+  position: fixed;
+  top: 50%;
+  width: 400px;
+}
diff --git a/components/web_app_resources/web_app_default_offline.html b/components/web_app_resources/web_app_default_offline.html
index 2659984..f56add9 100644
--- a/components/web_app_resources/web_app_default_offline.html
+++ b/components/web_app_resources/web_app_default_offline.html
@@ -10,12 +10,14 @@
     :root {
       --customized-background-color: $i18n{customized_background_color};
       --theme-color: $i18n{theme_color};
+      --dark-mode-background-color: $i18n{dark_mode_background_color};
+      --dark-mode-theme-color: $i18n{dark_mode_theme_color};
     }
   </style>
 </head>
   <body style="font-family: $i18n{fontfamily};font-size:$i18n{fontsize}">
     <h1>$i18n{app_short_name}</h1>
-    <h2  id="default-web-app-msg">$i18n{web_app_default_offline_message}</h2>
-    <!-- TODO(crbug.com/1285723): Add web app icon. -->
+    <h2 id="default-web-app-msg">$i18n{web_app_default_offline_message}</h2>
+    <!--TODO(crbug.com/1285723: Add web app icon.)-->
   </body>
 </html>
\ No newline at end of file
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index dc1b872f..fb32e2e 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -844,8 +844,6 @@
     "eye_dropper_chooser_impl.h",
     "feature_observer.cc",
     "feature_observer.h",
-    "federated_learning/floc_service_impl.cc",
-    "federated_learning/floc_service_impl.h",
     "fenced_frame/fenced_frame.cc",
     "fenced_frame/fenced_frame.h",
     "fenced_frame/fenced_frame_url_mapping.cc",
diff --git a/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm b/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm
index b6372d1..5b0adacf 100644
--- a/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm
+++ b/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm
@@ -591,4 +591,22 @@
 )~~");
 }
 
+IN_PROC_BROWSER_TEST_F(AXTreeFormatterMacBrowserTest,
+                       ScriptAccessibilityApiWithSELArgument) {
+  TestScript(
+      R"~~(<input id="s" type="range" min="0" max="100">)~~",
+      {"s.isAccessibilitySelectorAllowed(@SEL:setAccessibilityValue:)"},
+      R"~~(s.isAccessibilitySelectorAllowed(@SEL:setAccessibilityValue:)=0
+)~~");
+}
+
+IN_PROC_BROWSER_TEST_F(AXTreeFormatterMacBrowserTest,
+                       ScriptAccessibilityApiWithInvalidSELArgument) {
+  TestScript(
+      R"~~(<input id="s" type="range" min="0" max="100">)~~",
+      {"s.isAccessibilitySelectorAllowed(@SELInvalid)"},
+      R"~~(s.isAccessibilitySelectorAllowed(@SELInvalid)=ERROR:FAILED_TO_PARSE
+)~~");
+}
+
 }  // namespace content
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index 56acc3eb..235b7b5 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -23,7 +23,6 @@
 #include "content/browser/content_index/content_index_service_impl.h"
 #include "content/browser/cookie_store/cookie_store_manager.h"
 #include "content/browser/eye_dropper_chooser_impl.h"
-#include "content/browser/federated_learning/floc_service_impl.h"
 #include "content/browser/handwriting/handwriting_recognition_service_factory.h"
 #include "content/browser/image_capture/image_capture_impl.h"
 #include "content/browser/interest_group/ad_auction_service_impl.h"
@@ -1092,8 +1091,6 @@
       base::BindRepeating(&ContentIndexServiceImpl::CreateForFrame));
   map->Add<blink::mojom::KeyboardLockService>(
       base::BindRepeating(&KeyboardLockServiceImpl::CreateMojoService));
-  map->Add<blink::mojom::FlocService>(
-      base::BindRepeating(&FlocServiceImpl::CreateMojoService));
   if (base::FeatureList::IsEnabled(blink::features::kInterestGroupStorage)) {
     map->Add<blink::mojom::AdAuctionService>(
         base::BindRepeating(&AdAuctionServiceImpl::CreateMojoService));
diff --git a/content/browser/federated_learning/DIR_METADATA b/content/browser/federated_learning/DIR_METADATA
deleted file mode 100644
index ea6a8e2..0000000
--- a/content/browser/federated_learning/DIR_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-mixins: "//components/federated_learning/COMMON_METADATA"
diff --git a/content/browser/federated_learning/OWNERS b/content/browser/federated_learning/OWNERS
deleted file mode 100644
index 91d39f3..0000000
--- a/content/browser/federated_learning/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://components/federated_learning/OWNERS
diff --git a/content/browser/federated_learning/floc_service_impl.cc b/content/browser/federated_learning/floc_service_impl.cc
deleted file mode 100644
index ebd6ec0..0000000
--- a/content/browser/federated_learning/floc_service_impl.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/federated_learning/floc_service_impl.h"
-
-#include "base/bind.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/document_service.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_client.h"
-#include "net/base/isolation_info.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
-
-namespace content {
-
-FlocServiceImpl::FlocServiceImpl(
-    RenderFrameHost* render_frame_host,
-    mojo::PendingReceiver<blink::mojom::FlocService> receiver)
-    : DocumentService(render_frame_host, std::move(receiver)) {}
-
-// static
-void FlocServiceImpl::CreateMojoService(
-    RenderFrameHost* render_frame_host,
-    mojo::PendingReceiver<blink::mojom::FlocService> receiver) {
-  DCHECK(render_frame_host);
-
-  // The object is bound to the lifetime of |render_frame_host| and the mojo
-  // connection. See DocumentService for details.
-  new FlocServiceImpl(render_frame_host, std::move(receiver));
-}
-
-void FlocServiceImpl::GetInterestCohort(GetInterestCohortCallback callback) {
-  blink::mojom::InterestCohortPtr interest_cohort =
-      GetContentClient()->browser()->GetInterestCohortForJsApi(
-          WebContents::FromRenderFrameHost(render_frame_host()),
-          render_frame_host()->GetLastCommittedURL(),
-          render_frame_host()
-              ->GetIsolationInfoForSubresources()
-              .top_frame_origin());
-
-  std::move(callback).Run(std::move(interest_cohort));
-}
-
-FlocServiceImpl::~FlocServiceImpl() = default;
-
-}  // namespace content
diff --git a/content/browser/federated_learning/floc_service_impl.h b/content/browser/federated_learning/floc_service_impl.h
deleted file mode 100644
index 2750bcef..0000000
--- a/content/browser/federated_learning/floc_service_impl.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_FEDERATED_LEARNING_FLOC_SERVICE_IMPL_H_
-#define CONTENT_BROWSER_FEDERATED_LEARNING_FLOC_SERVICE_IMPL_H_
-
-#include "content/public/browser/document_service.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
-
-namespace content {
-
-class RenderFrameHost;
-
-class FlocServiceImpl final
-    : public DocumentService<blink::mojom::FlocService> {
- public:
-  FlocServiceImpl(RenderFrameHost* render_frame_host,
-                  mojo::PendingReceiver<blink::mojom::FlocService> receiver);
-
-  static void CreateMojoService(
-      RenderFrameHost* render_frame_host,
-      mojo::PendingReceiver<blink::mojom::FlocService> receiver);
-
-  // blink::mojom::FlocService.
-  void GetInterestCohort(GetInterestCohortCallback callback) override;
-
- private:
-  // |this| can only be destroyed by DocumentService.
-  ~FlocServiceImpl() override;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_FEDERATED_LEARNING_FLOC_SERVICE_IMPL_H_
diff --git a/content/browser/loader/navigation_url_loader_impl_unittest.cc b/content/browser/loader/navigation_url_loader_impl_unittest.cc
index 5624a678..02dbd8b 100644
--- a/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -45,6 +45,7 @@
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/network/resource_scheduler/resource_scheduler_client.h"
+#include "services/network/test/url_loader_context_for_tests.h"
 #include "services/network/url_loader.h"
 #include "services/network/url_request_context_owner.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -65,16 +66,24 @@
   explicit TestNavigationLoaderInterceptor(
       absl::optional<network::ResourceRequest>* most_recent_resource_request)
       : most_recent_resource_request_(most_recent_resource_request) {
-    net::URLRequestContextBuilder context_builder;
-    context_builder.set_proxy_resolution_service(
+    net::URLRequestContextBuilder url_request_context_builder;
+    url_request_context_builder.set_proxy_resolution_service(
         net::ConfiguredProxyResolutionService::CreateDirect());
-    context_ = context_builder.Build();
+    url_request_context_ = url_request_context_builder.Build();
+    url_loader_context_.set_url_request_context(url_request_context_.get());
+
     constexpr int child_id = 4;
     constexpr int route_id = 8;
     resource_scheduler_client_ =
         base::MakeRefCounted<network::ResourceSchedulerClient>(
             child_id, route_id, &resource_scheduler_,
-            context_->network_quality_estimator());
+            url_request_context_->network_quality_estimator());
+    url_loader_context_.set_resource_scheduler_client(
+        resource_scheduler_client_);
+
+    url_loader_context_.mutable_factory_params().process_id =
+        network::mojom::kBrowserProcessId;
+    url_loader_context_.mutable_factory_params().is_corb_enabled = false;
   }
 
   ~TestNavigationLoaderInterceptor() override {
@@ -96,23 +105,16 @@
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
       mojo::PendingRemote<network::mojom::URLLoaderClient> client) {
     *most_recent_resource_request_ = resource_request;
-    static network::mojom::URLLoaderFactoryParams params;
-    params.process_id = network::mojom::kBrowserProcessId;
-    params.is_corb_enabled = false;
     url_loader_ = std::make_unique<network::URLLoader>(
-        context_.get(), /*url_loader_factory=*/nullptr,
-        nullptr /* network_context_client */,
+        url_loader_context_,
         base::BindOnce(&TestNavigationLoaderInterceptor::DeleteURLLoader,
                        base::Unretained(this)),
         std::move(receiver), 0 /* options */, resource_request,
         std::move(client), nullptr /* sync_url_loader_client */,
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-        /*coep_reporter=*/nullptr, 0, /* request_id */
+        TRAFFIC_ANNOTATION_FOR_TESTS, 0, /* request_id */
         0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client_,
         nullptr /* keepalive_statistics_recorder */,
-        nullptr /* header_client */, nullptr /* origin_policy_manager */,
-        nullptr /* trust_token_helper */, kEmptyOriginAccessList,
+        nullptr /* trust_token_helper */,
         mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
@@ -140,7 +142,8 @@
   raw_ptr<absl::optional<network::ResourceRequest>>
       most_recent_resource_request_;  // NOT OWNED.
   network::ResourceScheduler resource_scheduler_;
-  std::unique_ptr<net::URLRequestContext> context_;
+  network::URLLoaderContextForTests url_loader_context_;
+  std::unique_ptr<net::URLRequestContext> url_request_context_;
   scoped_refptr<network::ResourceSchedulerClient> resource_scheduler_client_;
   std::unique_ptr<network::URLLoader> url_loader_;
 
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 067d0df..43ecf55 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -3703,11 +3703,7 @@
               network::mojom::WebClientHintsType>() /* enabled_client_hints */,
           false /* is_cross_browsing_instance */, nullptr /* old_page_info */,
           -1 /* http_response_code */,
-          std::vector<blink::mojom::
-                          AppHistoryEntryPtr>() /* app_history_back_entries */,
-          std::vector<
-              blink::mojom::
-                  AppHistoryEntryPtr>() /* app_history_forward_entries */,
+          blink::mojom::AppHistoryEntryArrays::New(),
           std::vector<GURL>() /* early_hints_preloaded_resources */,
           absl::nullopt /* ad_auction_components */,
           // This timestamp will be populated when the commit IPC is sent.
@@ -4348,7 +4344,8 @@
   return entries;
 }
 
-void NavigationControllerImpl::PopulateAppHistoryEntryVectors(
+blink::mojom::AppHistoryEntryArraysPtr
+NavigationControllerImpl::GetAppHistoryEntryVectors(
     NavigationRequest* request) {
   url::Origin pending_origin =
       request->commit_params().origin_to_commit
@@ -4384,18 +4381,19 @@
     }
   }
 
-  request->set_app_history_back_entries(PopulateSingleAppHistoryEntryVector(
+  auto entry_arrays = blink::mojom::AppHistoryEntryArrays::New();
+  entry_arrays->back_entries = PopulateSingleAppHistoryEntryVector(
       Direction::kBack, entry_index, pending_origin, node, site_instance.get(),
-      pending_item_sequence_number, pending_document_sequence_number));
+      pending_item_sequence_number, pending_document_sequence_number);
 
   // Don't populate forward entries if they will be truncated by a new entry.
   if (!will_create_new_entry) {
-    request->set_app_history_forward_entries(
-        PopulateSingleAppHistoryEntryVector(
-            Direction::kForward, entry_index, pending_origin, node,
-            site_instance.get(), pending_item_sequence_number,
-            pending_document_sequence_number));
+    entry_arrays->forward_entries = PopulateSingleAppHistoryEntryVector(
+        Direction::kForward, entry_index, pending_origin, node,
+        site_instance.get(), pending_item_sequence_number,
+        pending_document_sequence_number);
   }
+  return entry_arrays;
 }
 
 NavigationControllerImpl::HistoryNavigationAction
diff --git a/content/browser/renderer_host/navigation_controller_impl.h b/content/browser/renderer_host/navigation_controller_impl.h
index de8aaa1..99be3c2 100644
--- a/content/browser/renderer_host/navigation_controller_impl.h
+++ b/content/browser/renderer_host/navigation_controller_impl.h
@@ -32,6 +32,7 @@
 #include "services/network/public/mojom/source_location.mojom-forward.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
+#include "third_party/blink/public/mojom/navigation/app_history_entry_arrays.mojom-forward.h"
 #include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h"
 
 namespace blink {
@@ -392,9 +393,9 @@
   // Called just before sending the commit to the renderer. Walks the
   // session history entries for the committing FrameTreeNode, forward and
   // backward from the pending entry. All contiguous and same-origin
-  // FrameNavigationEntries are serialized and added to |request|'s commit
-  // params.
-  void PopulateAppHistoryEntryVectors(NavigationRequest* request);
+  // FrameNavigationEntries are serialized and returned.
+  blink::mojom::AppHistoryEntryArraysPtr GetAppHistoryEntryVectors(
+      NavigationRequest* request);
 
   // The appHistory API exposes the urls of some non-current same-origin
   // FrameNavigationEntries to the renderer. This helper checks whether the
diff --git a/content/browser/renderer_host/navigation_entry_impl.cc b/content/browser/renderer_host/navigation_entry_impl.cc
index 889e393..8906c83 100644
--- a/content/browser/renderer_host/navigation_entry_impl.cc
+++ b/content/browser/renderer_host/navigation_entry_impl.cc
@@ -923,11 +923,7 @@
               network::mojom::WebClientHintsType>() /* enabled_client_hints */,
           false /* is_cross_browsing_instance */, nullptr /* old_page_info */,
           -1 /* http_response_code */,
-          std::vector<blink::mojom::
-                          AppHistoryEntryPtr>() /* app_history_back_entries */,
-          std::vector<
-              blink::mojom::
-                  AppHistoryEntryPtr>() /* app_history_forward_entries */,
+          blink::mojom::AppHistoryEntryArrays::New(),
           std::vector<GURL>() /* early_hints_preloaded_resources */,
           absl::nullopt /* ad_auction_components */,
           // This timestamp will be populated when the commit IPC is sent.
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index ea7c39b..d0401bf 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -1088,11 +1088,7 @@
           std::vector<network::mojom::WebClientHintsType>(),
           /*is_cross_browsing_instance=*/false,
           /*old_page_info=*/nullptr, /*http_response_code=*/-1,
-          std::vector<blink::mojom::
-                          AppHistoryEntryPtr>() /* app_history_back_entries */,
-          std::vector<
-              blink::mojom::
-                  AppHistoryEntryPtr>() /* app_history_forward_entries */,
+          blink::mojom::AppHistoryEntryArrays::New(),
           /*early_hints_preloaded_resources=*/
           std::vector<GURL>(), absl::nullopt /* ad_auction_components */,
           // This timestamp will be populated when the commit IPC is sent.
@@ -1214,12 +1210,7 @@
           std::vector<
               network::mojom::WebClientHintsType>() /* enabled_client_hints */,
           false /* is_cross_browsing_instance */, nullptr /* old_page_info */,
-          http_response_code,
-          std::vector<blink::mojom::
-                          AppHistoryEntryPtr>() /* app_history_back_entries */,
-          std::vector<
-              blink::mojom::
-                  AppHistoryEntryPtr>() /* app_history_forward_entries */,
+          http_response_code, blink::mojom::AppHistoryEntryArrays::New(),
           std::vector<GURL>() /* early_hints_preloaded_resources */,
           absl::nullopt /* ad_auction_components */,
           // This timestamp will be populated when the commit IPC is sent.
@@ -4438,8 +4429,10 @@
         pending_ad_components_map_->GetURNs();
   }
 
-  if (!IsSameDocument())
-    GetNavigationController()->PopulateAppHistoryEntryVectors(this);
+  if (!IsSameDocument()) {
+    commit_params_->app_history_entry_arrays =
+        GetNavigationController()->GetAppHistoryEntryVectors(this);
+  }
 
   if (early_hints_manager_) {
     commit_params_->early_hints_preloaded_resources =
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h
index abfdd6c..9844fe8 100644
--- a/content/browser/renderer_host/navigation_request.h
+++ b/content/browser/renderer_host/navigation_request.h
@@ -404,16 +404,6 @@
         is_cross_site_cross_browsing_context_group;
   }
 
-  void set_app_history_back_entries(
-      std::vector<blink::mojom::AppHistoryEntryPtr> entries) {
-    commit_params_->app_history_back_entries = std::move(entries);
-  }
-
-  void set_app_history_forward_entries(
-      std::vector<blink::mojom::AppHistoryEntryPtr> entries) {
-    commit_params_->app_history_forward_entries = std::move(entries);
-  }
-
   NavigationURLLoader* loader_for_testing() const { return loader_.get(); }
 
   NavigationState state() const { return state_; }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index cc14d01..861b6fd 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -703,7 +703,8 @@
     view->TextInputStateChanged(state_with_type_text);
   }
 
-  BrowserTaskEnvironment task_environment_;
+  BrowserTaskEnvironment task_environment_{
+      base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME};
   std::unique_ptr<aura::test::AuraTestHelper> aura_test_helper_;
   std::unique_ptr<BrowserContext> browser_context_;
   std::unique_ptr<WebContents> web_contents_;
@@ -1787,8 +1788,7 @@
 
   // Let the MouseWheelPhaseHandler::mouse_wheel_end_dispatch_timer_ fire. A
   // synthetic wheel event with zero deltas and kPhaseEnded will be sent.
-  base::PlatformThread::Sleep(base::Milliseconds(100));
-  base::RunLoop().RunUntilIdle();
+  task_environment_.FastForwardBy(base::Milliseconds(100));
 
   events = GetAndResetDispatchedMessages();
   const WebMouseWheelEvent* wheel_end_event =
@@ -4262,8 +4262,7 @@
   // enough overscroll to complete the gesture, the overscroll controller
   // will reset the state. The scroll-end should therefore be dispatched to the
   // renderer, and the gesture-event-filter should await an ACK for it.
-  base::PlatformThread::Sleep(base::Milliseconds(10));
-  base::RunLoop().RunUntilIdle();
+  task_environment_.FastForwardBy(base::Milliseconds(10));
   events = GetAndResetDispatchedMessages();
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
   EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
@@ -4387,8 +4386,7 @@
 
   SimulateGestureEvent(blink::WebInputEvent::Type::kGestureScrollEnd,
                        blink::WebGestureDevice::kTouchscreen);
-  base::PlatformThread::Sleep(base::Milliseconds(10));
-  base::RunLoop().RunUntilIdle();
+  task_environment_.FastForwardBy(base::Milliseconds(10));
   events = GetAndResetDispatchedMessages();
   EXPECT_EQ("GestureScrollEnd", GetMessageNames(events));
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
@@ -4443,8 +4441,7 @@
                        blink::WebGestureDevice::kTouchscreen);
   events = GetAndResetDispatchedMessages();
   EXPECT_EQ(0U, events.size());
-  base::PlatformThread::Sleep(base::Milliseconds(10));
-  base::RunLoop().RunUntilIdle();
+  task_environment_.FastForwardBy(base::Milliseconds(10));
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
   EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
@@ -4487,8 +4484,7 @@
                        blink::WebGestureDevice::kTouchscreen);
   events = GetAndResetDispatchedMessages();
   EXPECT_EQ(0U, events.size());
-  base::PlatformThread::Sleep(base::Milliseconds(10));
-  base::RunLoop().RunUntilIdle();
+  task_environment_.FastForwardBy(base::Milliseconds(10));
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
   EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 9df4e4c..dd39e46 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -11945,8 +11945,9 @@
 #if !BUILDFLAG(IS_ANDROID)
 // This test verifies that after occluding a WebContents the RAF inside a
 // cross-process child frame is throttled.
+// Disabled due to flakiness. crbug.com/1293207
 IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
-                       OccludedRenderWidgetThrottlesRAF) {
+                       DISABlED_OccludedRenderWidgetThrottlesRAF) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(b)"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
diff --git a/content/browser/webid/README.md b/content/browser/webid/README.md
index b3d2de1..7465b63 100644
--- a/content/browser/webid/README.md
+++ b/content/browser/webid/README.md
@@ -1,30 +1,30 @@
-# WebID Browser side
+# FedCM Browser side
 
 This folder contains the implementation of the browser side logic for the
-[WebID](https://wicg.github.io/WebID/README.html) feature. It is responsible for making all of the
-network requests needed to implement a WebID request and also controls what UI and at which point in
+[FedCM](https://github.com/fedidcg/FedCM/blob/main/explainer/README.md) feature. It is responsible for making all of the
+network requests needed to implement a FedCM request and also controls what UI and at which point in
 the process is shown to the user.
 
-## Anatomy of a WebID request
+## Anatomy of a FedCM request
 
-A WebID request is initiated by a [Relying
-Party](https://wicg.github.io/WebID/glossary.html#relying-party-rp) (RP) in order to perform a
+A FedCM request is initiated by a [Relying
+Party](https://github.com/fedidcg/FedCM/blob/main/explainer/glossary.md#relying-party-rp) (RP) in order to perform a
 federated identity related operation e.g., authenticate, logout etc., with an [Identity
-Provider](https://wicg.github.io/WebID/glossary.html#identity-provider-idp) (IDP).
+Provider](https://github.com/fedidcg/FedCM/blob/main/explainer/glossary.md#identity-provider-idp) (IDP).
 
 While RP and IDP could belong to the same site (or origin) the most interesting and common case
 is when the RP and IDP belong to different sites and thus this operation is a cross-site
 communication and subject to additional scrutiny by the browser.
 
 
-Here is the basic process in Chromium for a WebID request:
+Here is the basic process in Chromium for a FedCM request:
 
 1. The RP renderer process creates a new request via async JavaScript APIs which return a promise.
       - See [WebID.idl](../../../third_party/blink/renderer/modules/webid/web_id.idl) for supported
         methods.
       - The logic for handling and validation of these request lives in
         [`web_id.cc`](../../../third_party/blink/renderer/modules/webid/web_id.cc)
-      - Also in certain situations WebID can be activated passively by a navigation throttle that
+      - Also in certain situations FedCM can be activated passively by a navigation throttle that
         identifies an OAuth request being passed over a top-level navigation.
 
 1. Renderer process passes this request to the browser process via the
@@ -43,9 +43,9 @@
 
 ## Network Fetches
 
-As explained before, the cross-site nature of WebID communication means that there is additional
+As explained before, the cross-site nature of FedCM communication means that there is additional
 scrutiny and enforcement for them by the browser. These enforcements occur in the browser process so
-that they cannot be side-stepped by a malicious renderer process. This is why all of WebID network
+that they cannot be side-stepped by a malicious renderer process. This is why all of FedCM network
 requests occur in the browser process.
 
 **TODO**: Explain various fetches that occur in
@@ -55,7 +55,7 @@
 
 ## Permission Grants
 
-As part of the WebID request flow the user often has to grant the RP and IDP special permissions to
+As part of the FedCM request flow the user often has to grant the RP and IDP special permissions to
 allow cross-site communications. This exact UX for granting of these permissions depends on the
 mode that is used.
 
@@ -93,9 +93,9 @@
 
 ## UI
 
-There are currently two different modes supported for WebID with their own specific UX and UI:
-[permission-oriented mode](https://wicg.github.io/WebID/README.html#the-permission-oriented-api),
-and [mediation-oriented mode](https://wicg.github.io/WebID/README.html#the-mediation-oriented-api).
+There are currently two different modes supported for FedCM with their own specific UX and UI:
+[permission-oriented mode](https://github.com/fedidcg/FedCM/blob/main/explainer/proposal.md#the-permission-oriented-api),
+and [mediation-oriented mode](https://github.com/fedidcg/FedCM/blob/main/explainer/proposal.md#the-mediated-oriented-api).
 
 At the moment the mediation UI is only implemented on
 [Android](../../../chrome/browser/ui/android/webid/README.md) and on Desktop platforms no UI is shown and
@@ -107,10 +107,10 @@
 
 ## Key Classes
 
-- `FederatedAuthRequestImpl`: Concrete implementation of the mojo interface to initiate a WebID
-   request. It contains most of the business logic and state necessary for WebID requests.
-- `IdPNetworkRequestManager`: Handles all fetches needed for WebID. It ensures we use the right
+- `FederatedAuthRequestImpl`: Concrete implementation of the mojo interface to initiate a FedCM
+   request. It contains most of the business logic and state necessary for FedCM requests.
+- `IdPNetworkRequestManager`: Handles all fetches needed for FedCM. It ensures we use the right
   storage partition and cookie jar for each request. This class is stateless itself.
-- `FederatedAuthResponseImpl`: Concrete implementation of the mojo interface to provide a WebID
+- `FederatedAuthResponseImpl`: Concrete implementation of the mojo interface to provide a FedCM
    response. This is to be used by the IDP login page to complete its process by providing
    an id token.
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc
index 1a94fa9..debb3701 100644
--- a/content/browser/webid/idp_network_request_manager.cc
+++ b/content/browser/webid/idp_network_request_manager.cc
@@ -165,7 +165,7 @@
 
   absl::optional<LoginState> approved_value;
   if (approved_clients) {
-    for (const base::Value& entry : approved_clients->GetList()) {
+    for (const base::Value& entry : approved_clients->GetListDeprecated()) {
       if (entry.is_string() && entry.GetString() == client_id) {
         approved_value = LoginState::kSignIn;
         break;
diff --git a/content/browser/webui/web_ui_message_handler.cc b/content/browser/webui/web_ui_message_handler.cc
index 0b05ca0c7..9c8582d 100644
--- a/content/browser/webui/web_ui_message_handler.cc
+++ b/content/browser/webui/web_ui_message_handler.cc
@@ -43,7 +43,13 @@
 
 bool WebUIMessageHandler::ExtractIntegerValue(const base::ListValue* value,
                                               int* out_int) {
-  const base::Value& single_element = value->GetListDeprecated()[0];
+  return WebUIMessageHandler::ExtractIntegerValue(value->GetListDeprecated(),
+                                                  out_int);
+}
+
+bool WebUIMessageHandler::ExtractIntegerValue(base::Value::ConstListView value,
+                                              int* out_int) {
+  const base::Value& single_element = value[0];
   absl::optional<double> double_value = single_element.GetIfDouble();
   if (double_value) {
     *out_int = static_cast<int>(*double_value);
@@ -55,7 +61,13 @@
 
 bool WebUIMessageHandler::ExtractDoubleValue(const base::ListValue* value,
                                              double* out_value) {
-  const base::Value& single_element = value->GetListDeprecated()[0];
+  return WebUIMessageHandler::ExtractDoubleValue(value->GetListDeprecated(),
+                                                 out_value);
+}
+
+bool WebUIMessageHandler::ExtractDoubleValue(base::Value::ConstListView value,
+                                             double* out_value) {
+  const base::Value& single_element = value[0];
   absl::optional<double> double_value = single_element.GetIfDouble();
   if (double_value) {
     *out_value = *double_value;
@@ -67,7 +79,11 @@
 
 std::u16string WebUIMessageHandler::ExtractStringValue(
     const base::ListValue* value) {
-  base::Value::ConstListView list_view = value->GetListDeprecated();
+  return WebUIMessageHandler::ExtractStringValue(value->GetListDeprecated());
+}
+
+std::u16string WebUIMessageHandler::ExtractStringValue(
+    base::Value::ConstListView list_view) {
   if (0u < list_view.size() && list_view[0].is_string())
     return base::UTF8ToUTF16(list_view[0].GetString());
 
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 45a4e89..8880e7b8 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -359,8 +359,6 @@
           {"FontSrcLocalMatching", features::kFontSrcLocalMatching},
           {"ForceSynchronousHTMLParsing",
            blink::features::kForceSynchronousHTMLParsing},
-          {"InterestCohortFeaturePolicy",
-           blink::features::kInterestCohortFeaturePolicy},
           {"LateFormNewlineNormalization",
            blink::features::kLateFormNewlineNormalization},
           {"LayoutNG", blink::features::kLayoutNG},
diff --git a/content/common/common_param_traits_unittest.cc b/content/common/common_param_traits_unittest.cc
index 31ea175f..deb59ae 100644
--- a/content/common/common_param_traits_unittest.cc
+++ b/content/common/common_param_traits_unittest.cc
@@ -99,7 +99,7 @@
   base::PickleIterator iter(msg);
   EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
 
-  EXPECT_TRUE(input.Equals(&output));
+  EXPECT_EQ(input, output);
 
   // Also test the corrupt case.
   IPC::Message bad_msg(1, 2, IPC::Message::PRIORITY_NORMAL);
@@ -133,7 +133,7 @@
   base::PickleIterator iter(msg);
   EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
 
-  EXPECT_TRUE(input.Equals(&output));
+  EXPECT_EQ(input, output);
 
   // Also test the corrupt case.
   IPC::Message bad_msg(1, 2, IPC::Message::PRIORITY_NORMAL);
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 174b7a6..e4be60c 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -67,7 +67,6 @@
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/shell_dialogs/select_file_policy.h"
 #include "url/gurl.h"
@@ -1123,13 +1122,6 @@
     bool user_gesture,
     blink::NavigationDownloadPolicy* download_policy) {}
 
-blink::mojom::InterestCohortPtr ContentBrowserClient::GetInterestCohortForJsApi(
-    WebContents* web_contents,
-    const GURL& url,
-    const absl::optional<url::Origin>& top_frame_origin) {
-  return blink::mojom::InterestCohort::New();
-}
-
 bool ContentBrowserClient::IsBluetoothScanningBlocked(
     content::BrowserContext* browser_context,
     const url::Origin& requesting_origin,
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index f5db7c3..db75a34 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -60,7 +60,6 @@
 #include "storage/browser/file_system/file_system_context.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom-forward.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 #include "ui/accessibility/ax_mode.h"
 #include "ui/base/page_transition_types.h"
@@ -1948,13 +1947,6 @@
       bool user_gesture,
       blink::NavigationDownloadPolicy* download_policy);
 
-  // Returns the interest cohort associated with the browser context of
-  // |web_contents|.
-  virtual blink::mojom::InterestCohortPtr GetInterestCohortForJsApi(
-      WebContents* web_contents,
-      const GURL& url,
-      const absl::optional<url::Origin>& top_frame_origin);
-
   // Returns whether a site is blocked to use Bluetooth scanning API.
   virtual bool IsBluetoothScanningBlocked(
       content::BrowserContext* browser_context,
diff --git a/content/public/browser/web_ui_message_handler.h b/content/public/browser/web_ui_message_handler.h
index 65d149a..dc958ce 100644
--- a/content/public/browser/web_ui_message_handler.h
+++ b/content/public/browser/web_ui_message_handler.h
@@ -20,10 +20,6 @@
 class MojoWebUIBrowserTest;
 class CertificateHandlerTest;
 
-namespace base {
-class ListValue;
-}
-
 namespace content {
 
 class TestWebUI;
@@ -69,13 +65,18 @@
 
   // Extract an integer value from a list Value.
   static bool ExtractIntegerValue(const base::ListValue* value, int* out_int);
+  static bool ExtractIntegerValue(base::Value::ConstListView value,
+                                  int* out_int);
 
   // Extract a floating point (double) value from a list Value.
   static bool ExtractDoubleValue(const base::ListValue* value,
                                  double* out_value);
+  static bool ExtractDoubleValue(base::Value::ConstListView value,
+                                 double* out_value);
 
   // Extract a string value from a list Value.
   static std::u16string ExtractStringValue(const base::ListValue* value);
+  static std::u16string ExtractStringValue(base::Value::ConstListView value);
 
   // This is where subclasses specify which messages they'd like to handle and
   // perform any additional initialization.. At this point web_ui() will return
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 58381e81..9e36b3b 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -419,7 +419,7 @@
 // Note that navigation_start does not take into account the amount of time the
 // renderer spends processing the IPC (that is, executing script).
 const base::Feature kIncludeIpcOverheadInNavigationStart{
-    "IncludeIpcOverheadInNavigationStart", base::FEATURE_DISABLED_BY_DEFAULT};
+    "IncludeIpcOverheadInNavigationStart", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Kill switch for the GetInstalledRelatedApps API.
 const base::Feature kInstalledApp{"InstalledApp",
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 0cec8fa..4b28186 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1071,15 +1071,16 @@
     navigation_params->http_status_code = commit_params.http_response_code;
 
   // Populate the arrays of non-current entries for the appHistory API.
+  auto& entry_arrays = commit_params.app_history_entry_arrays;
   navigation_params->app_history_back_entries.reserve(
-      commit_params.app_history_back_entries.size());
-  for (const auto& entry : commit_params.app_history_back_entries) {
+      entry_arrays->back_entries.size());
+  for (const auto& entry : entry_arrays->back_entries) {
     navigation_params->app_history_back_entries.emplace_back(
         AppHistoryEntryPtrToWebHistoryItem(*entry));
   }
   navigation_params->app_history_forward_entries.reserve(
-      commit_params.app_history_forward_entries.size());
-  for (const auto& entry : commit_params.app_history_forward_entries) {
+      entry_arrays->forward_entries.size());
+  for (const auto& entry : entry_arrays->forward_entries) {
     navigation_params->app_history_forward_entries.emplace_back(
         AppHistoryEntryPtrToWebHistoryItem(*entry));
   }
diff --git a/content/services/auction_worklet/auction_v8_helper_unittest.cc b/content/services/auction_worklet/auction_v8_helper_unittest.cc
index cbb413e..15d8671 100644
--- a/content/services/auction_worklet/auction_v8_helper_unittest.cc
+++ b/content/services/auction_worklet/auction_v8_helper_unittest.cc
@@ -524,16 +524,18 @@
     EXPECT_EQ("debug", *type);
     const base::Value* args = message.value.FindListPath("params.args");
     ASSERT_TRUE(args);
-    ASSERT_EQ(1u, args->GetList().size());
-    EXPECT_EQ("string", *args->GetList()[0].FindStringKey("type"));
-    EXPECT_EQ("debug is there", *args->GetList()[0].FindStringKey("value"));
+    ASSERT_EQ(1u, args->GetListDeprecated().size());
+    EXPECT_EQ("string", *args->GetListDeprecated()[0].FindStringKey("type"));
+    EXPECT_EQ("debug is there",
+              *args->GetListDeprecated()[0].FindStringKey("value"));
     const base::Value* stack_trace =
         message.value.FindListPath("params.stackTrace.callFrames");
-    ASSERT_EQ(1u, stack_trace->GetList().size());
-    EXPECT_EQ("", *stack_trace->GetList()[0].FindStringKey("functionName"));
+    ASSERT_EQ(1u, stack_trace->GetListDeprecated().size());
+    EXPECT_EQ(
+        "", *stack_trace->GetListDeprecated()[0].FindStringKey("functionName"));
     EXPECT_EQ("https://foo.test/",
-              *stack_trace->GetList()[0].FindStringKey("url"));
-    EXPECT_EQ(1, *stack_trace->GetList()[0].FindIntKey("lineNumber"));
+              *stack_trace->GetListDeprecated()[0].FindStringKey("url"));
+    EXPECT_EQ(1, *stack_trace->GetListDeprecated()[0].FindIntKey("lineNumber"));
   }
 
   {
@@ -544,25 +546,26 @@
     EXPECT_EQ("log", *type);
     const base::Value* args = message.value.FindListPath("params.args");
     ASSERT_TRUE(args);
-    ASSERT_EQ(5u, args->GetList().size());
-    EXPECT_EQ("string", *args->GetList()[0].FindStringKey("type"));
-    EXPECT_EQ("can", *args->GetList()[0].FindStringKey("value"));
-    EXPECT_EQ("string", *args->GetList()[1].FindStringKey("type"));
-    EXPECT_EQ("log", *args->GetList()[1].FindStringKey("value"));
-    EXPECT_EQ("string", *args->GetList()[2].FindStringKey("type"));
-    EXPECT_EQ("multiple", *args->GetList()[2].FindStringKey("value"));
-    EXPECT_EQ("string", *args->GetList()[3].FindStringKey("type"));
-    EXPECT_EQ("things", *args->GetList()[3].FindStringKey("value"));
-    EXPECT_EQ("boolean", *args->GetList()[4].FindStringKey("type"));
-    EXPECT_EQ(true, *args->GetList()[4].FindBoolKey("value"));
+    ASSERT_EQ(5u, args->GetListDeprecated().size());
+    EXPECT_EQ("string", *args->GetListDeprecated()[0].FindStringKey("type"));
+    EXPECT_EQ("can", *args->GetListDeprecated()[0].FindStringKey("value"));
+    EXPECT_EQ("string", *args->GetListDeprecated()[1].FindStringKey("type"));
+    EXPECT_EQ("log", *args->GetListDeprecated()[1].FindStringKey("value"));
+    EXPECT_EQ("string", *args->GetListDeprecated()[2].FindStringKey("type"));
+    EXPECT_EQ("multiple", *args->GetListDeprecated()[2].FindStringKey("value"));
+    EXPECT_EQ("string", *args->GetListDeprecated()[3].FindStringKey("type"));
+    EXPECT_EQ("things", *args->GetListDeprecated()[3].FindStringKey("value"));
+    EXPECT_EQ("boolean", *args->GetListDeprecated()[4].FindStringKey("type"));
+    EXPECT_EQ(true, *args->GetListDeprecated()[4].FindBoolKey("value"));
 
     const base::Value* stack_trace =
         message.value.FindListPath("params.stackTrace.callFrames");
-    ASSERT_EQ(1u, stack_trace->GetList().size());
-    EXPECT_EQ("foo", *stack_trace->GetList()[0].FindStringKey("functionName"));
+    ASSERT_EQ(1u, stack_trace->GetListDeprecated().size());
+    EXPECT_EQ("foo", *stack_trace->GetListDeprecated()[0].FindStringKey(
+                         "functionName"));
     EXPECT_EQ("https://foo.test/",
-              *stack_trace->GetList()[0].FindStringKey("url"));
-    EXPECT_EQ(4, *stack_trace->GetList()[0].FindIntKey("lineNumber"));
+              *stack_trace->GetListDeprecated()[0].FindStringKey("url"));
+    EXPECT_EQ(4, *stack_trace->GetListDeprecated()[0].FindIntKey("lineNumber"));
   }
 
   {
@@ -573,16 +576,18 @@
     EXPECT_EQ("table", *type);
     const base::Value* args = message.value.FindListPath("params.args");
     ASSERT_TRUE(args);
-    ASSERT_EQ(1u, args->GetList().size());
-    EXPECT_EQ("string", *args->GetList()[0].FindStringKey("type"));
-    EXPECT_EQ("even table!", *args->GetList()[0].FindStringKey("value"));
+    ASSERT_EQ(1u, args->GetListDeprecated().size());
+    EXPECT_EQ("string", *args->GetListDeprecated()[0].FindStringKey("type"));
+    EXPECT_EQ("even table!",
+              *args->GetListDeprecated()[0].FindStringKey("value"));
     const base::Value* stack_trace =
         message.value.FindListPath("params.stackTrace.callFrames");
-    ASSERT_EQ(1u, stack_trace->GetList().size());
-    EXPECT_EQ("foo", *stack_trace->GetList()[0].FindStringKey("functionName"));
+    ASSERT_EQ(1u, stack_trace->GetListDeprecated().size());
+    EXPECT_EQ("foo", *stack_trace->GetListDeprecated()[0].FindStringKey(
+                         "functionName"));
     EXPECT_EQ("https://foo.test/",
-              *stack_trace->GetList()[0].FindStringKey("url"));
-    EXPECT_EQ(5, *stack_trace->GetList()[0].FindIntKey("lineNumber"));
+              *stack_trace->GetListDeprecated()[0].FindStringKey("url"));
+    EXPECT_EQ(5, *stack_trace->GetListDeprecated()[0].FindIntKey("lineNumber"));
   }
 
   id->AbortDebuggerPauses();
diff --git a/content/test/attribution_simulator_input_parser.cc b/content/test/attribution_simulator_input_parser.cc
index f1fc76e..ea06bfc 100644
--- a/content/test/attribution_simulator_input_parser.cc
+++ b/content/test/attribution_simulator_input_parser.cc
@@ -162,13 +162,13 @@
   std::vector<AttributionSimulationEvent> events;
 
   if (const base::Value* items = input.FindListKey("sources")) {
-    for (const base::Value& item : items->GetList()) {
+    for (const base::Value& item : items->GetListDeprecated()) {
       events.push_back(ParseSource(item, offset_time));
     }
   }
 
   if (const base::Value* items = input.FindListKey("triggers")) {
-    for (const base::Value& item : items->GetList()) {
+    for (const base::Value& item : items->GetListDeprecated()) {
       events.push_back(ParseTrigger(item, offset_time));
     }
   }
diff --git a/content/test/data/accessibility/mac/methods/is-accessibility-selector-allowed-expected.txt b/content/test/data/accessibility/mac/methods/is-accessibility-selector-allowed-expected.txt
new file mode 100644
index 0000000..6d7c1f7
--- /dev/null
+++ b/content/test/data/accessibility/mac/methods/is-accessibility-selector-allowed-expected.txt
@@ -0,0 +1 @@
+slider.isAccessibilitySelectorAllowed(@SEL:setAccessibilityValue:)=0
diff --git a/content/test/data/accessibility/mac/methods/is-accessibility-selector-allowed.html b/content/test/data/accessibility/mac/methods/is-accessibility-selector-allowed.html
new file mode 100644
index 0000000..501be4c
--- /dev/null
+++ b/content/test/data/accessibility/mac/methods/is-accessibility-selector-allowed.html
@@ -0,0 +1,5 @@
+<!--
+@SCRIPT:
+  slider.isAccessibilitySelectorAllowed(@SEL:setAccessibilityValue:)
+-->
+<input id="slider" type="range" min=0 max=100>
diff --git a/content/test/data/accessibility/readme.md b/content/test/data/accessibility/readme.md
index 2da80cb2..613fdb9 100644
--- a/content/test/data/accessibility/readme.md
+++ b/content/test/data/accessibility/readme.md
@@ -211,7 +211,7 @@
   input.AXName
 ```
 
-Calls can be chained, for example:
+Calls can be chained. For example:
 
 `input.AXFocusableAncestor.AXRole`
 
@@ -229,7 +229,7 @@
   input.accessibilityAttributeNames.has(AXInvalid)
 ```
 
-Parameterized attributes are also supported, for example:
+Parameterized attributes are also supported. For example:
 
 `paragraph.AXTextMarkerForIndex(0)`
 
@@ -249,14 +249,20 @@
 You can also use array operator[] to refer to an array element at a given index,
 for example `paragraph.AXChildren[0]` will refer to the first child of the paragraph.
 
-To set a settable attribute you can assign a value to the attribute, for example:
+To set a settable attribute you can assign a value to the attribute. For example:
 ```
 textarea_range:= textarea.AXTextMarkerRangeForUIElement(textarea)
 textarea.AXSelectedTextMarkerRange = textarea_range
 ```
 
+To pass a SEL as argument, you need to use the "@SEL:" prefix. For example:
+```
+@SCRIPT:
+  slider.isAccessibilitySelectorAllowed(@SEL:setAccessibilityValue:)
+```
+
 You can use `waitfor` instruction to wait for a specific event before the script
-continues, for example:
+continues. For example:
 
 ```
 @MAC-SCRIPT:
@@ -266,7 +272,7 @@
 
 will trigger `AXPress` action on a button and will wait for
 `AXFocusedUIElementChanged` event. You can also be more specific if you want to
-and provide the event target, for example:
+and provide the event target. For example:
 `wait for AXFocusedUIElementChanged on AXButton`
 
 ### Advanced directives
@@ -319,11 +325,11 @@
 #### @NO_DUMP and @NO_CHILDREN_DUMP
 
 To skip dumping a particular element, add `@NO_DUMP` to a property that will
-be exposed as an ax::mojom::StringAttribute, for example
+be exposed as an ax::mojom::StringAttribute. For example
 `<div class="@NO_DUMP"></div>`.
 
 To skip dumping all children of a particular element, add `@NO_CHILDREN_DUMP`
-to a property that will be exposed as an ax::mojom::StringAttribute, for example
+to a property that will be exposed as an ax::mojom::StringAttribute. For example
 `<div class="@NO_CHILDREN_DUMP"></div>`.
 
 Note that setting the `aria-label` value to `@NO_DUMP` or `@NO_CHILDREN_DUMP`
@@ -331,7 +337,7 @@
 provided naming in ARIA 1.2.
 
 To load an iframe from a different site, forcing it into a different process,
-use `/cross-site/HOSTNAME/` in the url, for example:
+use `/cross-site/HOSTNAME/` in the url. For example:
 `<iframe src="cross-site/1.com/accessibility/html/frame.html"></iframe>`
 
 ## Generating expectations and rebaselining:
@@ -339,7 +345,7 @@
 If you want to populate the expectation file directly rather than typing it
 or copying-and-pasting it, first make sure the file exists (it can be empty),
 then run the test with the `--generate-accessibility-test-expectations`
-argument, for example:
+argument. For example:
 ```
   out/Debug/content_browsertests \
     --generate-accessibility-test-expectations \
diff --git a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
index b08f9dff..8b0610a4 100644
--- a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
@@ -92,6 +92,9 @@
 crbug.com/1084794 [ chromeos ] GpuProcess_feature_status_under_swiftshader [ Skip ]
 crbug.com/1084794 [ chromeos ] GpuProcess_swiftshader_for_webgl [ Skip ]
 
+# Seems to kill the system UI/otherwise make the device unusable.
+crbug.com/1294065 [ android android-shield-android-tv ] GpuProcess_visibility [ Skip ]
+
 ###################
 # Failures/Flakes #
 ###################
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 2e74056..8af3bb807 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -613,6 +613,8 @@
 crbug.com/478572 [ android android-nexus-9 ] deqp/data/gles2/shaders/functions.html [ Failure ]
 # Texture tests found to generate intermittent GL errors in the GPU process
 crbug.com/1090407 [ android android-nexus-9 ] conformance/textures/* [ RetryOnFailure ]
+crbug.com/1294071 [ android-pie android-shield-android-tv ] conformance/glsl/bugs/vector-matrix-constructor-scalarization.html [ Failure ]
+crbug.com/1294340 [ android android-shield-android-tv ] conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ RetryOnFailure ]
 
 # Pixel 4
 crbug.com/1175223 [ android android-pixel-4 angle-opengles passthrough ] conformance/extensions/angle-instanced-arrays-out-of-bounds.html [ Failure ]
diff --git a/courgette/BUILD.gn b/courgette/BUILD.gn
index 6b15c39..a234bd2f 100644
--- a/courgette/BUILD.gn
+++ b/courgette/BUILD.gn
@@ -232,8 +232,7 @@
   data = [ "testdata/" ]
 
   if (is_fuchsia) {
-    # TODO(crbug.com/1256502): Switch back to CFv2 once the bug is fixed.
-    use_cfv2 = false
+    use_cfv2 = true
   }
 }
 
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn
index b1731400..63b65b46 100644
--- a/extensions/BUILD.gn
+++ b/extensions/BUILD.gn
@@ -9,6 +9,8 @@
 import("//tools/grit/repack.gni")
 import("//ui/base/ui_features.gni")
 
+assert(enable_extensions)
+
 assert(
     !(enable_autofill_assistant_api && is_official_build),
     "The AutofillAssistant Extension API must be disabled in official builds.")
@@ -31,359 +33,353 @@
   defines = [ "EXTENSIONS_COMPONENT_IMPLEMENTATION" ]
 }
 
-# TODO(crbug.com/731689): Assert that extensions are enabled.
-# We can't do this here directly because some platforms where extensions aren't
-# enabled depend on //extensions/common:common_constants, which in turn depends
-# on the //extensions component target in component builds.
-if (enable_extensions) {
-  group("extensions_resources") {
-    public_deps = [
-      ":extensions_browser_resources",
-      ":extensions_renderer_resources",
-      ":extensions_resources_grd",
-    ]
+group("extensions_resources") {
+  public_deps = [
+    ":extensions_browser_resources",
+    ":extensions_renderer_resources",
+    ":extensions_resources_grd",
+  ]
+}
+
+grit("extensions_resources_grd") {
+  source = "extensions_resources.grd"
+  outputs = [
+    "grit/extensions_resources.h",
+    "extensions_resources.pak",
+  ]
+}
+
+grit("extensions_browser_resources") {
+  source = "browser/resources/extensions_browser_resources.grd"
+  outputs = [
+    "grit/extensions_browser_resources.h",
+    "grit/extensions_browser_resources_map.cc",
+    "grit/extensions_browser_resources_map.h",
+    "extensions_browser_resources_100_percent.pak",
+    "extensions_browser_resources_200_percent.pak",
+  ]
+}
+
+grit("extensions_renderer_resources") {
+  source = "renderer/resources/extensions_renderer_resources.grd"
+  defines = [ "is_chromecast=$is_chromecast" ]
+  outputs = [
+    "grit/extensions_renderer_resources.h",
+    "extensions_renderer_resources.pak",
+  ]
+  grit_flags = [
+    "-E",
+    "mojom_root=" + rebase_path(root_gen_dir, root_build_dir),
+  ]
+
+  deps = [
+    "//extensions/common:mojom_js",
+    "//extensions/common/api:mojom_js",
+    "//services/device/public/mojom:mojom_js",
+  ]
+}
+
+static_library("test_support") {
+  testonly = true
+  sources = [
+    "browser/api/declarative/test_rules_registry.cc",
+    "browser/api/declarative/test_rules_registry.h",
+    "browser/api/storage/settings_test_util.cc",
+    "browser/api/storage/settings_test_util.h",
+    "browser/api_test_utils.cc",
+    "browser/api_test_utils.h",
+    "browser/api_unittest.cc",
+    "browser/api_unittest.h",
+    "browser/app_window/test_app_window_contents.cc",
+    "browser/app_window/test_app_window_contents.h",
+    "browser/content_verifier/test_utils.cc",
+    "browser/content_verifier/test_utils.h",
+    "browser/extension_error_test_util.cc",
+    "browser/extension_error_test_util.h",
+    "browser/extensions_test.cc",
+    "browser/extensions_test.h",
+    "browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc",
+    "browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h",
+    "browser/mock_extension_system.cc",
+    "browser/mock_extension_system.h",
+    "browser/mock_external_provider.cc",
+    "browser/mock_external_provider.h",
+    "browser/scoped_ignore_content_verifier_for_test.cc",
+    "browser/scoped_ignore_content_verifier_for_test.h",
+    "browser/test_event_router.cc",
+    "browser/test_event_router.h",
+    "browser/test_extension_registry_observer.cc",
+    "browser/test_extension_registry_observer.h",
+    "browser/test_extensions_browser_client.cc",
+    "browser/test_extensions_browser_client.h",
+    "browser/test_image_loader.cc",
+    "browser/test_image_loader.h",
+    "browser/test_management_policy.cc",
+    "browser/test_management_policy.h",
+    "browser/test_runtime_api_delegate.cc",
+    "browser/test_runtime_api_delegate.h",
+    "common/extension_builder.cc",
+    "common/extension_builder.h",
+    "common/manifest_test.cc",
+    "common/manifest_test.h",
+    "common/permissions/mock_manifest_permission.cc",
+    "common/permissions/mock_manifest_permission.h",
+    "common/permissions/permission_message_test_util.cc",
+    "common/permissions/permission_message_test_util.h",
+    "common/scoped_testing_manifest_handler_registry.cc",
+    "common/scoped_testing_manifest_handler_registry.h",
+    "renderer/test_extensions_renderer_client.cc",
+    "renderer/test_extensions_renderer_client.h",
+    "test/extension_background_page_waiter.cc",
+    "test/extension_background_page_waiter.h",
+    "test/extension_state_tester.cc",
+    "test/extension_state_tester.h",
+    "test/extension_test_message_listener.cc",
+    "test/extension_test_message_listener.h",
+    "test/extension_test_notification_observer.cc",
+    "test/extension_test_notification_observer.h",
+    "test/logging_timer.cc",
+    "test/logging_timer.h",
+    "test/result_catcher.cc",
+    "test/result_catcher.h",
+    "test/test_content_script_load_waiter.cc",
+    "test/test_content_script_load_waiter.h",
+    "test/test_content_utility_client.cc",
+    "test/test_content_utility_client.h",
+    "test/test_extension_dir.cc",
+    "test/test_extension_dir.h",
+    "test/test_extensions_client.cc",
+    "test/test_extensions_client.h",
+    "test/test_permission_message_provider.cc",
+    "test/test_permission_message_provider.h",
+  ]
+
+  deps = [
+    ":extensions_resources",
+    "//base",
+    "//build:chromeos_buildflags",
+    "//chrome/common:buildflags",
+    "//components/crx_file",
+    "//components/guest_view/browser:test_support",
+    "//components/keyed_service/content",
+    "//components/pref_registry",
+    "//components/prefs:test_support",
+    "//components/sync_preferences:test_support",
+    "//components/update_client",
+    "//components/user_prefs",
+    "//content/public/common",
+    "//content/test:test_support",
+    "//extensions/browser",
+    "//extensions/browser:test_support",
+    "//extensions/browser/api",
+    "//extensions/browser/updater",
+    "//extensions/common",
+    "//extensions/common:core_api_provider",
+    "//extensions/common/api",
+    "//extensions/common/api:extensions_features",
+    "//extensions/renderer",
+    "//net:test_support",
+    "//services/network/public/mojom",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/cld_3/src/src:cld_3",
+    "//third_party/zlib/google:zip",
+  ]
+
+  # Generally, //extensions should not depend on //chromeos. However, a number
+  # of the APIs and the extensions shell already do. We should try to avoid
+  # expanding these dependencies.
+  if (is_chromeos_ash) {
+    deps += [ "//chromeos/login/login_state" ]
   }
 
-  grit("extensions_resources_grd") {
-    source = "extensions_resources.grd"
-    outputs = [
-      "grit/extensions_resources.h",
-      "extensions_resources.pak",
-    ]
+  if (is_chromeos_lacros) {
+    deps += [ "//chromeos/lacros:test_support" ]
   }
 
-  grit("extensions_browser_resources") {
-    source = "browser/resources/extensions_browser_resources.grd"
-    outputs = [
-      "grit/extensions_browser_resources.h",
-      "grit/extensions_browser_resources_map.cc",
-      "grit/extensions_browser_resources_map.h",
-      "extensions_browser_resources_100_percent.pak",
-      "extensions_browser_resources_200_percent.pak",
+  public_deps = [ "//content/public/browser" ]
+}
+
+repack("shell_and_test_pak") {
+  testonly = true
+
+  sources = [
+    "$root_gen_dir/content/browser/devtools/devtools_resources.pak",
+    "$root_gen_dir/content/content_resources.pak",
+    "$root_gen_dir/content/dev_ui_content_resources.pak",
+    "$root_gen_dir/content/shell/shell_resources.pak",
+    "$root_gen_dir/device/bluetooth/strings/bluetooth_strings_en-US.pak",
+    "$root_gen_dir/extensions/extensions_browser_resources_100_percent.pak",
+    "$root_gen_dir/extensions/extensions_renderer_resources.pak",
+    "$root_gen_dir/extensions/extensions_resources.pak",
+    "$root_gen_dir/extensions/shell/app_shell_resources.pak",
+    "$root_gen_dir/extensions/strings/extensions_strings_en-US.pak",
+    "$root_gen_dir/mojo/public/js/mojo_bindings_resources.pak",
+    "$root_gen_dir/third_party/blink/public/resources/blink_resources.pak",
+    "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_100_percent.pak",
+    "$root_gen_dir/third_party/blink/public/strings/blink_strings_en-US.pak",
+    "$root_gen_dir/ui/resources/ui_resources_100_percent.pak",
+    "$root_gen_dir/ui/strings/app_locale_settings_en-US.pak",
+    "$root_gen_dir/ui/strings/ax_strings_en-US.pak",
+    "$root_gen_dir/ui/strings/ui_strings_en-US.pak",
+  ]
+
+  output = "$root_out_dir/extensions_shell_and_test.pak"
+
+  deps = [
+    ":extensions_resources",
+    "//content:content_resources",
+    "//content:dev_ui_content_resources",
+    "//content/browser/devtools:devtools_resources",
+    "//content/shell:resources",
+    "//device/bluetooth/strings",
+    "//extensions/shell:resources",
+    "//extensions/strings",
+    "//mojo/public/js:resources",
+    "//third_party/blink/public:resources",
+    "//third_party/blink/public:scaled_resources_100_percent",
+    "//third_party/blink/public/strings",
+    "//ui/resources",
+    "//ui/strings",
+  ]
+}
+
+test("extensions_unittests") {
+  use_xvfb = use_xvfb_in_this_config
+
+  sources = [
+    "test/extensions_unittests_main.cc",
+    "test/logging_timer_unittest.cc",
+  ]
+
+  data = [
+    "test/data/",
+    "//chrome/test/data/extensions/",
+    "//components/test/data/cast_certificate/",
+    "$root_out_dir/content_shell.pak",
+    "$root_out_dir/extensions_shell_and_test.pak",
+  ]
+
+  deps = [
+    ":extensions_resources",
+    ":shell_and_test_pak",
+    ":test_support",
+    "//base/test:test_support",
+    "//content/public/common",
+    "//content/test:test_support",
+    "//extensions/browser:unit_tests",
+    "//extensions/common",
+    "//extensions/common:unit_tests",
+    "//extensions/renderer:unit_tests",
+    "//extensions/shell:unit_tests",
+    "//services/data_decoder:lib",
+    "//services/service_manager/public/cpp/test:test_support",
+    "//ui/gl:test_support",
+  ]
+
+  data_deps = [
+    "//testing/buildbot/filters:extensions_unittests_filters",
+    "//third_party/mesa_headers",
+  ]
+
+  if (is_fuchsia) {
+    additional_manifest_fragments = [
+      "//build/config/fuchsia/test/jit_capabilities.test-cmx",
+      "//build/config/fuchsia/test/network_capabilities.test-cmx",
     ]
   }
+}
 
-  grit("extensions_renderer_resources") {
-    source = "renderer/resources/extensions_renderer_resources.grd"
-    defines = [ "is_chromecast=$is_chromecast" ]
-    outputs = [
-      "grit/extensions_renderer_resources.h",
-      "extensions_renderer_resources.pak",
-    ]
-    grit_flags = [
-      "-E",
-      "mojom_root=" + rebase_path(root_gen_dir, root_build_dir),
-    ]
+test("extensions_browsertests") {
+  use_xvfb = use_xvfb_in_this_config
 
-    deps = [
-      "//extensions/common:mojom_js",
-      "//extensions/common/api:mojom_js",
-      "//services/device/public/mojom:mojom_js",
-    ]
-  }
+  data = [
+    "//extensions/test/data/",
+    "//net/tools/testserver/",
+    "//third_party/pywebsocket3/src/mod_pywebsocket/",
+    "$root_out_dir/extensions_shell_and_test.pak",
+  ]
 
-  static_library("test_support") {
-    testonly = true
-    sources = [
-      "browser/api/declarative/test_rules_registry.cc",
-      "browser/api/declarative/test_rules_registry.h",
-      "browser/api/storage/settings_test_util.cc",
-      "browser/api/storage/settings_test_util.h",
-      "browser/api_test_utils.cc",
-      "browser/api_test_utils.h",
-      "browser/api_unittest.cc",
-      "browser/api_unittest.h",
-      "browser/app_window/test_app_window_contents.cc",
-      "browser/app_window/test_app_window_contents.h",
-      "browser/content_verifier/test_utils.cc",
-      "browser/content_verifier/test_utils.h",
-      "browser/extension_error_test_util.cc",
-      "browser/extension_error_test_util.h",
-      "browser/extensions_test.cc",
-      "browser/extensions_test.h",
-      "browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc",
-      "browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h",
-      "browser/mock_extension_system.cc",
-      "browser/mock_extension_system.h",
-      "browser/mock_external_provider.cc",
-      "browser/mock_external_provider.h",
-      "browser/scoped_ignore_content_verifier_for_test.cc",
-      "browser/scoped_ignore_content_verifier_for_test.h",
-      "browser/test_event_router.cc",
-      "browser/test_event_router.h",
-      "browser/test_extension_registry_observer.cc",
-      "browser/test_extension_registry_observer.h",
-      "browser/test_extensions_browser_client.cc",
-      "browser/test_extensions_browser_client.h",
-      "browser/test_image_loader.cc",
-      "browser/test_image_loader.h",
-      "browser/test_management_policy.cc",
-      "browser/test_management_policy.h",
-      "browser/test_runtime_api_delegate.cc",
-      "browser/test_runtime_api_delegate.h",
-      "common/extension_builder.cc",
-      "common/extension_builder.h",
-      "common/manifest_test.cc",
-      "common/manifest_test.h",
-      "common/permissions/mock_manifest_permission.cc",
-      "common/permissions/mock_manifest_permission.h",
-      "common/permissions/permission_message_test_util.cc",
-      "common/permissions/permission_message_test_util.h",
-      "common/scoped_testing_manifest_handler_registry.cc",
-      "common/scoped_testing_manifest_handler_registry.h",
-      "renderer/test_extensions_renderer_client.cc",
-      "renderer/test_extensions_renderer_client.h",
-      "test/extension_background_page_waiter.cc",
-      "test/extension_background_page_waiter.h",
-      "test/extension_state_tester.cc",
-      "test/extension_state_tester.h",
-      "test/extension_test_message_listener.cc",
-      "test/extension_test_message_listener.h",
-      "test/extension_test_notification_observer.cc",
-      "test/extension_test_notification_observer.h",
-      "test/logging_timer.cc",
-      "test/logging_timer.h",
-      "test/result_catcher.cc",
-      "test/result_catcher.h",
-      "test/test_content_script_load_waiter.cc",
-      "test/test_content_script_load_waiter.h",
-      "test/test_content_utility_client.cc",
-      "test/test_content_utility_client.h",
-      "test/test_extension_dir.cc",
-      "test/test_extension_dir.h",
-      "test/test_extensions_client.cc",
-      "test/test_extensions_client.h",
-      "test/test_permission_message_provider.cc",
-      "test/test_permission_message_provider.h",
-    ]
+  deps = [
+    "//extensions/browser:browser_tests",
+    "//extensions/shell:browser_tests",
+  ]
 
-    deps = [
-      ":extensions_resources",
-      "//base",
-      "//build:chromeos_buildflags",
-      "//chrome/common:buildflags",
-      "//components/crx_file",
-      "//components/guest_view/browser:test_support",
-      "//components/keyed_service/content",
-      "//components/pref_registry",
-      "//components/prefs:test_support",
-      "//components/sync_preferences:test_support",
-      "//components/update_client",
-      "//components/user_prefs",
-      "//content/public/common",
-      "//content/test:test_support",
-      "//extensions/browser",
-      "//extensions/browser:test_support",
-      "//extensions/browser/api",
-      "//extensions/browser/updater",
-      "//extensions/common",
-      "//extensions/common:core_api_provider",
-      "//extensions/common/api",
-      "//extensions/common/api:extensions_features",
-      "//extensions/renderer",
-      "//net:test_support",
-      "//services/network/public/mojom",
-      "//testing/gmock",
-      "//testing/gtest",
-      "//third_party/cld_3/src/src:cld_3",
-      "//third_party/zlib/google:zip",
-    ]
+  data_deps = [ "//third_party/mesa_headers" ]
+}
 
-    # Generally, //extensions should not depend on //chromeos. However, a number
-    # of the APIs and the extensions shell already do. We should try to avoid
-    # expanding these dependencies.
-    if (is_chromeos_ash) {
-      deps += [ "//chromeos/login/login_state" ]
-    }
+# TODO(rockot) bug 505926: These should be moved to extensions_browsertests but have
+# old dependencies on chrome files. The chrome dependencies should be removed
+# and these moved to the extensions_browsertests target. Currently, we solve
+# the problem by making this a source set and linking it into
+# //chrome/test:browser_tests.
+source_set("chrome_extensions_browsertests") {
+  testonly = true
+  sources = [
+    "browser/api/app_window/app_window_apitest.cc",
+    "browser/api/bluetooth/bluetooth_apitest.cc",
+    "browser/api/bluetooth/bluetooth_private_apitest.cc",
+    "browser/api/serial/serial_apitest.cc",
+    "browser/api/usb/usb_manual_apitest.cc",
+    "browser/app_window/app_window_browsertest.cc",
+    "browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc",
+    "renderer/script_context_browsertest.cc",
+  ]
 
-    if (is_chromeos_lacros) {
-      deps += [ "//chromeos/lacros:test_support" ]
-    }
+  defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
 
-    public_deps = [ "//content/public/browser" ]
-  }
+  # These are the deps from browser_tests minus some internal Chrome ones that
+  # aren't allowed to be included here and that aren't needed.
+  deps = [
+    "//base",
+    "//base:i18n",
+    "//base/test:test_support",
+    "//build:chromeos_buildflags",
+    "//chrome/browser",
+    "//chrome/common/extensions/api",
+    "//chrome/renderer",
+    "//chrome/test:test_support",
+    "//components/autofill/content/browser:risk_proto",
+    "//components/autofill/content/renderer:test_support",
+    "//components/captive_portal/core:test_support",
+    "//components/dom_distiller/content/browser",
+    "//components/dom_distiller/core:test_support",
+    "//components/guest_view/browser:test_support",
+    "//components/javascript_dialogs",
+    "//components/resources",
+    "//components/strings",
+    "//components/sync",
+    "//components/sync:test_support_model",
+    "//components/translate/core/common",
+    "//crypto:platform",
+    "//crypto:test_support",
+    "//device/bluetooth:mocks",
+    "//extensions/browser/api/bluetooth",
+    "//extensions/common/api",
+    "//extensions/renderer",
+    "//google_apis:test_support",
+    "//media:test_support",
+    "//net",
+    "//net:test_support",
+    "//skia",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//testing/perf",
+    "//third_party/blink/public:blink",
+    "//third_party/icu",
+    "//third_party/leveldatabase",
+    "//third_party/libaddressinput",
+    "//third_party/webrtc_overrides:webrtc_component",
+    "//third_party/widevine/cdm:headers",
+    "//ui/accessibility:test_support",
+    "//ui/base:test_support",
+    "//ui/compositor:test_support",
+    "//ui/resources",
+    "//ui/web_dialogs:test_support",
+    "//v8",
+  ]
 
-  repack("shell_and_test_pak") {
-    testonly = true
-
-    sources = [
-      "$root_gen_dir/content/browser/devtools/devtools_resources.pak",
-      "$root_gen_dir/content/content_resources.pak",
-      "$root_gen_dir/content/dev_ui_content_resources.pak",
-      "$root_gen_dir/content/shell/shell_resources.pak",
-      "$root_gen_dir/device/bluetooth/strings/bluetooth_strings_en-US.pak",
-      "$root_gen_dir/extensions/extensions_browser_resources_100_percent.pak",
-      "$root_gen_dir/extensions/extensions_renderer_resources.pak",
-      "$root_gen_dir/extensions/extensions_resources.pak",
-      "$root_gen_dir/extensions/shell/app_shell_resources.pak",
-      "$root_gen_dir/extensions/strings/extensions_strings_en-US.pak",
-      "$root_gen_dir/mojo/public/js/mojo_bindings_resources.pak",
-      "$root_gen_dir/third_party/blink/public/resources/blink_resources.pak",
-      "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_100_percent.pak",
-      "$root_gen_dir/third_party/blink/public/strings/blink_strings_en-US.pak",
-      "$root_gen_dir/ui/resources/ui_resources_100_percent.pak",
-      "$root_gen_dir/ui/strings/app_locale_settings_en-US.pak",
-      "$root_gen_dir/ui/strings/ax_strings_en-US.pak",
-      "$root_gen_dir/ui/strings/ui_strings_en-US.pak",
-    ]
-
-    output = "$root_out_dir/extensions_shell_and_test.pak"
-
-    deps = [
-      ":extensions_resources",
-      "//content:content_resources",
-      "//content:dev_ui_content_resources",
-      "//content/browser/devtools:devtools_resources",
-      "//content/shell:resources",
-      "//device/bluetooth/strings",
-      "//extensions/shell:resources",
-      "//extensions/strings",
-      "//mojo/public/js:resources",
-      "//third_party/blink/public:resources",
-      "//third_party/blink/public:scaled_resources_100_percent",
-      "//third_party/blink/public/strings",
-      "//ui/resources",
-      "//ui/strings",
-    ]
-  }
-
-  test("extensions_unittests") {
-    use_xvfb = use_xvfb_in_this_config
-
-    sources = [
-      "test/extensions_unittests_main.cc",
-      "test/logging_timer_unittest.cc",
-    ]
-
-    data = [
-      "test/data/",
-      "//chrome/test/data/extensions/",
-      "//components/test/data/cast_certificate/",
-      "$root_out_dir/content_shell.pak",
-      "$root_out_dir/extensions_shell_and_test.pak",
-    ]
-
-    deps = [
-      ":extensions_resources",
-      ":shell_and_test_pak",
-      ":test_support",
-      "//base/test:test_support",
-      "//content/public/common",
-      "//content/test:test_support",
-      "//extensions/browser:unit_tests",
-      "//extensions/common",
-      "//extensions/common:unit_tests",
-      "//extensions/renderer:unit_tests",
-      "//extensions/shell:unit_tests",
-      "//services/data_decoder:lib",
-      "//services/service_manager/public/cpp/test:test_support",
-      "//ui/gl:test_support",
-    ]
-
-    data_deps = [
-      "//testing/buildbot/filters:extensions_unittests_filters",
-      "//third_party/mesa_headers",
-    ]
-
-    if (is_fuchsia) {
-      additional_manifest_fragments = [
-        "//build/config/fuchsia/test/jit_capabilities.test-cmx",
-        "//build/config/fuchsia/test/network_capabilities.test-cmx",
-      ]
-    }
-  }
-
-  test("extensions_browsertests") {
-    use_xvfb = use_xvfb_in_this_config
-
-    data = [
-      "//extensions/test/data/",
-      "//net/tools/testserver/",
-      "//third_party/pywebsocket3/src/mod_pywebsocket/",
-      "$root_out_dir/extensions_shell_and_test.pak",
-    ]
-
-    deps = [
-      "//extensions/browser:browser_tests",
-      "//extensions/shell:browser_tests",
-    ]
-
-    data_deps = [ "//third_party/mesa_headers" ]
-  }
-
-  # TODO(rockot) bug 505926: These should be moved to extensions_browsertests but have
-  # old dependencies on chrome files. The chrome dependencies should be removed
-  # and these moved to the extensions_browsertests target. Currently, we solve
-  # the problem by making this a source set and linking it into
-  # //chrome/test:browser_tests.
-  source_set("chrome_extensions_browsertests") {
-    testonly = true
-    sources = [
-      "browser/api/app_window/app_window_apitest.cc",
-      "browser/api/bluetooth/bluetooth_apitest.cc",
-      "browser/api/bluetooth/bluetooth_private_apitest.cc",
-      "browser/api/serial/serial_apitest.cc",
-      "browser/api/usb/usb_manual_apitest.cc",
-      "browser/app_window/app_window_browsertest.cc",
-      "browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc",
-      "renderer/script_context_browsertest.cc",
-    ]
-
-    defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
-
-    # These are the deps from browser_tests minus some internal Chrome ones that
-    # aren't allowed to be included here and that aren't needed.
-    deps = [
-      "//base",
-      "//base:i18n",
-      "//base/test:test_support",
-      "//build:chromeos_buildflags",
-      "//chrome/browser",
-      "//chrome/common/extensions/api",
-      "//chrome/renderer",
-      "//chrome/test:test_support",
-      "//components/autofill/content/browser:risk_proto",
-      "//components/autofill/content/renderer:test_support",
-      "//components/captive_portal/core:test_support",
-      "//components/dom_distiller/content/browser",
-      "//components/dom_distiller/core:test_support",
-      "//components/guest_view/browser:test_support",
-      "//components/javascript_dialogs",
-      "//components/resources",
-      "//components/strings",
-      "//components/sync",
-      "//components/sync:test_support_model",
-      "//components/translate/core/common",
-      "//crypto:platform",
-      "//crypto:test_support",
-      "//device/bluetooth:mocks",
-      "//extensions/browser/api/bluetooth",
-      "//extensions/common/api",
-      "//extensions/renderer",
-      "//google_apis:test_support",
-      "//media:test_support",
-      "//net",
-      "//net:test_support",
-      "//skia",
-      "//testing/gmock",
-      "//testing/gtest",
-      "//testing/perf",
-      "//third_party/blink/public:blink",
-      "//third_party/icu",
-      "//third_party/leveldatabase",
-      "//third_party/libaddressinput",
-      "//third_party/webrtc_overrides:webrtc_component",
-      "//third_party/widevine/cdm:headers",
-      "//ui/accessibility:test_support",
-      "//ui/base:test_support",
-      "//ui/compositor:test_support",
-      "//ui/resources",
-      "//ui/web_dialogs:test_support",
-      "//v8",
-    ]
-
-    if (is_chromeos_ash) {
-      deps += [ "//components/user_manager:test_support" ]
-    }
+  if (is_chromeos_ash) {
+    deps += [ "//components/user_manager:test_support" ]
   }
 }
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn
index f86aa01f..a2a26ee 100644
--- a/extensions/common/BUILD.gn
+++ b/extensions/common/BUILD.gn
@@ -9,7 +9,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 
-# TODO(crbug.com/731689): Assert that extensions are enabled.
+assert(enable_extensions)
 
 group("common_constants") {
   if (is_component_build) {
@@ -64,621 +64,619 @@
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 }
 
-if (enable_extensions) {
-  mojom("mojom") {
-    # We don't want Blink variants of bindings to be generated.
-    disable_variants = true
+mojom("mojom") {
+  # We don't want Blink variants of bindings to be generated.
+  disable_variants = true
 
-    sources = [
-      "mojom/activation_sequence.mojom",
-      "mojom/api_permission_id.mojom",
-      "mojom/app_window.mojom",
-      "mojom/channel.mojom",
-      "mojom/code_injection.mojom",
-      "mojom/css_origin.mojom",
-      "mojom/event_dispatcher.mojom",
-      "mojom/event_router.mojom",
-      "mojom/execution_world.mojom",
-      "mojom/feature_session_type.mojom",
-      "mojom/frame.mojom",
-      "mojom/guest_view.mojom",
-      "mojom/host_id.mojom",
-      "mojom/injection_type.mojom",
-      "mojom/keep_alive.mojom",
-      "mojom/manifest.mojom",
-      "mojom/permission_set.mojom",
-      "mojom/renderer.mojom",
-      "mojom/run_location.mojom",
-      "mojom/url_pattern_set.mojom",
-      "mojom/view_type.mojom",
-    ]
+  sources = [
+    "mojom/activation_sequence.mojom",
+    "mojom/api_permission_id.mojom",
+    "mojom/app_window.mojom",
+    "mojom/channel.mojom",
+    "mojom/code_injection.mojom",
+    "mojom/css_origin.mojom",
+    "mojom/event_dispatcher.mojom",
+    "mojom/event_router.mojom",
+    "mojom/execution_world.mojom",
+    "mojom/feature_session_type.mojom",
+    "mojom/frame.mojom",
+    "mojom/guest_view.mojom",
+    "mojom/host_id.mojom",
+    "mojom/injection_type.mojom",
+    "mojom/keep_alive.mojom",
+    "mojom/manifest.mojom",
+    "mojom/permission_set.mojom",
+    "mojom/renderer.mojom",
+    "mojom/run_location.mojom",
+    "mojom/url_pattern_set.mojom",
+    "mojom/view_type.mojom",
+  ]
 
-    public_deps = [
-      "//content/public/common:interfaces",
-      "//extensions/common/api:mojom",
-      "//mojo/public/mojom/base",
-      "//ui/gfx/geometry/mojom",
-      "//url/mojom:url_mojom_gurl",
-    ]
+  public_deps = [
+    "//content/public/common:interfaces",
+    "//extensions/common/api:mojom",
+    "//mojo/public/mojom/base",
+    "//ui/gfx/geometry/mojom",
+    "//url/mojom:url_mojom_gurl",
+  ]
 
-    cpp_typemaps = [
-      {
-        types = [
-          {
-            mojom = "extensions.mojom.Channel"
-            cpp = "version_info::Channel"
-          },
-        ]
-        traits_headers = [ "//extensions/common/mojom/channel_mojom_traits.h" ]
-        traits_public_deps = [ "//components/version_info:channel" ]
-      },
-      {
-        types = [
-          {
-            mojom = "extensions.mojom.APIPermission"
-            cpp = "::std::unique_ptr<::extensions::APIPermission>"
-            move_only = true
-          },
-          {
-            mojom = "extensions.mojom.APIPermissionSet"
-            cpp = "::extensions::APIPermissionSet"
-            move_only = true
-          },
-          {
-            mojom = "extensions.mojom.ManifestPermission"
-            cpp = "::std::unique_ptr<::extensions::ManifestPermission>"
-            move_only = true
-          },
-          {
-            mojom = "extensions.mojom.ManifestPermissionSet"
-            cpp = "::extensions::ManifestPermissionSet"
-            move_only = true
-          },
-          {
-            mojom = "extensions.mojom.PermissionSet"
-            cpp = "::extensions::PermissionSet"
-            move_only = true
-          },
-        ]
-        traits_headers =
-            [ "//extensions/common/mojom/permission_set_mojom_traits.h" ]
-        traits_sources =
-            [ "//extensions/common/mojom/permission_set_mojom_traits.cc" ]
-      },
-      {
-        types = [
-          {
-            mojom = "extensions.mojom.URLPattern"
-            cpp = "::URLPattern"
-          },
-          {
-            mojom = "extensions.mojom.URLPatternSet"
-            cpp = "::extensions::URLPatternSet"
-            move_only = true
-          },
-        ]
-        traits_headers =
-            [ "//extensions/common/mojom/url_pattern_set_mojom_traits.h" ]
-        traits_sources =
-            [ "//extensions/common/mojom/url_pattern_set_mojom_traits.cc" ]
-      },
-      {
-        types = [
-          {
-            mojom = "extensions.mojom.ActivationSequence"
-            cpp = "::extensions::ActivationSequence"
-          },
-        ]
-        traits_headers =
-            [ "//extensions/common/mojom/activation_sequence_mojom_traits.h" ]
-        traits_sources =
-            [ "//extensions/common/mojom/activation_sequence_mojom_traits.cc" ]
-      },
-      {
-        types = [
-          {
-            mojom = "extensions.mojom.EventFilteringInfo"
-            cpp = "::extensions::EventFilteringInfo"
-          },
-        ]
-        traits_headers =
-            [ "//extensions/common/mojom/event_dispatcher_mojom_traits.h" ]
-        traits_sources =
-            [ "//extensions/common/mojom/event_dispatcher_mojom_traits.cc" ]
-      },
-    ]
-    overridden_deps = [ "//content/public/common:interfaces" ]
-
-    component_deps = [ "//content/public/common" ]
-  }
-
-  # This must be a static library because extensions common depends on
-  # GetTrustedICAPublicKey in extensions/browser which isn't always linked
-  # in. TODO(brettw): This reverse dependency should be fixed.
-  static_library("common") {
-    sources = [
-      "activation_sequence.h",
-      "alias.h",
-      "api/bluetooth/bluetooth_manifest_data.cc",
-      "api/bluetooth/bluetooth_manifest_data.h",
-      "api/bluetooth/bluetooth_manifest_handler.cc",
-      "api/bluetooth/bluetooth_manifest_handler.h",
-      "api/bluetooth/bluetooth_manifest_permission.cc",
-      "api/bluetooth/bluetooth_manifest_permission.h",
-      "api/declarative/declarative_constants.cc",
-      "api/declarative/declarative_constants.h",
-      "api/declarative/declarative_manifest_data.cc",
-      "api/declarative/declarative_manifest_data.h",
-      "api/declarative/declarative_manifest_handler.cc",
-      "api/declarative/declarative_manifest_handler.h",
-      "api/declarative_net_request/constants.cc",
-      "api/declarative_net_request/constants.h",
-      "api/declarative_net_request/dnr_manifest_data.cc",
-      "api/declarative_net_request/dnr_manifest_data.h",
-      "api/declarative_net_request/dnr_manifest_handler.cc",
-      "api/declarative_net_request/dnr_manifest_handler.h",
-      "api/extension_action/action_info.cc",
-      "api/extension_action/action_info.h",
-      "api/messaging/message.h",
-      "api/messaging/messaging_endpoint.cc",
-      "api/messaging/messaging_endpoint.h",
-      "api/messaging/port_context.cc",
-      "api/messaging/port_context.h",
-      "api/messaging/port_id.cc",
-      "api/messaging/port_id.h",
-      "api/printer_provider/usb_printer_manifest_data.cc",
-      "api/printer_provider/usb_printer_manifest_data.h",
-      "api/printer_provider/usb_printer_manifest_handler.cc",
-      "api/printer_provider/usb_printer_manifest_handler.h",
-      "api/sockets/sockets_manifest_data.cc",
-      "api/sockets/sockets_manifest_data.h",
-      "api/sockets/sockets_manifest_handler.cc",
-      "api/sockets/sockets_manifest_handler.h",
-      "api/sockets/sockets_manifest_permission.cc",
-      "api/sockets/sockets_manifest_permission.h",
-      "common_manifest_handlers.cc",
-      "common_manifest_handlers.h",
-      "common_param_traits.h",
-      "content_script_injection_url_getter.cc",
-      "content_script_injection_url_getter.h",
-      "cors_util.cc",
-      "cors_util.h",
-      "csp_validator.cc",
-      "csp_validator.h",
-      "dom_action_types.h",
-      "draggable_region.cc",
-      "draggable_region.h",
-      "error_utils.cc",
-      "error_utils.h",
-      "event_filter.cc",
-      "event_filter.h",
-      "event_filtering_info.cc",
-      "event_filtering_info.h",
-      "event_filtering_info_type_converters.cc",
-      "event_filtering_info_type_converters.h",
-      "event_matcher.cc",
-      "event_matcher.h",
-      "extension.cc",
-      "extension.h",
-      "extension_api.cc",
-      "extension_api.h",
-      "extension_features.cc",
-      "extension_features.h",
-      "extension_icon_set.cc",
-      "extension_icon_set.h",
-      "extension_id.h",
-      "extension_l10n_util.cc",
-      "extension_l10n_util.h",
-      "extension_message_generator.cc",
-      "extension_message_generator.h",
-      "extension_messages.h",
-      "extension_paths.cc",
-      "extension_paths.h",
-      "extension_resource.cc",
-      "extension_resource.h",
-      "extension_resource_path_normalizer.cc",
-      "extension_resource_path_normalizer.h",
-      "extension_set.cc",
-      "extension_set.h",
-      "extension_updater_uma.h",
-      "extension_urls.cc",
-      "extension_urls.h",
-      "extension_utility_types.h",
-      "extensions_client.cc",
-      "extensions_client.h",
-      "feature_switch.cc",
-      "feature_switch.h",
-      "features/behavior_feature.cc",
-      "features/behavior_feature.h",
-      "features/complex_feature.cc",
-      "features/complex_feature.h",
-      "features/feature.cc",
-      "features/feature.h",
-      "features/feature_channel.cc",
-      "features/feature_channel.h",
-      "features/feature_developer_mode_only.cc",
-      "features/feature_developer_mode_only.h",
-      "features/feature_flags.cc",
-      "features/feature_flags.h",
-      "features/feature_provider.cc",
-      "features/feature_provider.h",
-      "features/feature_session_type.cc",
-      "features/feature_session_type.h",
-      "features/json_feature_provider_source.cc",
-      "features/json_feature_provider_source.h",
-      "features/manifest_feature.cc",
-      "features/manifest_feature.h",
-      "features/permission_feature.cc",
-      "features/permission_feature.h",
-      "features/simple_feature.cc",
-      "features/simple_feature.h",
-      "file_util.cc",
-      "file_util.h",
-      "hashed_extension_id.cc",
-      "hashed_extension_id.h",
-      "identifiability_metrics.cc",
-      "identifiability_metrics.h",
-      "image_util.cc",
-      "image_util.h",
-      "install_warning.cc",
-      "install_warning.h",
-      "manifest.cc",
-      "manifest.h",
-      "manifest_constants.cc",
-      "manifest_constants.h",
-      "manifest_handler.cc",
-      "manifest_handler.h",
-      "manifest_handler_helpers.cc",
-      "manifest_handler_helpers.h",
-      "manifest_handlers/app_isolation_info.cc",
-      "manifest_handlers/app_isolation_info.h",
-      "manifest_handlers/automation.cc",
-      "manifest_handlers/automation.h",
-      "manifest_handlers/background_info.cc",
-      "manifest_handlers/background_info.h",
-      "manifest_handlers/content_capabilities_handler.cc",
-      "manifest_handlers/content_capabilities_handler.h",
-      "manifest_handlers/content_scripts_handler.cc",
-      "manifest_handlers/content_scripts_handler.h",
-      "manifest_handlers/cross_origin_isolation_info.cc",
-      "manifest_handlers/cross_origin_isolation_info.h",
-      "manifest_handlers/csp_info.cc",
-      "manifest_handlers/csp_info.h",
-      "manifest_handlers/default_locale_handler.cc",
-      "manifest_handlers/default_locale_handler.h",
-      "manifest_handlers/extension_action_handler.cc",
-      "manifest_handlers/extension_action_handler.h",
-      "manifest_handlers/externally_connectable.cc",
-      "manifest_handlers/externally_connectable.h",
-      "manifest_handlers/file_handler_info.cc",
-      "manifest_handlers/file_handler_info.h",
-      "manifest_handlers/icons_handler.cc",
-      "manifest_handlers/icons_handler.h",
-      "manifest_handlers/incognito_info.cc",
-      "manifest_handlers/incognito_info.h",
-      "manifest_handlers/kiosk_mode_info.cc",
-      "manifest_handlers/kiosk_mode_info.h",
-      "manifest_handlers/mime_types_handler.cc",
-      "manifest_handlers/mime_types_handler.h",
-      "manifest_handlers/oauth2_manifest_handler.cc",
-      "manifest_handlers/oauth2_manifest_handler.h",
-      "manifest_handlers/offline_enabled_info.cc",
-      "manifest_handlers/offline_enabled_info.h",
-      "manifest_handlers/options_page_info.cc",
-      "manifest_handlers/options_page_info.h",
-      "manifest_handlers/permissions_parser.cc",
-      "manifest_handlers/permissions_parser.h",
-      "manifest_handlers/replacement_apps.cc",
-      "manifest_handlers/replacement_apps.h",
-      "manifest_handlers/requirements_info.cc",
-      "manifest_handlers/requirements_info.h",
-      "manifest_handlers/sandboxed_page_info.cc",
-      "manifest_handlers/sandboxed_page_info.h",
-      "manifest_handlers/shared_module_info.cc",
-      "manifest_handlers/shared_module_info.h",
-      "manifest_handlers/web_accessible_resources_info.cc",
-      "manifest_handlers/web_accessible_resources_info.h",
-      "manifest_handlers/webview_info.cc",
-      "manifest_handlers/webview_info.h",
-      "manifest_url_handlers.cc",
-      "manifest_url_handlers.h",
-      "message_bundle.cc",
-      "message_bundle.h",
-      "permissions/api_permission.cc",
-      "permissions/api_permission.h",
-      "permissions/api_permission_set.cc",
-      "permissions/api_permission_set.h",
-      "permissions/base_set_operators.h",
-      "permissions/extensions_api_permissions.cc",
-      "permissions/extensions_api_permissions.h",
-      "permissions/manifest_permission.cc",
-      "permissions/manifest_permission.h",
-      "permissions/manifest_permission_set.cc",
-      "permissions/manifest_permission_set.h",
-      "permissions/permission_message.cc",
-      "permissions/permission_message.h",
-      "permissions/permission_message_provider.cc",
-      "permissions/permission_message_provider.h",
-      "permissions/permission_message_util.cc",
-      "permissions/permission_message_util.h",
-      "permissions/permission_set.cc",
-      "permissions/permission_set.h",
-      "permissions/permissions_data.cc",
-      "permissions/permissions_data.h",
-      "permissions/permissions_info.cc",
-      "permissions/permissions_info.h",
-      "permissions/set_disjunction_permission.h",
-      "permissions/settings_override_permission.cc",
-      "permissions/settings_override_permission.h",
-      "permissions/socket_permission.cc",
-      "permissions/socket_permission.h",
-      "permissions/socket_permission_data.cc",
-      "permissions/socket_permission_data.h",
-      "permissions/socket_permission_entry.cc",
-      "permissions/socket_permission_entry.h",
-      "permissions/usb_device_permission.cc",
-      "permissions/usb_device_permission.h",
-      "permissions/usb_device_permission_data.cc",
-      "permissions/usb_device_permission_data.h",
-      "script_constants.h",
-      "stack_frame.cc",
-      "stack_frame.h",
-      "switches.cc",
-      "switches.h",
-      "trace_util.cc",
-      "trace_util.h",
-      "url_pattern.cc",
-      "url_pattern.h",
-      "url_pattern_set.cc",
-      "url_pattern_set.h",
-      "user_script.cc",
-      "user_script.h",
-      "utils/base_string.cc",
-      "utils/base_string.h",
-      "utils/content_script_utils.cc",
-      "utils/content_script_utils.h",
-      "value_builder.cc",
-      "value_builder.h",
-      "value_counter.cc",
-      "value_counter.h",
-      "verifier_formats.cc",
-      "verifier_formats.h",
-      "view_type_util.cc",
-      "view_type_util.h",
-    ]
-
-    configs += [
-      "//build/config:precompiled_headers",
-      "//build/config/compiler:wexit_time_destructors",
-    ]
-
-    public_deps = [
-      ":common_constants",
-      ":mojom",
-      "//components/services/app_service/public/cpp:app_file_handling",
-      "//content/public/common",
-      "//ipc",
-      "//skia",
-    ]
-
-    # Allows including manifest_handler.h and permissions/permissions_info.h
-    # from mojom/permission_set_mojom_traits.cc.
-    allow_circular_includes_from = [ ":mojom" ]
-
-    deps = [
-      "//base",
-      "//build:branding_buildflags",
-      "//build:chromeos_buildflags",
-      "//components/crx_file",
-      "//components/nacl/common:buildflags",
-      "//components/url_formatter",
-      "//components/url_matcher",
-      "//components/version_info",
-      "//crypto",
-      "//device/bluetooth",
-      "//device/bluetooth/public/cpp",
-      "//extensions:extensions_resources",
-      "//extensions/common:mojom",
-      "//extensions/common/api",
-      "//extensions/strings",
-      "//net",
-      "//services/device/public/cpp/usb",
-      "//services/device/public/mojom:usb",
-      "//services/network/public/mojom",
-      "//third_party/boringssl",
-      "//third_party/icu",
-      "//third_party/re2",
-      "//third_party/zlib/google:compression_utils",
-      "//tools/json_schema_compiler:generated_api_util",
-      "//ui/base",
-      "//ui/gfx/geometry",
-      "//ui/gfx/ipc",
-      "//ui/gfx/ipc/geometry",
-      "//ui/gfx/ipc/skia",
-      "//url",
-    ]
-
-    if (enable_nacl) {
-      sources += [
-        "manifest_handlers/nacl_modules_handler.cc",
-        "manifest_handlers/nacl_modules_handler.h",
+  cpp_typemaps = [
+    {
+      types = [
+        {
+          mojom = "extensions.mojom.Channel"
+          cpp = "version_info::Channel"
+        },
       ]
-    }
-
-    if (is_chromeos_ash) {
-      sources += [
-        "manifest_handlers/action_handlers_handler.cc",
-        "manifest_handlers/action_handlers_handler.h",
+      traits_headers = [ "//extensions/common/mojom/channel_mojom_traits.h" ]
+      traits_public_deps = [ "//components/version_info:channel" ]
+    },
+    {
+      types = [
+        {
+          mojom = "extensions.mojom.APIPermission"
+          cpp = "::std::unique_ptr<::extensions::APIPermission>"
+          move_only = true
+        },
+        {
+          mojom = "extensions.mojom.APIPermissionSet"
+          cpp = "::extensions::APIPermissionSet"
+          move_only = true
+        },
+        {
+          mojom = "extensions.mojom.ManifestPermission"
+          cpp = "::std::unique_ptr<::extensions::ManifestPermission>"
+          move_only = true
+        },
+        {
+          mojom = "extensions.mojom.ManifestPermissionSet"
+          cpp = "::extensions::ManifestPermissionSet"
+          move_only = true
+        },
+        {
+          mojom = "extensions.mojom.PermissionSet"
+          cpp = "::extensions::PermissionSet"
+          move_only = true
+        },
       ]
-    }
-  }
+      traits_headers =
+          [ "//extensions/common/mojom/permission_set_mojom_traits.h" ]
+      traits_sources =
+          [ "//extensions/common/mojom/permission_set_mojom_traits.cc" ]
+    },
+    {
+      types = [
+        {
+          mojom = "extensions.mojom.URLPattern"
+          cpp = "::URLPattern"
+        },
+        {
+          mojom = "extensions.mojom.URLPatternSet"
+          cpp = "::extensions::URLPatternSet"
+          move_only = true
+        },
+      ]
+      traits_headers =
+          [ "//extensions/common/mojom/url_pattern_set_mojom_traits.h" ]
+      traits_sources =
+          [ "//extensions/common/mojom/url_pattern_set_mojom_traits.cc" ]
+    },
+    {
+      types = [
+        {
+          mojom = "extensions.mojom.ActivationSequence"
+          cpp = "::extensions::ActivationSequence"
+        },
+      ]
+      traits_headers =
+          [ "//extensions/common/mojom/activation_sequence_mojom_traits.h" ]
+      traits_sources =
+          [ "//extensions/common/mojom/activation_sequence_mojom_traits.cc" ]
+    },
+    {
+      types = [
+        {
+          mojom = "extensions.mojom.EventFilteringInfo"
+          cpp = "::extensions::EventFilteringInfo"
+        },
+      ]
+      traits_headers =
+          [ "//extensions/common/mojom/event_dispatcher_mojom_traits.h" ]
+      traits_sources =
+          [ "//extensions/common/mojom/event_dispatcher_mojom_traits.cc" ]
+    },
+  ]
+  overridden_deps = [ "//content/public/common:interfaces" ]
 
-  # NOTE: This is separate from ":common" because it depends on
-  # extensions/common/api:extensions_features, which in turn depends on
-  # :common.
-  source_set("core_api_provider") {
-    sources = [
-      "core_extensions_api_provider.cc",
-      "core_extensions_api_provider.h",
-    ]
+  component_deps = [ "//content/public/common" ]
+}
 
-    configs += [ "//build/config/compiler:wexit_time_destructors" ]
-    deps = [
-      ":common",
-      "//extensions:extensions_resources",
-      "//extensions/common/api",
-      "//extensions/common/api:extensions_features",
+# This must be a static library because extensions common depends on
+# GetTrustedICAPublicKey in extensions/browser which isn't always linked
+# in. TODO(brettw): This reverse dependency should be fixed.
+static_library("common") {
+  sources = [
+    "activation_sequence.h",
+    "alias.h",
+    "api/bluetooth/bluetooth_manifest_data.cc",
+    "api/bluetooth/bluetooth_manifest_data.h",
+    "api/bluetooth/bluetooth_manifest_handler.cc",
+    "api/bluetooth/bluetooth_manifest_handler.h",
+    "api/bluetooth/bluetooth_manifest_permission.cc",
+    "api/bluetooth/bluetooth_manifest_permission.h",
+    "api/declarative/declarative_constants.cc",
+    "api/declarative/declarative_constants.h",
+    "api/declarative/declarative_manifest_data.cc",
+    "api/declarative/declarative_manifest_data.h",
+    "api/declarative/declarative_manifest_handler.cc",
+    "api/declarative/declarative_manifest_handler.h",
+    "api/declarative_net_request/constants.cc",
+    "api/declarative_net_request/constants.h",
+    "api/declarative_net_request/dnr_manifest_data.cc",
+    "api/declarative_net_request/dnr_manifest_data.h",
+    "api/declarative_net_request/dnr_manifest_handler.cc",
+    "api/declarative_net_request/dnr_manifest_handler.h",
+    "api/extension_action/action_info.cc",
+    "api/extension_action/action_info.h",
+    "api/messaging/message.h",
+    "api/messaging/messaging_endpoint.cc",
+    "api/messaging/messaging_endpoint.h",
+    "api/messaging/port_context.cc",
+    "api/messaging/port_context.h",
+    "api/messaging/port_id.cc",
+    "api/messaging/port_id.h",
+    "api/printer_provider/usb_printer_manifest_data.cc",
+    "api/printer_provider/usb_printer_manifest_data.h",
+    "api/printer_provider/usb_printer_manifest_handler.cc",
+    "api/printer_provider/usb_printer_manifest_handler.h",
+    "api/sockets/sockets_manifest_data.cc",
+    "api/sockets/sockets_manifest_data.h",
+    "api/sockets/sockets_manifest_handler.cc",
+    "api/sockets/sockets_manifest_handler.h",
+    "api/sockets/sockets_manifest_permission.cc",
+    "api/sockets/sockets_manifest_permission.h",
+    "common_manifest_handlers.cc",
+    "common_manifest_handlers.h",
+    "common_param_traits.h",
+    "content_script_injection_url_getter.cc",
+    "content_script_injection_url_getter.h",
+    "cors_util.cc",
+    "cors_util.h",
+    "csp_validator.cc",
+    "csp_validator.h",
+    "dom_action_types.h",
+    "draggable_region.cc",
+    "draggable_region.h",
+    "error_utils.cc",
+    "error_utils.h",
+    "event_filter.cc",
+    "event_filter.h",
+    "event_filtering_info.cc",
+    "event_filtering_info.h",
+    "event_filtering_info_type_converters.cc",
+    "event_filtering_info_type_converters.h",
+    "event_matcher.cc",
+    "event_matcher.h",
+    "extension.cc",
+    "extension.h",
+    "extension_api.cc",
+    "extension_api.h",
+    "extension_features.cc",
+    "extension_features.h",
+    "extension_icon_set.cc",
+    "extension_icon_set.h",
+    "extension_id.h",
+    "extension_l10n_util.cc",
+    "extension_l10n_util.h",
+    "extension_message_generator.cc",
+    "extension_message_generator.h",
+    "extension_messages.h",
+    "extension_paths.cc",
+    "extension_paths.h",
+    "extension_resource.cc",
+    "extension_resource.h",
+    "extension_resource_path_normalizer.cc",
+    "extension_resource_path_normalizer.h",
+    "extension_set.cc",
+    "extension_set.h",
+    "extension_updater_uma.h",
+    "extension_urls.cc",
+    "extension_urls.h",
+    "extension_utility_types.h",
+    "extensions_client.cc",
+    "extensions_client.h",
+    "feature_switch.cc",
+    "feature_switch.h",
+    "features/behavior_feature.cc",
+    "features/behavior_feature.h",
+    "features/complex_feature.cc",
+    "features/complex_feature.h",
+    "features/feature.cc",
+    "features/feature.h",
+    "features/feature_channel.cc",
+    "features/feature_channel.h",
+    "features/feature_developer_mode_only.cc",
+    "features/feature_developer_mode_only.h",
+    "features/feature_flags.cc",
+    "features/feature_flags.h",
+    "features/feature_provider.cc",
+    "features/feature_provider.h",
+    "features/feature_session_type.cc",
+    "features/feature_session_type.h",
+    "features/json_feature_provider_source.cc",
+    "features/json_feature_provider_source.h",
+    "features/manifest_feature.cc",
+    "features/manifest_feature.h",
+    "features/permission_feature.cc",
+    "features/permission_feature.h",
+    "features/simple_feature.cc",
+    "features/simple_feature.h",
+    "file_util.cc",
+    "file_util.h",
+    "hashed_extension_id.cc",
+    "hashed_extension_id.h",
+    "identifiability_metrics.cc",
+    "identifiability_metrics.h",
+    "image_util.cc",
+    "image_util.h",
+    "install_warning.cc",
+    "install_warning.h",
+    "manifest.cc",
+    "manifest.h",
+    "manifest_constants.cc",
+    "manifest_constants.h",
+    "manifest_handler.cc",
+    "manifest_handler.h",
+    "manifest_handler_helpers.cc",
+    "manifest_handler_helpers.h",
+    "manifest_handlers/app_isolation_info.cc",
+    "manifest_handlers/app_isolation_info.h",
+    "manifest_handlers/automation.cc",
+    "manifest_handlers/automation.h",
+    "manifest_handlers/background_info.cc",
+    "manifest_handlers/background_info.h",
+    "manifest_handlers/content_capabilities_handler.cc",
+    "manifest_handlers/content_capabilities_handler.h",
+    "manifest_handlers/content_scripts_handler.cc",
+    "manifest_handlers/content_scripts_handler.h",
+    "manifest_handlers/cross_origin_isolation_info.cc",
+    "manifest_handlers/cross_origin_isolation_info.h",
+    "manifest_handlers/csp_info.cc",
+    "manifest_handlers/csp_info.h",
+    "manifest_handlers/default_locale_handler.cc",
+    "manifest_handlers/default_locale_handler.h",
+    "manifest_handlers/extension_action_handler.cc",
+    "manifest_handlers/extension_action_handler.h",
+    "manifest_handlers/externally_connectable.cc",
+    "manifest_handlers/externally_connectable.h",
+    "manifest_handlers/file_handler_info.cc",
+    "manifest_handlers/file_handler_info.h",
+    "manifest_handlers/icons_handler.cc",
+    "manifest_handlers/icons_handler.h",
+    "manifest_handlers/incognito_info.cc",
+    "manifest_handlers/incognito_info.h",
+    "manifest_handlers/kiosk_mode_info.cc",
+    "manifest_handlers/kiosk_mode_info.h",
+    "manifest_handlers/mime_types_handler.cc",
+    "manifest_handlers/mime_types_handler.h",
+    "manifest_handlers/oauth2_manifest_handler.cc",
+    "manifest_handlers/oauth2_manifest_handler.h",
+    "manifest_handlers/offline_enabled_info.cc",
+    "manifest_handlers/offline_enabled_info.h",
+    "manifest_handlers/options_page_info.cc",
+    "manifest_handlers/options_page_info.h",
+    "manifest_handlers/permissions_parser.cc",
+    "manifest_handlers/permissions_parser.h",
+    "manifest_handlers/replacement_apps.cc",
+    "manifest_handlers/replacement_apps.h",
+    "manifest_handlers/requirements_info.cc",
+    "manifest_handlers/requirements_info.h",
+    "manifest_handlers/sandboxed_page_info.cc",
+    "manifest_handlers/sandboxed_page_info.h",
+    "manifest_handlers/shared_module_info.cc",
+    "manifest_handlers/shared_module_info.h",
+    "manifest_handlers/web_accessible_resources_info.cc",
+    "manifest_handlers/web_accessible_resources_info.h",
+    "manifest_handlers/webview_info.cc",
+    "manifest_handlers/webview_info.h",
+    "manifest_url_handlers.cc",
+    "manifest_url_handlers.h",
+    "message_bundle.cc",
+    "message_bundle.h",
+    "permissions/api_permission.cc",
+    "permissions/api_permission.h",
+    "permissions/api_permission_set.cc",
+    "permissions/api_permission_set.h",
+    "permissions/base_set_operators.h",
+    "permissions/extensions_api_permissions.cc",
+    "permissions/extensions_api_permissions.h",
+    "permissions/manifest_permission.cc",
+    "permissions/manifest_permission.h",
+    "permissions/manifest_permission_set.cc",
+    "permissions/manifest_permission_set.h",
+    "permissions/permission_message.cc",
+    "permissions/permission_message.h",
+    "permissions/permission_message_provider.cc",
+    "permissions/permission_message_provider.h",
+    "permissions/permission_message_util.cc",
+    "permissions/permission_message_util.h",
+    "permissions/permission_set.cc",
+    "permissions/permission_set.h",
+    "permissions/permissions_data.cc",
+    "permissions/permissions_data.h",
+    "permissions/permissions_info.cc",
+    "permissions/permissions_info.h",
+    "permissions/set_disjunction_permission.h",
+    "permissions/settings_override_permission.cc",
+    "permissions/settings_override_permission.h",
+    "permissions/socket_permission.cc",
+    "permissions/socket_permission.h",
+    "permissions/socket_permission_data.cc",
+    "permissions/socket_permission_data.h",
+    "permissions/socket_permission_entry.cc",
+    "permissions/socket_permission_entry.h",
+    "permissions/usb_device_permission.cc",
+    "permissions/usb_device_permission.h",
+    "permissions/usb_device_permission_data.cc",
+    "permissions/usb_device_permission_data.h",
+    "script_constants.h",
+    "stack_frame.cc",
+    "stack_frame.h",
+    "switches.cc",
+    "switches.h",
+    "trace_util.cc",
+    "trace_util.h",
+    "url_pattern.cc",
+    "url_pattern.h",
+    "url_pattern_set.cc",
+    "url_pattern_set.h",
+    "user_script.cc",
+    "user_script.h",
+    "utils/base_string.cc",
+    "utils/base_string.h",
+    "utils/content_script_utils.cc",
+    "utils/content_script_utils.h",
+    "value_builder.cc",
+    "value_builder.h",
+    "value_counter.cc",
+    "value_counter.h",
+    "verifier_formats.cc",
+    "verifier_formats.h",
+    "view_type_util.cc",
+    "view_type_util.h",
+  ]
+
+  configs += [
+    "//build/config:precompiled_headers",
+    "//build/config/compiler:wexit_time_destructors",
+  ]
+
+  public_deps = [
+    ":common_constants",
+    ":mojom",
+    "//components/services/app_service/public/cpp:app_file_handling",
+    "//content/public/common",
+    "//ipc",
+    "//skia",
+  ]
+
+  # Allows including manifest_handler.h and permissions/permissions_info.h
+  # from mojom/permission_set_mojom_traits.cc.
+  allow_circular_includes_from = [ ":mojom" ]
+
+  deps = [
+    "//base",
+    "//build:branding_buildflags",
+    "//build:chromeos_buildflags",
+    "//components/crx_file",
+    "//components/nacl/common:buildflags",
+    "//components/url_formatter",
+    "//components/url_matcher",
+    "//components/version_info",
+    "//crypto",
+    "//device/bluetooth",
+    "//device/bluetooth/public/cpp",
+    "//extensions:extensions_resources",
+    "//extensions/common:mojom",
+    "//extensions/common/api",
+    "//extensions/strings",
+    "//net",
+    "//services/device/public/cpp/usb",
+    "//services/device/public/mojom:usb",
+    "//services/network/public/mojom",
+    "//third_party/boringssl",
+    "//third_party/icu",
+    "//third_party/re2",
+    "//third_party/zlib/google:compression_utils",
+    "//tools/json_schema_compiler:generated_api_util",
+    "//ui/base",
+    "//ui/gfx/geometry",
+    "//ui/gfx/ipc",
+    "//ui/gfx/ipc/geometry",
+    "//ui/gfx/ipc/skia",
+    "//url",
+  ]
+
+  if (enable_nacl) {
+    sources += [
+      "manifest_handlers/nacl_modules_handler.cc",
+      "manifest_handlers/nacl_modules_handler.h",
     ]
   }
 
-  source_set("test_support") {
-    testonly = true
-
-    sources = [
-      "api/declarative_net_request/test_utils.cc",
-      "api/declarative_net_request/test_utils.h",
-      "api/extension_action/action_info_test_util.cc",
-      "api/extension_action/action_info_test_util.h",
-      "file_test_util.cc",
-      "file_test_util.h",
-    ]
-
-    deps = [
-      ":common",
-      "//base",
-      "//components/version_info:channel",
-      "//extensions/common/api",
+  if (is_chromeos_ash) {
+    sources += [
+      "manifest_handlers/action_handlers_handler.cc",
+      "manifest_handlers/action_handlers_handler.h",
     ]
   }
+}
 
-  source_set("unit_tests") {
-    testonly = true
-    sources = [
-      "api/declarative/declarative_manifest_unittest.cc",
-      "api/declarative_net_request/dnr_manifest_unittest.cc",
-      "api/printer_provider/usb_printer_manifest_unittest.cc",
-      "api/sockets/sockets_manifest_permission_unittest.cc",
-      "component_extension_url_pattern_unittest.cc",
-      "csp_validator_unittest.cc",
-      "error_utils_unittest.cc",
-      "event_filter_unittest.cc",
-      "extension_builder_unittest.cc",
-      "extension_icon_set_unittest.cc",
-      "extension_l10n_util_unittest.cc",
-      "extension_resource_path_normalizer_unittest.cc",
-      "extension_resource_unittest.cc",
-      "extension_set_unittest.cc",
-      "extension_unittest.cc",
-      "feature_switch_unittest.cc",
-      "features/complex_feature_unittest.cc",
-      "features/feature_provider_unittest.cc",
-      "features/simple_feature_unittest.cc",
-      "file_util_unittest.cc",
-      "hashed_extension_id_unittest.cc",
-      "image_util_unittest.cc",
-      "manifest_handler_perf_test.cc",
-      "manifest_handler_unittest.cc",
-      "manifest_handlers/content_capabilities_manifest_unittest.cc",
-      "manifest_handlers/csp_info_unittest.cc",
-      "manifest_handlers/default_locale_manifest_unittest.cc",
-      "manifest_handlers/extension_action_handler_unittest.cc",
-      "manifest_handlers/externally_connectable_unittest.cc",
-      "manifest_handlers/file_handler_manifest_unittest.cc",
-      "manifest_handlers/icons_handler_unittest.cc",
-      "manifest_handlers/incognito_manifest_unittest.cc",
-      "manifest_handlers/kiosk_mode_info_unittest.cc",
-      "manifest_handlers/manifest_v3_permissions_unittest.cc",
-      "manifest_handlers/oauth2_manifest_unittest.cc",
-      "manifest_handlers/replacement_apps_unittest.cc",
-      "manifest_handlers/shared_module_manifest_unittest.cc",
-      "manifest_unittest.cc",
-      "message_bundle_unittest.cc",
-      "mojom/permission_set_mojom_traits_unittest.cc",
-      "mojom/url_pattern_set_mojom_traits_unittest.cc",
-      "permissions/api_permission_set_unittest.cc",
-      "permissions/api_permission_unittest.cc",
-      "permissions/base_set_operators_unittest.cc",
-      "permissions/manifest_permission_set_unittest.cc",
-      "permissions/socket_permission_unittest.cc",
-      "permissions/usb_device_permission_unittest.cc",
-      "stack_frame_unittest.cc",
-      "url_pattern_set_unittest.cc",
-      "url_pattern_unittest.cc",
-      "user_script_unittest.cc",
-      "value_builder_unittest.cc",
-      "value_counter_unittest.cc",
-    ]
+# NOTE: This is separate from ":common" because it depends on
+# extensions/common/api:extensions_features, which in turn depends on
+# :common.
+source_set("core_api_provider") {
+  sources = [
+    "core_extensions_api_provider.cc",
+    "core_extensions_api_provider.h",
+  ]
 
-    deps = [
-      ":common",
-      ":test_support",
-      "//base",
-      "//base:i18n",
-      "//base/test:test_support",
-      "//components/crx_file",
-      "//components/version_info:version_info",
-      "//content/test:test_support",
-      "//extensions:extensions_resources",
-      "//extensions/common:mojom",
-      "//extensions/common/api",
-      "//mojo/public/cpp/test_support:test_utils",
-      "//tools/json_schema_compiler:generated_api_util",
+  configs += [ "//build/config/compiler:wexit_time_destructors" ]
+  deps = [
+    ":common",
+    "//extensions:extensions_resources",
+    "//extensions/common/api",
+    "//extensions/common/api:extensions_features",
+  ]
+}
 
-      # TODO(brettw) these tests should not be including headers from browser.
-      "//extensions:test_support",
-      "//extensions/browser",
-      "//extensions/strings",
-      "//ipc",
-      "//services/device/public/cpp:test_support",
-      "//testing/gmock",
-      "//testing/gtest",
-      "//third_party/zlib/google:compression_utils",
-      "//ui/base",
-      "//ui/gfx",
-      "//url",
-    ]
+source_set("test_support") {
+  testonly = true
 
-    if (is_chromeos_ash) {
-      sources += [ "manifest_handlers/action_handlers_handler_unittest.cc" ]
-    }
+  sources = [
+    "api/declarative_net_request/test_utils.cc",
+    "api/declarative_net_request/test_utils.h",
+    "api/extension_action/action_info_test_util.cc",
+    "api/extension_action/action_info_test_util.h",
+    "file_test_util.cc",
+    "file_test_util.h",
+  ]
 
-    data = [
-      "//extensions/common/mojom/api_permission_id.mojom",
-      "//tools/metrics/histograms/enums.xml",
-    ]
+  deps = [
+    ":common",
+    "//base",
+    "//components/version_info:channel",
+    "//extensions/common/api",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "api/declarative/declarative_manifest_unittest.cc",
+    "api/declarative_net_request/dnr_manifest_unittest.cc",
+    "api/printer_provider/usb_printer_manifest_unittest.cc",
+    "api/sockets/sockets_manifest_permission_unittest.cc",
+    "component_extension_url_pattern_unittest.cc",
+    "csp_validator_unittest.cc",
+    "error_utils_unittest.cc",
+    "event_filter_unittest.cc",
+    "extension_builder_unittest.cc",
+    "extension_icon_set_unittest.cc",
+    "extension_l10n_util_unittest.cc",
+    "extension_resource_path_normalizer_unittest.cc",
+    "extension_resource_unittest.cc",
+    "extension_set_unittest.cc",
+    "extension_unittest.cc",
+    "feature_switch_unittest.cc",
+    "features/complex_feature_unittest.cc",
+    "features/feature_provider_unittest.cc",
+    "features/simple_feature_unittest.cc",
+    "file_util_unittest.cc",
+    "hashed_extension_id_unittest.cc",
+    "image_util_unittest.cc",
+    "manifest_handler_perf_test.cc",
+    "manifest_handler_unittest.cc",
+    "manifest_handlers/content_capabilities_manifest_unittest.cc",
+    "manifest_handlers/csp_info_unittest.cc",
+    "manifest_handlers/default_locale_manifest_unittest.cc",
+    "manifest_handlers/extension_action_handler_unittest.cc",
+    "manifest_handlers/externally_connectable_unittest.cc",
+    "manifest_handlers/file_handler_manifest_unittest.cc",
+    "manifest_handlers/icons_handler_unittest.cc",
+    "manifest_handlers/incognito_manifest_unittest.cc",
+    "manifest_handlers/kiosk_mode_info_unittest.cc",
+    "manifest_handlers/manifest_v3_permissions_unittest.cc",
+    "manifest_handlers/oauth2_manifest_unittest.cc",
+    "manifest_handlers/replacement_apps_unittest.cc",
+    "manifest_handlers/shared_module_manifest_unittest.cc",
+    "manifest_unittest.cc",
+    "message_bundle_unittest.cc",
+    "mojom/permission_set_mojom_traits_unittest.cc",
+    "mojom/url_pattern_set_mojom_traits_unittest.cc",
+    "permissions/api_permission_set_unittest.cc",
+    "permissions/api_permission_unittest.cc",
+    "permissions/base_set_operators_unittest.cc",
+    "permissions/manifest_permission_set_unittest.cc",
+    "permissions/socket_permission_unittest.cc",
+    "permissions/usb_device_permission_unittest.cc",
+    "stack_frame_unittest.cc",
+    "url_pattern_set_unittest.cc",
+    "url_pattern_unittest.cc",
+    "user_script_unittest.cc",
+    "value_builder_unittest.cc",
+    "value_counter_unittest.cc",
+  ]
+
+  deps = [
+    ":common",
+    ":test_support",
+    "//base",
+    "//base:i18n",
+    "//base/test:test_support",
+    "//components/crx_file",
+    "//components/version_info:version_info",
+    "//content/test:test_support",
+    "//extensions:extensions_resources",
+    "//extensions/common:mojom",
+    "//extensions/common/api",
+    "//mojo/public/cpp/test_support:test_utils",
+    "//tools/json_schema_compiler:generated_api_util",
+
+    # TODO(brettw) these tests should not be including headers from browser.
+    "//extensions:test_support",
+    "//extensions/browser",
+    "//extensions/strings",
+    "//ipc",
+    "//services/device/public/cpp:test_support",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/zlib/google:compression_utils",
+    "//ui/base",
+    "//ui/gfx",
+    "//url",
+  ]
+
+  if (is_chromeos_ash) {
+    sources += [ "manifest_handlers/action_handlers_handler_unittest.cc" ]
   }
 
-  fuzzer_test("extension_fuzzer") {
-    sources = [ "extension_fuzzer.cc" ]
-    deps = [
-      ":common",
-      "//base",
-    ]
-  }
+  data = [
+    "//extensions/common/mojom/api_permission_id.mojom",
+    "//tools/metrics/histograms/enums.xml",
+  ]
+}
 
-  fuzzer_test("extension_manifest_fuzzer") {
-    sources = [ "manifest_fuzzer.cc" ]
-    deps = [
-      ":common",
-      "//base",
-      "//extensions:test_support",
-    ]
-  }
+fuzzer_test("extension_fuzzer") {
+  sources = [ "extension_fuzzer.cc" ]
+  deps = [
+    ":common",
+    "//base",
+  ]
+}
 
-  fuzzer_test("extension_url_pattern_fuzzer") {
-    sources = [ "url_pattern_fuzzer.cc" ]
-    deps = [
-      ":common",
-      "//base",
-    ]
-  }
+fuzzer_test("extension_manifest_fuzzer") {
+  sources = [ "manifest_fuzzer.cc" ]
+  deps = [
+    ":common",
+    "//base",
+    "//extensions:test_support",
+  ]
+}
 
-  fuzzer_test("extension_csp_validator_fuzzer") {
-    sources = [ "csp_validator_fuzzer.cc" ]
-    deps = [
-      ":common",
-      "//base",
-      "//third_party/icu/fuzzers:fuzzer_support",
-    ]
-  }
-}  # enable_extensions
+fuzzer_test("extension_url_pattern_fuzzer") {
+  sources = [ "url_pattern_fuzzer.cc" ]
+  deps = [
+    ":common",
+    "//base",
+  ]
+}
+
+fuzzer_test("extension_csp_validator_fuzzer") {
+  sources = [ "csp_validator_fuzzer.cc" ]
+  deps = [
+    ":common",
+    "//base",
+    "//third_party/icu/fuzzers:fuzzer_support",
+  ]
+}
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index c26cd8ed..500e60da 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -775,8 +775,7 @@
   configs += [ ":headless_defines_config" ]
 
   if (is_fuchsia) {
-    # TODO(crbug.com/1256502): Switch back to CFv2 once the bug is fixed.
-    use_cfv2 = false
+    use_cfv2 = true
   }
 }
 
diff --git a/infra/config/generated/builders/try/gpu-fyi-try-android-n-nvidia-shield-tv-64/properties.textpb b/infra/config/generated/builders/try/gpu-fyi-try-android-nvidia-shield-tv/properties.textpb
similarity index 100%
rename from infra/config/generated/builders/try/gpu-fyi-try-android-n-nvidia-shield-tv-64/properties.textpb
rename to infra/config/generated/builders/try/gpu-fyi-try-android-nvidia-shield-tv/properties.textpb
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg
index 6e022a0..871bc29 100644
--- a/infra/config/generated/luci/commit-queue.cfg
+++ b/infra/config/generated/luci/commit-queue.cfg
@@ -882,7 +882,7 @@
         includable_only: true
       }
       builders {
-        name: "chromium/try/gpu-fyi-try-android-n-nvidia-shield-tv-64"
+        name: "chromium/try/gpu-fyi-try-android-nvidia-shield-tv"
         includable_only: true
       }
       builders {
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index ede5558..9bbca280 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -55802,7 +55802,7 @@
       }
     }
     builders {
-      name: "gpu-fyi-try-android-n-nvidia-shield-tv-64"
+      name: "gpu-fyi-try-android-nvidia-shield-tv"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
       dimensions: "cores:8"
@@ -55826,7 +55826,7 @@
         '    }'
         '  },'
         '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/try/gpu-fyi-try-android-n-nvidia-shield-tv-64/properties.textpb",'
+        '    "properties_file": "infra/config/generated/builders/try/gpu-fyi-try-android-nvidia-shield-tv/properties.textpb",'
         '    "top_level_project": {'
         '      "ref": "refs/heads/main",'
         '      "repo": {'
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index e0dce76..879c598 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -8333,7 +8333,7 @@
   }
   builders {
     name: "buildbucket/luci.chromium.ci/Android FYI Release (NVIDIA Shield TV)"
-    category: "Android|N64|NVDA"
+    category: "Android|P32|NVDA"
     short_name: "STV"
   }
   builders {
@@ -14393,7 +14393,7 @@
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-android-m-nexus-9-64"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/gpu-fyi-try-android-n-nvidia-shield-tv-64"
+    name: "buildbucket/luci.chromium.try/gpu-fyi-try-android-nvidia-shield-tv"
   }
   builders {
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-android-p-pixel-2-32"
@@ -15369,7 +15369,7 @@
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-android-m-nexus-9-64"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/gpu-fyi-try-android-n-nvidia-shield-tv-64"
+    name: "buildbucket/luci.chromium.try/gpu-fyi-try-android-nvidia-shield-tv"
   }
   builders {
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-android-p-pixel-2-32"
diff --git a/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star b/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
index 0349ec06..61ac2a0 100644
--- a/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
@@ -59,10 +59,10 @@
 ci.thin_tester(
     name = "Android FYI Release (NVIDIA Shield TV)",
     console_view_entry = consoles.console_view_entry(
-        category = "Android|N64|NVDA",
+        category = "Android|P32|NVDA",
         short_name = "STV",
     ),
-    triggered_by = ["GPU FYI Android arm64 Builder"],
+    triggered_by = ["GPU FYI Android arm Builder"],
 )
 
 ci.thin_tester(
diff --git a/infra/config/subprojects/chromium/gpu.try.star b/infra/config/subprojects/chromium/gpu.try.star
index e285ed0..e57a0d5 100644
--- a/infra/config/subprojects/chromium/gpu.try.star
+++ b/infra/config/subprojects/chromium/gpu.try.star
@@ -68,7 +68,7 @@
 )
 
 gpu_android_builder(
-    name = "gpu-fyi-try-android-n-nvidia-shield-tv-64",
+    name = "gpu-fyi-try-android-nvidia-shield-tv",
     pool = "luci.chromium.gpu.android.nvidia.shield.tv.try",
 )
 
diff --git a/infra/inclusive_language_presubmit_exempt_dirs.txt b/infra/inclusive_language_presubmit_exempt_dirs.txt
index b544f67..30cda0c 100644
--- a/infra/inclusive_language_presubmit_exempt_dirs.txt
+++ b/infra/inclusive_language_presubmit_exempt_dirs.txt
@@ -43,7 +43,6 @@
 chrome/browser/extensions 2 2
 chrome/browser/extensions/api/commands 3 1
 chrome/browser/extensions/api/identity 1 1
-chrome/browser/federated_learning 1 1
 chrome/browser/feed/android 1 1
 chrome/browser/first_run 1 1
 chrome/browser/mac 1 1
@@ -108,7 +107,6 @@
 components/cbor 2 2
 components/certificate_transparency 1 1
 components/domain_reliability 4 2
-components/federated_learning 1 1
 components/infobars/android/java/src/org/chromium/components/infobars 1 1
 components/metrics 1 1
 components/page_info 2 2
diff --git a/ios/chrome/browser/prerender/preload_controller.mm b/ios/chrome/browser/prerender/preload_controller.mm
index 2b953a7..fc1da7c 100644
--- a/ios/chrome/browser/prerender/preload_controller.mm
+++ b/ios/chrome/browser/prerender/preload_controller.mm
@@ -141,6 +141,27 @@
   __weak id<PreloadCancelling> cancel_handler_ = nil;
 };
 
+class PreloadManageAccountsDelegate : public ManageAccountsDelegate {
+ public:
+  explicit PreloadManageAccountsDelegate(id<PreloadCancelling> canceler)
+      : canceler_(canceler) {}
+  ~PreloadManageAccountsDelegate() override {}
+
+  void OnRestoreGaiaCookies() override { [canceler_ schedulePrerenderCancel]; }
+  void OnManageAccounts() override { [canceler_ schedulePrerenderCancel]; }
+  void OnAddAccount() override { [canceler_ schedulePrerenderCancel]; }
+  void OnShowConsistencyPromo(const GURL& url,
+                              web::WebState* webState) override {
+    [canceler_ schedulePrerenderCancel];
+  }
+  void OnGoIncognito(const GURL& url) override {
+    [canceler_ schedulePrerenderCancel];
+  }
+
+ private:
+  __weak id<PreloadCancelling> canceler_;
+};
+
 // Maximum time to let a cancelled webState attempt to finish restore.
 static const size_t kMaximumCancelledWebStateDelay = 2;
 
@@ -206,7 +227,6 @@
                                  CRWWebStateDelegate,
                                  CRWWebStateObserver,
                                  CRWWebStatePolicyDecider,
-                                 ManageAccountsDelegate,
                                  PrefObserverDelegate,
                                  PreloadCancelling> {
   std::unique_ptr<web::WebStateDelegateBridge> _webStateDelegate;
@@ -232,6 +252,8 @@
   // one. This is needed by |startPrerender| to build the new webstate with the
   // same sessions.
   web::WebState* _webStateToReplace;
+
+  std::unique_ptr<PreloadManageAccountsDelegate> _manageAccountsDelegate;
 }
 
 // The ChromeBrowserState passed on initialization.
@@ -310,6 +332,8 @@
     _observerBridge->ObserveChangesForPreference(
         prefs::kNetworkPredictionSetting, &_prefChangeRegistrar);
     _dialogPresenter = std::make_unique<PreloadJavaScriptDialogPresenter>(self);
+    _manageAccountsDelegate =
+        std::make_unique<PreloadManageAccountsDelegate>(self);
     if (_networkPredictionSetting ==
         prerender_prefs::NetworkPredictionSetting::kEnabledWifiOnly) {
       _connectionTypeObserver =
@@ -580,29 +604,6 @@
   decisionHandler(WebStatePolicyDecider::PolicyDecision::Allow());
 }
 
-#pragma mark - ManageAccountsDelegate
-
-- (void)onRestoreGaiaCookies {
-  [self schedulePrerenderCancel];
-}
-
-- (void)onManageAccounts {
-  [self schedulePrerenderCancel];
-}
-
-- (void)onShowConsistencyPromo:(const GURL&)url
-                      webState:(web::WebState*)webState {
-  [self schedulePrerenderCancel];
-}
-
-- (void)onAddAccount {
-  [self schedulePrerenderCancel];
-}
-
-- (void)onGoIncognito:(const GURL&)url {
-  [self schedulePrerenderCancel];
-}
-
 #pragma mark - PrefObserverDelegate
 
 - (void)onPreferenceChanged:(const std::string&)preferenceName {
@@ -724,7 +725,8 @@
   if (AccountConsistencyService* accountConsistencyService =
           ios::AccountConsistencyServiceFactory::GetForBrowserState(
               self.browserState)) {
-    accountConsistencyService->SetWebStateHandler(_webState.get(), self);
+    accountConsistencyService->SetWebStateHandler(
+        _webState.get(), _manageAccountsDelegate.get());
   }
 
   HistoryTabHelper::FromWebState(_webState.get())
diff --git a/ios/chrome/browser/signin/account_consistency_browser_agent.h b/ios/chrome/browser/signin/account_consistency_browser_agent.h
index 6e5adc3..6b22dc6 100644
--- a/ios/chrome/browser/signin/account_consistency_browser_agent.h
+++ b/ios/chrome/browser/signin/account_consistency_browser_agent.h
@@ -5,6 +5,7 @@
 #ifndef IOS_CHROME_BROWSER_SIGNIN_ACCOUNT_CONSISTENCY_BROWSER_AGENT_H_
 #define IOS_CHROME_BROWSER_SIGNIN_ACCOUNT_CONSISTENCY_BROWSER_AGENT_H_
 
+#import "components/signin/ios/browser/manage_accounts_delegate.h"
 #import "ios/chrome/browser/main/browser_observer.h"
 #import "ios/chrome/browser/main/browser_user_data.h"
 #import "ios/chrome/browser/web_state_list/web_state_dependency_installation_observer.h"
@@ -21,6 +22,7 @@
 class AccountConsistencyBrowserAgent
     : public BrowserUserData<AccountConsistencyBrowserAgent>,
       public DependencyInstaller,
+      public ManageAccountsDelegate,
       BrowserObserver {
  public:
   // |browser| is the browser this agent is attached to.
@@ -41,12 +43,13 @@
   void InstallDependency(web::WebState* web_state) override;
   void UninstallDependency(web::WebState* web_state) override;
 
-  // Handlers for the corresponding protocol methods in ManageAccountDelegate.
-  void OnRestoreGaiaCookies();
-  void OnManageAccounts();
-  void OnAddAccount();
-  void OnShowConsistencyPromo(const GURL& url, web::WebState* webState);
-  void OnGoIncognito(const GURL& url);
+  // ManageAccountsDelegate
+  void OnRestoreGaiaCookies() override;
+  void OnManageAccounts() override;
+  void OnAddAccount() override;
+  void OnShowConsistencyPromo(const GURL& url,
+                              web::WebState* webState) override;
+  void OnGoIncognito(const GURL& url) override;
 
  private:
   AccountConsistencyBrowserAgent(Browser* browser,
diff --git a/ios/chrome/browser/signin/account_consistency_browser_agent.mm b/ios/chrome/browser/signin/account_consistency_browser_agent.mm
index cc8dfc6..cbf8c08 100644
--- a/ios/chrome/browser/signin/account_consistency_browser_agent.mm
+++ b/ios/chrome/browser/signin/account_consistency_browser_agent.mm
@@ -8,7 +8,6 @@
 
 #import "components/signin/core/browser/account_reconcilor.h"
 #import "components/signin/ios/browser/account_consistency_service.h"
-#import "components/signin/ios/browser/manage_accounts_delegate.h"
 #import "ios/chrome/browser/signin/account_consistency_service_factory.h"
 #import "ios/chrome/browser/signin/account_reconcilor_factory.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
@@ -23,50 +22,6 @@
 
 BROWSER_USER_DATA_KEY_IMPL(AccountConsistencyBrowserAgent)
 
-// Obj-C bridge object to forward ManageAccountsDelegate methods to the browser
-// agent.
-// TODO(crbug.com/1293395): Refactor ManageAccountsDelegate into C++, removing
-// the need for this object.
-@interface ManageAccountsDelegateBridge : NSObject <ManageAccountsDelegate>
-
-- (instancetype)initWithBrowserAgent:(AccountConsistencyBrowserAgent*)agent;
-
-@end
-
-@implementation ManageAccountsDelegateBridge {
-  AccountConsistencyBrowserAgent* _agent;
-}
-
-- (instancetype)initWithBrowserAgent:(AccountConsistencyBrowserAgent*)agent {
-  if (self = [super init]) {
-    _agent = agent;
-  }
-  return self;
-}
-
-- (void)onRestoreGaiaCookies {
-  _agent->OnRestoreGaiaCookies();
-}
-
-- (void)onManageAccounts {
-  _agent->OnManageAccounts();
-}
-
-- (void)onAddAccount {
-  _agent->OnAddAccount();
-}
-
-- (void)onShowConsistencyPromo:(const GURL&)url
-                      webState:(web::WebState*)webState {
-  _agent->OnShowConsistencyPromo(url, webState);
-}
-
-- (void)onGoIncognito:(const GURL&)url {
-  _agent->OnGoIncognito(url);
-}
-
-@end
-
 void AccountConsistencyBrowserAgent::CreateForBrowser(
     Browser* browser,
     UIViewController* base_view_controller,
@@ -86,7 +41,6 @@
     : base_view_controller_(base_view_controller),
       handler_(handler),
       browser_(browser) {
-  bridge_ = [[ManageAccountsDelegateBridge alloc] initWithBrowserAgent:this];
   installation_observer_ =
       std::make_unique<WebStateDependencyInstallationObserver>(
           browser->GetWebStateList(), this);
@@ -100,7 +54,7 @@
   if (AccountConsistencyService* accountConsistencyService =
           ios::AccountConsistencyServiceFactory::GetForBrowserState(
               browser_->GetBrowserState())) {
-    accountConsistencyService->SetWebStateHandler(web_state, bridge_);
+    accountConsistencyService->SetWebStateHandler(web_state, this);
   }
 }
 
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index 36c3de9..a10250d 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-18a099559bd6e0f26667a34c7a8db44f2231433a
\ No newline at end of file
+3343a839b59bdca29ae44afe5bb9f82ca951b757
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index 9f018f0d..fa4a652c 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-c24024e7316f6d2b83e616bdd63e3959ee690c6d
\ No newline at end of file
+e8890c91117a1887057d06e6af2c59fc822e3f21
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index 7b48d12..2f8e676 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-966902c49315bbc3d64babfac2d7538d4760f6b9
\ No newline at end of file
+adb0101a8caba8a3600db4e14fdfbc4decea7bd3
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index bd034b6c..c8e07830 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-3b1f489588543e90b45e662080bc1c0e4799ea53
\ No newline at end of file
+67eccd63a45f6d9992bbd3ae98ba3d1cde082a18
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
index 6bfc279..8adbd9d 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-283d21c514036fc71d74a61565e9c429b9795ad3
\ No newline at end of file
+dd902dc476249b350620c4c498da33ecd8794de3
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
index a22128d..eff58a6b 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-fc75038082f8b31e597a37db1ba03aaaee77f7cc
\ No newline at end of file
+88f070706f962c0bce177dc1ce84171bdb723972
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 6f4f2561..1a861ce 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-6994c63f988781b60b92bfb398f5aa6385c8be34
\ No newline at end of file
+33fb3927f5840b596f3c2074be418c416f90f132
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index 5ede1da..97e753d 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-cf217df878c3e43c4b04c0dec9af5e8557909ee1
\ No newline at end of file
+9caacbfda2e62f20256c92cd7c1d026631edc879
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 1781297..040b08f1 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-67ee6698be03176d59e56b3edbfa697b3a62862a
\ No newline at end of file
+581a52488ed93faed2587a2e39ae61122502c60a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index f540c46..5a23540b 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-73684d668250b3a15f1b6561ca837cab3ed81200
\ No newline at end of file
+f5c5107e00a86d6b3c067cc6b09a2603f1a155be
\ No newline at end of file
diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn
index b1f63006..ae4ac90 100644
--- a/ipc/BUILD.gn
+++ b/ipc/BUILD.gn
@@ -294,8 +294,7 @@
     }
 
     if (is_fuchsia) {
-      # TODO(crbug.com/1256502): Switch back to CFv2 once the bug is fixed.
-      use_cfv2 = false
+      use_cfv2 = true
       sources -= [
         # No AF_UNIX domain sockets on Fuchsia.
         "sync_socket_unittest.cc",
diff --git a/media/gpu/chromeos/video_decoder_pipeline.cc b/media/gpu/chromeos/video_decoder_pipeline.cc
index 416b943..29d5cbf 100644
--- a/media/gpu/chromeos/video_decoder_pipeline.cc
+++ b/media/gpu/chromeos/video_decoder_pipeline.cc
@@ -49,7 +49,6 @@
 // TODO(mcasas): query the platform for its preferred formats and modifiers.
 constexpr Fourcc::Value kPreferredRenderableFourccs[] = {
     Fourcc::NV12,
-    Fourcc::YV12,
     Fourcc::P010,
 };
 
diff --git a/media/gpu/chromeos/video_decoder_pipeline_unittest.cc b/media/gpu/chromeos/video_decoder_pipeline_unittest.cc
index 1362f92..b29c1d2 100644
--- a/media/gpu/chromeos/video_decoder_pipeline_unittest.cc
+++ b/media/gpu/chromeos/video_decoder_pipeline_unittest.cc
@@ -628,15 +628,13 @@
       // Easy cases: one candidate that is supported, should be chosen.
       {{PixelLayoutCandidate{Fourcc(Fourcc::NV12), kSize, kModifier}},
        PixelLayoutCandidate{Fourcc(Fourcc::NV12), kSize, kModifier}},
-      {{PixelLayoutCandidate{Fourcc(Fourcc::YV12), kSize, kModifier}},
-       PixelLayoutCandidate{Fourcc(Fourcc::YV12), kSize, kModifier}},
       {{PixelLayoutCandidate{Fourcc(Fourcc::P010), kSize, kModifier}},
        PixelLayoutCandidate{Fourcc(Fourcc::P010), kSize, kModifier}},
       // Two candidates, both supported: pick as per implementation.
       {{PixelLayoutCandidate{Fourcc(Fourcc::NV12), kSize, kModifier},
-        PixelLayoutCandidate{Fourcc(Fourcc::YV12), kSize, kModifier}},
+        PixelLayoutCandidate{Fourcc(Fourcc::P010), kSize, kModifier}},
        PixelLayoutCandidate{Fourcc(Fourcc::NV12), kSize, kModifier}},
-      {{PixelLayoutCandidate{Fourcc(Fourcc::YV12), kSize, kModifier},
+      {{PixelLayoutCandidate{Fourcc(Fourcc::P010), kSize, kModifier},
         PixelLayoutCandidate{Fourcc(Fourcc::NV12), kSize, kModifier}},
        PixelLayoutCandidate{Fourcc(Fourcc::NV12), kSize, kModifier}},
       {{PixelLayoutCandidate{Fourcc(Fourcc::NV12), kSize, kModifier},
@@ -647,9 +645,6 @@
         PixelLayoutCandidate{Fourcc(Fourcc::NV12), kSize, kModifier}},
        PixelLayoutCandidate{Fourcc(Fourcc::NV12), kSize, kModifier}},
       {{PixelLayoutCandidate{Fourcc(Fourcc::YU16), kSize, kModifier},
-        PixelLayoutCandidate{Fourcc(Fourcc::YV12), kSize, kModifier}},
-       PixelLayoutCandidate{Fourcc(Fourcc::YV12), kSize, kModifier}},
-      {{PixelLayoutCandidate{Fourcc(Fourcc::YU16), kSize, kModifier},
         PixelLayoutCandidate{Fourcc(Fourcc::P010), kSize, kModifier}},
        PixelLayoutCandidate{Fourcc(Fourcc::P010), kSize, kModifier}}};
 
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 8ceb09f4..3b00bcf3 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -841,6 +841,8 @@
     "quic/web_transport_client.h",
     "quic/web_transport_error.cc",
     "quic/web_transport_error.h",
+    "quiche/common/platform/impl/quiche_command_line_flags_impl.cc",
+    "quiche/common/platform/impl/quiche_command_line_flags_impl.h",
     "quiche/common/platform/impl/quiche_flag_utils_impl.h",
     "quiche/common/platform/impl/quiche_flags_impl.cc",
     "quiche/common/platform/impl/quiche_flags_impl.h",
@@ -4574,6 +4576,7 @@
     sources += [
       "quic/platform/impl/quic_epoll_clock_test.cc",
       "quic/platform/impl/quic_flags_test.cc",
+      "quiche/common/platform/impl/quiche_command_line_flags_test.cc",
       "tools/quic/quic_http_proxy_backend_stream_test.cc",
       "tools/quic/quic_http_proxy_backend_test.cc",
       "tools/quic/quic_simple_server_test.cc",
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc
index f50ed5c..36ea770 100644
--- a/net/http/http_response_info.cc
+++ b/net/http/http_response_info.cc
@@ -168,6 +168,7 @@
     case CONNECTION_INFO_QUIC_DRAFT_29:
     case CONNECTION_INFO_QUIC_T051:
     case CONNECTION_INFO_QUIC_RFC_V1:
+    case CONNECTION_INFO_QUIC_2_DRAFT_1:
       return CONNECTION_INFO_COARSE_QUIC;
 
     case CONNECTION_INFO_UNKNOWN:
@@ -527,6 +528,7 @@
     case CONNECTION_INFO_QUIC_DRAFT_29:
     case CONNECTION_INFO_QUIC_T051:
     case CONNECTION_INFO_QUIC_RFC_V1:
+    case CONNECTION_INFO_QUIC_2_DRAFT_1:
       return true;
     case NUM_OF_CONNECTION_INFOS:
       NOTREACHED();
@@ -625,6 +627,8 @@
       return "h3-T051";
     case CONNECTION_INFO_QUIC_RFC_V1:
       return "h3";
+    case CONNECTION_INFO_QUIC_2_DRAFT_1:
+      return "quic2/1";
     case NUM_OF_CONNECTION_INFOS:
       break;
   }
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h
index 86d157aa..a6d80e49 100644
--- a/net/http/http_response_info.h
+++ b/net/http/http_response_info.h
@@ -77,6 +77,7 @@
     CONNECTION_INFO_QUIC_DRAFT_29 = 38,
     CONNECTION_INFO_QUIC_T051 = 39,
     CONNECTION_INFO_QUIC_RFC_V1 = 40,
+    CONNECTION_INFO_QUIC_2_DRAFT_1 = 41,
     NUM_OF_CONNECTION_INFOS,
   };
 
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc
index dffc4d00..e8f7973 100644
--- a/net/http/http_server_properties_manager_unittest.cc
+++ b/net/http/http_server_properties_manager_unittest.cc
@@ -3036,12 +3036,13 @@
     AlternativeServiceInfoVector alternative_service_info_vector_out =
         server_info.alternative_services.value();
     ASSERT_EQ(1u, alternative_service_info_vector_out.size());
-    EXPECT_EQ(
-        kProtoQUIC,
-        alternative_service_info_vector_out[0].alternative_service().protocol);
+    const auto& altsvc_info = alternative_service_info_vector_out[0];
+    EXPECT_EQ(kProtoQUIC, altsvc_info.alternative_service().protocol);
     // Ensure we correctly parsed the version.
-    EXPECT_EQ(advertised_versions,
-              alternative_service_info_vector_out[0].advertised_versions());
+    // (Versions with identical ALPN string are considered equal.)
+    ASSERT_EQ(1u, altsvc_info.advertised_versions().size());
+    EXPECT_EQ(quic::AlpnForVersion(version),
+              quic::AlpnForVersion(altsvc_info.advertised_versions()[0]));
   }
 }
 
diff --git a/net/quic/platform/impl/quic_default_proof_providers_impl.cc b/net/quic/platform/impl/quic_default_proof_providers_impl.cc
index 6d349ff..341ab94 100644
--- a/net/quic/platform/impl/quic_default_proof_providers_impl.cc
+++ b/net/quic/platform/impl/quic_default_proof_providers_impl.cc
@@ -17,24 +17,25 @@
 #include "net/quic/crypto/proof_source_chromium.h"
 #include "net/quic/crypto/proof_verifier_chromium.h"
 #include "net/quic/platform/impl/quic_chromium_clock.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_command_line_flags.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
 #include "net/third_party/quiche/src/quic/tools/simple_ticket_crypter.h"
 
-DEFINE_QUIC_COMMAND_LINE_FLAG(
+DEFINE_QUICHE_COMMAND_LINE_FLAG(
     bool,
     allow_unknown_root_cert,
     false,
     "If true, don't restrict cert verification to known roots");
 
-DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
-                              certificate_file,
-                              "",
-                              "Path to the certificate chain.");
+DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string,
+                                certificate_file,
+                                "",
+                                "Path to the certificate chain.");
 
-DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
-                              key_file,
-                              "",
-                              "Path to the pkcs8 private key.");
+DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string,
+                                key_file,
+                                "",
+                                "Path to the pkcs8 private key.");
 
 using net::CertVerifier;
 using net::ProofVerifierChromium;
diff --git a/net/quic/platform/impl/quic_flags_impl.cc b/net/quic/platform/impl/quic_flags_impl.cc
index 5461b16..5eae6f4 100644
--- a/net/quic/platform/impl/quic_flags_impl.cc
+++ b/net/quic/platform/impl/quic_flags_impl.cc
@@ -4,23 +4,9 @@
 
 #include "net/quic/platform/impl/quic_flags_impl.h"
 
-#include <algorithm>
-#include <initializer_list>
-#include <iostream>
-#include <limits>
-#include <set>
 #include <string>
 
-#include "base/command_line.h"
-#include "base/export_template.h"
-#include "base/logging.h"
-#include "base/no_destructor.h"
-#include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
 
 #define DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE(type, flag, value, doc) \
   type FLAGS_##flag = value;
@@ -46,240 +32,6 @@
 #undef DEFINE_QUIC_PROTOCOL_FLAG_TWO_VALUES
 #undef DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE
 
-namespace quic {
-
-namespace {
-
-// Overload for platforms where base::CommandLine::StringType == std::string.
-[[maybe_unused]] std::vector<std::string> ToQuicStringVector(
-    const std::vector<std::string>& v) {
-  return v;
-}
-
-#if defined(WCHAR_T_IS_UTF16)
-// Overload for platforms where base::CommandLine::StringType == std::wstring.
-[[maybe_unused]] std::vector<std::string> ToQuicStringVector(
-    const std::vector<std::wstring>& v) {
-  std::vector<std::string> qsv;
-  for (const auto& s : v) {
-    if (!base::IsStringASCII(s)) {
-      QUIC_LOG(ERROR) << "Unable to convert to ASCII: " << s;
-      continue;
-    }
-    qsv.push_back(base::WideToASCII(s));
-  }
-  return qsv;
-}
-#endif  // defined(WCHAR_T_IS_UTF16)
-
-size_t FindLineWrapPosition(const std::string& s, size_t desired_len) {
-  if (s.length() <= desired_len) {
-    return std::string::npos;
-  }
-  size_t pos = s.find_last_of(base::kWhitespaceASCII, desired_len);
-  if (pos != std::string::npos) {
-    return pos;
-  }
-  pos = s.find_first_of(base::kWhitespaceASCII, desired_len);
-  if (pos != std::string::npos) {
-    return pos;
-  }
-  return std::string::npos;
-}
-
-// Pretty-print a flag description in the format:
-//
-// --flag_name      Some text describing the flag that can
-//                  wrap around to the next line.
-void AppendFlagDescription(const std::string& name,
-                           std::string help,
-                           std::string* out) {
-  const int kStartCol = 20;
-  const int kEndCol = 80;
-  const int kMinPadding = 2;
-  static const char kDashes[] = "--";
-
-  base::StrAppend(out, {kDashes, name});
-  int col = strlen(kDashes) + name.length();
-  if (col + kMinPadding < kEndCol) {
-    // Start help text on same line
-    int pad_len = std::max(kMinPadding, kStartCol - col);
-    base::StrAppend(out, {std::string(pad_len, ' ')});
-    col += pad_len;
-  } else {
-    // Start help text on next line
-    base::StrAppend(out, {"\n", std::string(kStartCol, ' ')});
-    col = kStartCol;
-  }
-
-  while (!help.empty()) {
-    size_t desired_len = kEndCol - col;
-    size_t wrap_pos = FindLineWrapPosition(help, desired_len);
-    if (wrap_pos == std::string::npos) {
-      base::StrAppend(out, {help});
-      break;
-    }
-    base::StrAppend(
-        out, {help.substr(0, wrap_pos), "\n", std::string(kStartCol, ' ')});
-    help = help.substr(wrap_pos + 1);
-    col = kStartCol;
-  }
-  base::StrAppend(out, {"\n"});
-}
-
-}  // namespace
-
-// static
-QuicFlagRegistry& QuicFlagRegistry::GetInstance() {
-  static base::NoDestructor<QuicFlagRegistry> instance;
-  return *instance;
-}
-
-void QuicFlagRegistry::RegisterFlag(const char* name,
-                                    std::unique_ptr<QuicFlagHelper> helper) {
-  flags_.emplace(std::string(name), std::move(helper));
-}
-
-bool QuicFlagRegistry::SetFlags(const base::CommandLine& command_line,
-                                std::string* error_msg) const {
-  for (const auto& kv : flags_) {
-    const std::string& name = kv.first;
-    const QuicFlagHelper* helper = kv.second.get();
-    if (!command_line.HasSwitch(name)) {
-      continue;
-    }
-    std::string value = command_line.GetSwitchValueASCII(name);
-    if (!helper->SetFlag(value)) {
-      *error_msg =
-          base::StrCat({"Invalid value \"", value, "\" for flag --", name});
-      return false;
-    }
-    QUIC_LOG(INFO) << "Set flag --" << name << " = " << value;
-  }
-  return true;
-}
-
-void QuicFlagRegistry::ResetFlags() const {
-  for (const auto& kv : flags_) {
-    kv.second->ResetFlag();
-    QUIC_LOG(INFO) << "Reset flag --" << kv.first;
-  }
-}
-
-std::string QuicFlagRegistry::GetHelp() const {
-  std::string help;
-  AppendFlagDescription("help", "Print this help message.", &help);
-  for (const auto& kv : flags_) {
-    AppendFlagDescription(kv.first, kv.second->GetHelp(), &help);
-  }
-  return help;
-}
-
-template <>
-bool TypedQuicFlagHelper<bool>::SetFlag(const std::string& s) const {
-  static const base::NoDestructor<std::set<std::string>> kTrueValues(
-      std::initializer_list<std::string>({"", "1", "t", "true", "y", "yes"}));
-  static const base::NoDestructor<std::set<std::string>> kFalseValues(
-      std::initializer_list<std::string>({"0", "f", "false", "n", "no"}));
-  if (kTrueValues->find(base::ToLowerASCII(s)) != kTrueValues->end()) {
-    *flag_ = true;
-    return true;
-  }
-  if (kFalseValues->find(base::ToLowerASCII(s)) != kFalseValues->end()) {
-    *flag_ = false;
-    return true;
-  }
-  return false;
-}
-
-template <>
-bool TypedQuicFlagHelper<uint16_t>::SetFlag(const std::string& s) const {
-  int value;
-  if (!base::StringToInt(s, &value) ||
-      value < std::numeric_limits<uint16_t>::min() ||
-      value > std::numeric_limits<uint16_t>::max()) {
-    return false;
-  }
-  *flag_ = static_cast<uint16_t>(value);
-  return true;
-}
-
-template <>
-bool TypedQuicFlagHelper<int32_t>::SetFlag(const std::string& s) const {
-  int32_t value;
-  if (!base::StringToInt(s, &value)) {
-    return false;
-  }
-  *flag_ = value;
-  return true;
-}
-
-template <>
-bool TypedQuicFlagHelper<std::string>::SetFlag(const std::string& s) const {
-  *flag_ = s;
-  return true;
-}
-
-template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE)
-    TypedQuicFlagHelper<bool>;
-template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE)
-    TypedQuicFlagHelper<uint16_t>;
-template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE)
-    TypedQuicFlagHelper<int32_t>;
-template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE)
-    TypedQuicFlagHelper<std::string>;
-
-std::vector<std::string> QuicParseCommandLineFlagsImpl(
-    const char* usage,
-    int argc,
-    const char* const* argv) {
-  base::CommandLine::Init(argc, argv);
-  auto result = QuicParseCommandLineFlagsHelper(
-      usage, *base::CommandLine::ForCurrentProcess());
-  if (result.exit_status.has_value()) {
-    exit(*result.exit_status);
-  }
-
-  logging::LoggingSettings settings;
-  settings.logging_dest = logging::LOG_TO_STDERR;
-  CHECK(logging::InitLogging(settings));
-
-  return result.non_flag_args;
-}
-
-QuicParseCommandLineFlagsResult QuicParseCommandLineFlagsHelper(
-    const char* usage,
-    const base::CommandLine& command_line) {
-  QuicParseCommandLineFlagsResult result;
-  result.non_flag_args = ToQuicStringVector(command_line.GetArgs());
-  if (command_line.HasSwitch("h") || command_line.HasSwitch("help")) {
-    QuicPrintCommandLineFlagHelpImpl(usage);
-    result.exit_status = 0;
-  } else {
-    std::string msg;
-    if (!QuicFlagRegistry::GetInstance().SetFlags(command_line, &msg)) {
-      std::cerr << msg << std::endl;
-      result.exit_status = 1;
-    }
-  }
-  return result;
-}
-
-void QuicPrintCommandLineFlagHelpImpl(const char* usage) {
-  std::cout << usage << std::endl
-            << "Options:" << std::endl
-            << QuicFlagRegistry::GetInstance().GetHelp() << std::endl;
-}
-
-QuicFlagRegistry::QuicFlagRegistry() = default;
-QuicFlagRegistry::~QuicFlagRegistry() = default;
-QuicParseCommandLineFlagsResult::QuicParseCommandLineFlagsResult() = default;
-QuicParseCommandLineFlagsResult::QuicParseCommandLineFlagsResult(
-    const QuicParseCommandLineFlagsResult&) = default;
-QuicParseCommandLineFlagsResult::~QuicParseCommandLineFlagsResult() = default;
-
-}  // namespace quic
-
 namespace {
 
 void SetQuicFlagByName_bool(bool* flag, const std::string& value) {
diff --git a/net/quic/platform/impl/quic_flags_impl.h b/net/quic/platform/impl/quic_flags_impl.h
index 3f679b6..99d11ca 100644
--- a/net/quic/platform/impl/quic_flags_impl.h
+++ b/net/quic/platform/impl/quic_flags_impl.h
@@ -5,16 +5,8 @@
 #ifndef NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_
 #define NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_
 
-#include <cstdint>
-#include <map>
-#include <memory>
 #include <string>
-#include <vector>
 
-#include "base/command_line.h"
-#include "base/export_template.h"
-#include "base/memory/raw_ptr.h"
-#include "base/no_destructor.h"
 #include "net/third_party/quiche/src/common/platform/api/quiche_flags.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -30,141 +22,4 @@
 QUIC_EXPORT_PRIVATE void SetQuicFlagByName(const std::string& flag_name,
                                            const std::string& value);
 
-namespace quic {
-
-// ------------------------------------------------------------------------
-// DEFINE_QUIC_COMMAND_LINE_FLAG implementation.
-// ------------------------------------------------------------------------
-
-// Abstract class for setting flags and fetching help strings.
-class QuicFlagHelper {
- public:
-  explicit QuicFlagHelper(const char* help) : help_(help) {}
-  virtual ~QuicFlagHelper() = default;
-
-  virtual bool SetFlag(const std::string& value) const = 0;
-  virtual void ResetFlag() const = 0;
-  std::string GetHelp() const { return help_; }
-
- private:
-  std::string help_;
-};
-
-// Templated class for setting flags of various types.
-template <typename T>
-class TypedQuicFlagHelper : public QuicFlagHelper {
- public:
-  TypedQuicFlagHelper(T* flag, const T& default_value, const char* help)
-      : QuicFlagHelper(help), flag_(flag), default_value_(default_value) {}
-  bool SetFlag(const std::string& value) const override;
-  void ResetFlag() const override { *flag_ = default_value_; }
-
- private:
-  mutable raw_ptr<T> flag_;
-  T default_value_;
-};
-
-// SetFlag specializations. Implementations in .cc file.
-template <>
-QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<bool>::SetFlag(
-    const std::string&) const;
-template <>
-QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<uint16_t>::SetFlag(
-    const std::string&) const;
-template <>
-QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<int32_t>::SetFlag(
-    const std::string&) const;
-template <>
-QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<std::string>::SetFlag(
-    const std::string&) const;
-
-// TypedQuicFlagHelper instantiations are in .cc file.
-extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE)
-    TypedQuicFlagHelper<bool>;
-extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE)
-    TypedQuicFlagHelper<uint16_t>;
-extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE)
-    TypedQuicFlagHelper<int32_t>;
-extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE)
-    TypedQuicFlagHelper<std::string>;
-
-// Registry of QuicFlagHelpers.
-class QUIC_EXPORT_PRIVATE QuicFlagRegistry {
- public:
-  ~QuicFlagRegistry();
-
-  static QuicFlagRegistry& GetInstance();
-
-  // Adds a flag to the registry.
-  void RegisterFlag(const char* name, std::unique_ptr<QuicFlagHelper> helper);
-
-  // Sets any flags in the registry that are specified in |command_line|,
-  // returning true iff successful. If there is a failure, e.g. due to an
-  // invalid flag value, returns false and sets |error_msg|.
-  bool SetFlags(const base::CommandLine& command_line,
-                std::string* error_msg) const;
-
-  // Resets flags to their default values.
-  void ResetFlags() const;
-
-  // Returns a help string consisting of the names and help strings of all
-  // registered flags.
-  std::string GetHelp() const;
-
- private:
-  friend class base::NoDestructor<QuicFlagRegistry>;
-
-  // Should only be accessed as a singleton.
-  QuicFlagRegistry();
-
-  std::map<std::string, std::unique_ptr<QuicFlagHelper>> flags_;
-};
-
-// Class instantiated in DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL macro expansion,
-// that registers flag as a side effect of its constructor. Similar in spirit to
-// absl::flags_internal::FlagRegistrar.
-template <typename T>
-class QuicFlagSetup {
- public:
-  QuicFlagSetup(T* flag,
-                const char* name,
-                const T& default_value,
-                const char* help) {
-    QuicFlagRegistry::GetInstance().RegisterFlag(
-        name,
-        std::make_unique<TypedQuicFlagHelper<T>>(flag, default_value, help));
-  }
-  // Allow QuicFlagSetup instance to convert to a bool in
-  // DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL macro expansion, so it can go away.
-  operator bool() const { return true; }
-};
-
-#define DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL(type, name, default_value, help) \
-  type FLAGS_##name = default_value;                                        \
-  bool FLAGS_no##name =                                                     \
-      quic::QuicFlagSetup<type>(&FLAGS_##name, #name, default_value, help)
-
-QUIC_EXPORT_PRIVATE std::vector<std::string> QuicParseCommandLineFlagsImpl(
-    const char* usage,
-    int argc,
-    const char* const* argv);
-
-// Used internally by QuicParseCommandLineFlagsImpl(), but exposed here for
-// testing.
-struct QUIC_EXPORT_PRIVATE QuicParseCommandLineFlagsResult {
-  QuicParseCommandLineFlagsResult();
-  QuicParseCommandLineFlagsResult(const QuicParseCommandLineFlagsResult&);
-  ~QuicParseCommandLineFlagsResult();
-
-  std::vector<std::string> non_flag_args;
-  absl::optional<int> exit_status;
-};
-
-QUIC_EXPORT_PRIVATE QuicParseCommandLineFlagsResult
-QuicParseCommandLineFlagsHelper(const char* usage,
-                                const base::CommandLine& command_line);
-
-QUIC_EXPORT_PRIVATE void QuicPrintCommandLineFlagHelpImpl(const char* usage);
-
-}  // namespace quic
 #endif  // NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_
diff --git a/net/quic/platform/impl/quic_flags_test.cc b/net/quic/platform/impl/quic_flags_test.cc
index d781872..c36d946 100644
--- a/net/quic/platform/impl/quic_flags_test.cc
+++ b/net/quic/platform/impl/quic_flags_test.cc
@@ -6,184 +6,14 @@
 
 #include <string>
 
-#include "base/command_line.h"
 #include "base/cxx17_backports.h"
-#include "base/strings/strcat.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
 #include "net/quic/platform/impl/quic_flags_impl.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(bool, foo, false, "An old silent pond...");
-DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, bar, 123, "A frog jumps into the pond,");
-DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, baz, "splash!", "Silence again.");
 
 namespace quic {
 namespace test {
 
-class QuicCommandLineFlagTest : public QuicTest {
- protected:
-  void SetUp() override { QuicFlagRegistry::GetInstance().ResetFlags(); }
-
-  static QuicParseCommandLineFlagsResult QuicParseCommandLineFlagsForTest(
-      const char* usage,
-      int argc,
-      const char* const* argv) {
-    base::CommandLine::StringVector v;
-    FillCommandLineArgs(argc, argv, &v);
-    return QuicParseCommandLineFlagsHelper(usage, base::CommandLine(v));
-  }
-
- private:
-  // Overload for platforms where base::CommandLine::StringType == std::string.
-  static void FillCommandLineArgs(int argc,
-                                  const char* const* argv,
-                                  std::vector<std::string>* v) {
-    for (int i = 0; i < argc; ++i) {
-      v->push_back(argv[i]);
-    }
-  }
-
-  // Overload for platforms where base::CommandLine::StringType ==
-  // std::u16string.
-  static void FillCommandLineArgs(int argc,
-                                  const char* const* argv,
-                                  std::vector<std::u16string>* v) {
-    for (int i = 0; i < argc; ++i) {
-      v->push_back(base::UTF8ToUTF16(argv[i]));
-    }
-  }
-};
-
-TEST_F(QuicCommandLineFlagTest, DefaultValues) {
-  EXPECT_EQ(false, GetQuicFlag(FLAGS_foo));
-  EXPECT_EQ(123, GetQuicFlag(FLAGS_bar));
-  EXPECT_EQ("splash!", GetQuicFlag(FLAGS_baz));
-}
-
-TEST_F(QuicCommandLineFlagTest, NotSpecified) {
-  const char* argv[]{"one", "two", "three"};
-  auto parse_result =
-      QuicParseCommandLineFlagsForTest("usage message", base::size(argv), argv);
-  EXPECT_FALSE(parse_result.exit_status.has_value());
-  std::vector<std::string> expected_args{"two", "three"};
-  EXPECT_EQ(expected_args, parse_result.non_flag_args);
-
-  EXPECT_EQ(false, GetQuicFlag(FLAGS_foo));
-  EXPECT_EQ(123, GetQuicFlag(FLAGS_bar));
-  EXPECT_EQ("splash!", GetQuicFlag(FLAGS_baz));
-}
-
-TEST_F(QuicCommandLineFlagTest, BoolFlag) {
-  for (const char* s :
-       {"--foo", "--foo=1", "--foo=t", "--foo=True", "--foo=Y", "--foo=yes"}) {
-    SetQuicFlag(FLAGS_foo, false);
-    const char* argv[]{"argv0", s};
-    auto parse_result = QuicParseCommandLineFlagsForTest(
-        "usage message", base::size(argv), argv);
-    EXPECT_FALSE(parse_result.exit_status.has_value());
-    EXPECT_TRUE(parse_result.non_flag_args.empty());
-    EXPECT_TRUE(GetQuicFlag(FLAGS_foo));
-  }
-
-  for (const char* s :
-       {"--foo=0", "--foo=f", "--foo=False", "--foo=N", "--foo=no"}) {
-    SetQuicFlag(FLAGS_foo, true);
-    const char* argv[]{"argv0", s};
-    auto parse_result = QuicParseCommandLineFlagsForTest(
-        "usage message", base::size(argv), argv);
-    EXPECT_FALSE(parse_result.exit_status.has_value());
-    EXPECT_TRUE(parse_result.non_flag_args.empty());
-    EXPECT_FALSE(GetQuicFlag(FLAGS_foo));
-  }
-
-  for (const char* s : {"--foo=7", "--foo=abc", "--foo=trueish"}) {
-    SetQuicFlag(FLAGS_foo, false);
-    const char* argv[]{"argv0", s};
-
-    testing::internal::CaptureStderr();
-    auto parse_result = QuicParseCommandLineFlagsForTest(
-        "usage message", base::size(argv), argv);
-    std::string captured_stderr = testing::internal::GetCapturedStderr();
-
-    EXPECT_TRUE(parse_result.exit_status.has_value());
-    EXPECT_EQ(1, *parse_result.exit_status);
-    EXPECT_THAT(captured_stderr,
-                testing::ContainsRegex("Invalid value.*for flag --foo"));
-    EXPECT_TRUE(parse_result.non_flag_args.empty());
-    EXPECT_FALSE(GetQuicFlag(FLAGS_foo));
-  }
-}
-
-TEST_F(QuicCommandLineFlagTest, Int32Flag) {
-  for (const int i : {-1, 0, 100, 38239832}) {
-    SetQuicFlag(FLAGS_bar, 0);
-    std::string flag_str = base::StringPrintf("--bar=%d", i);
-    const char* argv[]{"argv0", flag_str.c_str()};
-    auto parse_result = QuicParseCommandLineFlagsForTest(
-        "usage message", base::size(argv), argv);
-    EXPECT_FALSE(parse_result.exit_status.has_value());
-    EXPECT_TRUE(parse_result.non_flag_args.empty());
-    EXPECT_EQ(i, GetQuicFlag(FLAGS_bar));
-  }
-
-  for (const char* s : {"--bar", "--bar=a", "--bar=9999999999999"}) {
-    SetQuicFlag(FLAGS_bar, 0);
-    const char* argv[]{"argv0", s};
-
-    testing::internal::CaptureStderr();
-    auto parse_result = QuicParseCommandLineFlagsForTest(
-        "usage message", base::size(argv), argv);
-    std::string captured_stderr = testing::internal::GetCapturedStderr();
-
-    EXPECT_TRUE(parse_result.exit_status.has_value());
-    EXPECT_EQ(1, *parse_result.exit_status);
-    EXPECT_THAT(captured_stderr,
-                testing::ContainsRegex("Invalid value.*for flag --bar"));
-    EXPECT_TRUE(parse_result.non_flag_args.empty());
-    EXPECT_EQ(0, GetQuicFlag(FLAGS_bar));
-  }
-}
-
-TEST_F(QuicCommandLineFlagTest, StringFlag) {
-  {
-    SetQuicFlag(FLAGS_baz, "whee");
-    const char* argv[]{"argv0", "--baz"};
-    auto parse_result = QuicParseCommandLineFlagsForTest(
-        "usage message", base::size(argv), argv);
-    EXPECT_FALSE(parse_result.exit_status.has_value());
-    EXPECT_TRUE(parse_result.non_flag_args.empty());
-    EXPECT_EQ("", GetQuicFlag(FLAGS_baz));
-  }
-
-  for (const char* s : {"", "12345", "abcdefg"}) {
-    SetQuicFlag(FLAGS_baz, "qux");
-    std::string flag_str = base::StrCat({"--baz=", s});
-    const char* argv[]{"argv0", flag_str.c_str()};
-    auto parse_result = QuicParseCommandLineFlagsForTest(
-        "usage message", base::size(argv), argv);
-    EXPECT_FALSE(parse_result.exit_status.has_value());
-    EXPECT_TRUE(parse_result.non_flag_args.empty());
-    EXPECT_EQ(s, GetQuicFlag(FLAGS_baz));
-  }
-}
-
-TEST_F(QuicCommandLineFlagTest, PrintHelp) {
-  testing::internal::CaptureStdout();
-  QuicPrintCommandLineFlagHelp("usage message");
-  std::string captured_stdout = testing::internal::GetCapturedStdout();
-  EXPECT_THAT(captured_stdout, testing::HasSubstr("usage message"));
-  EXPECT_THAT(captured_stdout,
-              testing::ContainsRegex("--help +Print this help message."));
-  EXPECT_THAT(captured_stdout,
-              testing::ContainsRegex("--foo +An old silent pond..."));
-  EXPECT_THAT(captured_stdout,
-              testing::ContainsRegex("--bar +A frog jumps into the pond,"));
-  EXPECT_THAT(captured_stdout, testing::ContainsRegex("--baz +Silence again."));
-}
-
 class QuicFlagsTest : public QuicTest {};
 
 TEST_F(QuicFlagsTest, SetQuicFlagByName_bool) {
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index 7aeb0f6..d7e51b1 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -110,6 +110,8 @@
       return HttpResponseInfo::CONNECTION_INFO_QUIC_RFC_V1;
     case quic::QUIC_VERSION_RESERVED_FOR_NEGOTIATION:
       return HttpResponseInfo::CONNECTION_INFO_QUIC_999;
+    case quic::QUIC_VERSION_IETF_2_DRAFT_01:
+      return HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_1;
   }
   NOTREACHED();
   return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 843ea5e4..96c2f7d 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -688,8 +688,25 @@
     EXPECT_EQ(status_line, response->headers->GetStatusLine());
     EXPECT_TRUE(response->was_fetched_via_spdy);
     EXPECT_TRUE(response->was_alpn_negotiated);
-    EXPECT_EQ(QuicHttpStream::ConnectionInfoFromQuicVersion(version),
-              response->connection_info);
+    auto connection_info =
+        QuicHttpStream::ConnectionInfoFromQuicVersion(version);
+    if (connection_info == response->connection_info) {
+      return;
+    }
+    // QUIC v1 and QUIC v2 are considered a match, because they have the same
+    // ALPN token.
+    if ((connection_info == HttpResponseInfo::CONNECTION_INFO_QUIC_RFC_V1 ||
+         connection_info == HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_1) &&
+        (response->connection_info ==
+             HttpResponseInfo::CONNECTION_INFO_QUIC_RFC_V1 ||
+         response->connection_info ==
+             HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_1)) {
+      return;
+    }
+
+    // They do not match.  This EXPECT_EQ will fail and print useful
+    // information.
+    EXPECT_EQ(connection_info, response->connection_info);
   }
 
   void CheckWasQuicResponse(HttpNetworkTransaction* trans,
@@ -1002,6 +1019,53 @@
     }
   }
 
+  // Verify that the set of QUIC protocols in `alt_svc_info_vector` and
+  // `supported_versions` is the same.  Since QUICv1 and QUICv2 have the same
+  // ALPN token "h3", they cannot be distinguished when parsing ALPN, so
+  // consider them equal.  This is accomplished by comparing the set of ALPN
+  // strings (instead of comparing the set of ParsedQuicVersion entities).
+  static void VerifyQuicVersionsInAlternativeServices(
+      const AlternativeServiceInfoVector& alt_svc_info_vector,
+      const quic::ParsedQuicVersionVector& supported_versions) {
+    // Versions that support the legacy Google-specific Alt-Svc format are sent
+    // in a single Alt-Svc entry, therefore they are accumulated in a single
+    // AlternativeServiceInfo, whereas more recent versions all have their own
+    // Alt-Svc entry and AlternativeServiceInfo entry.  Flatten to compare.
+    std::vector<std::string> alt_svc_negotiated_alpn;
+    for (const auto& alt_svc_info : alt_svc_info_vector) {
+      EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol);
+      for (const auto& version : alt_svc_info.advertised_versions()) {
+        alt_svc_negotiated_alpn.push_back(quic::AlpnForVersion(version));
+      }
+    }
+
+    // Sort and deduplicate.
+    std::sort(alt_svc_negotiated_alpn.begin(), alt_svc_negotiated_alpn.end());
+    auto last = std::unique(alt_svc_negotiated_alpn.begin(),
+                            alt_svc_negotiated_alpn.end());
+    if (last != alt_svc_negotiated_alpn.end()) {
+      alt_svc_negotiated_alpn.erase(last, alt_svc_negotiated_alpn.end());
+    }
+
+    // Process supported versions.
+    std::vector<std::string> supported_alpn;
+    for (const auto& version : supported_versions) {
+      supported_alpn.push_back(quic::AlpnForVersion(version));
+    }
+
+    // Sort and deduplicate.
+    std::sort(supported_alpn.begin(), supported_alpn.end());
+    last = std::unique(supported_alpn.begin(), supported_alpn.end());
+    if (last != supported_alpn.end()) {
+      supported_alpn.erase(last, supported_alpn.end());
+    }
+
+    // Compare.
+    ASSERT_EQ(supported_alpn.size(), alt_svc_negotiated_alpn.size());
+    EXPECT_TRUE(std::equal(supported_alpn.begin(), supported_alpn.end(),
+                           alt_svc_negotiated_alpn.begin()));
+  }
+
   const quic::ParsedQuicVersion version_;
   const bool client_headers_include_h2_stream_dependency_;
   quic::ParsedQuicVersionVector supported_versions_;
@@ -1801,34 +1865,8 @@
   alt_svc_info_vector =
       session_->http_server_properties()->GetAlternativeServiceInfos(
           server, NetworkIsolationKey());
-  // Versions that support the legacy Google-specific Alt-Svc format are sent in
-  // a single Alt-Svc entry, therefore they are accumulated in a single
-  // AlternativeServiceInfo, whereas more recent versions all have their own
-  // Alt-Svc entry and AlternativeServiceInfo entry.  Flatten to compare.
-  quic::ParsedQuicVersionVector alt_svc_negotiated_versions;
-  for (const auto& alt_svc_info : alt_svc_info_vector) {
-    EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol);
-    for (const auto& version : alt_svc_info.advertised_versions()) {
-      if (std::find(alt_svc_negotiated_versions.begin(),
-                    alt_svc_negotiated_versions.end(),
-                    version) == alt_svc_negotiated_versions.end()) {
-        alt_svc_negotiated_versions.push_back(version);
-      }
-    }
-  }
-
-  ASSERT_EQ(supported_versions_.size(), alt_svc_negotiated_versions.size());
-  auto version_compare = [](const quic::ParsedQuicVersion& a,
-                            const quic::ParsedQuicVersion& b) {
-    return std::tie(a.transport_version, a.handshake_protocol) <
-           std::tie(b.transport_version, b.handshake_protocol);
-  };
-  std::sort(supported_versions_.begin(), supported_versions_.end(),
-            version_compare);
-  std::sort(alt_svc_negotiated_versions.begin(),
-            alt_svc_negotiated_versions.end(), version_compare);
-  EXPECT_TRUE(std::equal(supported_versions_.begin(), supported_versions_.end(),
-                         alt_svc_negotiated_versions.begin()));
+  VerifyQuicVersionsInAlternativeServices(alt_svc_info_vector,
+                                          supported_versions_);
 }
 
 // Regression test for https://crbug.com/546991.
@@ -2152,22 +2190,32 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceWithVersionForQuic1) {
-  // Both server advertises and client supports two QUIC versions.
-  // Only |version_| is advertised and supported.
+  // Both client and server supports two QUIC versions:
+  // Client supports |supported_versions_[0]| and |supported_versions_[1]|,
+  // server supports |version_| and |advertised_version_2|.
+  // Only |version_| (same as |supported_versions_[0]|) is supported by both.
   // The QuicStreamFactoy will pick up |version_|, which is verified as the
   // PacketMakers are using |version_|.
 
-  // Add support for another QUIC version besides |version_| on the client side.
-  // Also find a different version advertised by the server.
+  // Compare ALPN strings instead of ParsedQuicVersions because QUIC v1 and v2
+  // have the same ALPN string.
+  ASSERT_EQ(1u, supported_versions_.size());
+  ASSERT_EQ(supported_versions_[0], version_);
   quic::ParsedQuicVersion advertised_version_2 =
       quic::ParsedQuicVersion::Unsupported();
   for (const quic::ParsedQuicVersion& version : quic::AllSupportedVersions()) {
-    if (version == version_)
+    if (quic::AlpnForVersion(version) == quic::AlpnForVersion(version_)) {
       continue;
+    }
     if (supported_versions_.size() != 2) {
       supported_versions_.push_back(version);
       continue;
     }
+    if (supported_versions_.size() == 2 &&
+        quic::AlpnForVersion(supported_versions_[1]) ==
+            quic::AlpnForVersion(version)) {
+      continue;
+    }
     advertised_version_2 = version;
     break;
   }
@@ -2500,34 +2548,8 @@
   const AlternativeServiceInfoVector alt_svc_info_vector =
       session_->http_server_properties()->GetAlternativeServiceInfos(
           https_server, NetworkIsolationKey());
-  // Versions that support the legacy Google-specific Alt-Svc format are sent in
-  // a single Alt-Svc entry, therefore they are accumulated in a single
-  // AlternativeServiceInfo, whereas more recent versions all have their own
-  // Alt-Svc entry and AlternativeServiceInfo entry.  Flatten to compare.
-  quic::ParsedQuicVersionVector alt_svc_negotiated_versions;
-  for (const auto& alt_svc_info : alt_svc_info_vector) {
-    EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol);
-    for (const auto& version : alt_svc_info.advertised_versions()) {
-      if (std::find(alt_svc_negotiated_versions.begin(),
-                    alt_svc_negotiated_versions.end(),
-                    version) == alt_svc_negotiated_versions.end()) {
-        alt_svc_negotiated_versions.push_back(version);
-      }
-    }
-  }
-
-  ASSERT_EQ(supported_versions_.size(), alt_svc_negotiated_versions.size());
-  auto version_compare = [](const quic::ParsedQuicVersion& a,
-                            const quic::ParsedQuicVersion& b) {
-    return std::tie(a.transport_version, a.handshake_protocol) <
-           std::tie(b.transport_version, b.handshake_protocol);
-  };
-  std::sort(supported_versions_.begin(), supported_versions_.end(),
-            version_compare);
-  std::sort(alt_svc_negotiated_versions.begin(),
-            alt_svc_negotiated_versions.end(), version_compare);
-  EXPECT_TRUE(std::equal(supported_versions_.begin(), supported_versions_.end(),
-                         alt_svc_negotiated_versions.begin()));
+  VerifyQuicVersionsInAlternativeServices(alt_svc_info_vector,
+                                          supported_versions_);
 }
 
 TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceAllSupportedVersion) {
diff --git a/net/quiche/common/platform/impl/quiche_command_line_flags_impl.cc b/net/quiche/common/platform/impl/quiche_command_line_flags_impl.cc
new file mode 100644
index 0000000..c996161
--- /dev/null
+++ b/net/quiche/common/platform/impl/quiche_command_line_flags_impl.cc
@@ -0,0 +1,259 @@
+// 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 "net/quiche/common/platform/impl/quiche_command_line_flags_impl.h"
+
+#include <initializer_list>
+#include <iostream>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/export_template.h"
+#include "base/logging.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+namespace quiche {
+
+namespace {
+
+size_t FindLineWrapPosition(const std::string& s, size_t desired_len) {
+  if (s.length() <= desired_len) {
+    return std::string::npos;
+  }
+  size_t pos = s.find_last_of(base::kWhitespaceASCII, desired_len);
+  if (pos != std::string::npos) {
+    return pos;
+  }
+  pos = s.find_first_of(base::kWhitespaceASCII, desired_len);
+  if (pos != std::string::npos) {
+    return pos;
+  }
+  return std::string::npos;
+}
+
+// Pretty-print a flag description in the format:
+//
+// --flag_name      Some text describing the flag that can
+//                  wrap around to the next line.
+void AppendFlagDescription(const std::string& name,
+                           std::string help,
+                           std::string* out) {
+  const int kStartCol = 20;
+  const int kEndCol = 80;
+  const int kMinPadding = 2;
+  static const char kDashes[] = "--";
+
+  base::StrAppend(out, {kDashes, name});
+  int col = strlen(kDashes) + name.length();
+  if (col + kMinPadding < kEndCol) {
+    // Start help text on same line
+    int pad_len = std::max(kMinPadding, kStartCol - col);
+    base::StrAppend(out, {std::string(pad_len, ' ')});
+    col += pad_len;
+  } else {
+    // Start help text on next line
+    base::StrAppend(out, {"\n", std::string(kStartCol, ' ')});
+    col = kStartCol;
+  }
+
+  while (!help.empty()) {
+    size_t desired_len = kEndCol - col;
+    size_t wrap_pos = FindLineWrapPosition(help, desired_len);
+    if (wrap_pos == std::string::npos) {
+      base::StrAppend(out, {help});
+      break;
+    }
+    base::StrAppend(
+        out, {help.substr(0, wrap_pos), "\n", std::string(kStartCol, ' ')});
+    help = help.substr(wrap_pos + 1);
+    col = kStartCol;
+  }
+  base::StrAppend(out, {"\n"});
+}
+
+// Overload for platforms where base::CommandLine::StringType == std::string.
+[[maybe_unused]] std::vector<std::string> ToQuicheStringVector(
+    const std::vector<std::string>& v) {
+  return v;
+}
+
+#if defined(WCHAR_T_IS_UTF16)
+// Overload for platforms where base::CommandLine::StringType == std::wstring.
+[[maybe_unused]] std::vector<std::string> ToQuicheStringVector(
+    const std::vector<std::wstring>& v) {
+  std::vector<std::string> qsv;
+  for (const auto& s : v) {
+    if (!base::IsStringASCII(s)) {
+      QUIC_LOG(ERROR) << "Unable to convert to ASCII: " << s;
+      continue;
+    }
+    qsv.push_back(base::WideToASCII(s));
+  }
+  return qsv;
+}
+#endif  // defined(WCHAR_T_IS_UTF16)
+
+}  // namespace
+
+// static
+QuicheFlagRegistry& QuicheFlagRegistry::GetInstance() {
+  static base::NoDestructor<QuicheFlagRegistry> instance;
+  return *instance;
+}
+
+void QuicheFlagRegistry::RegisterFlag(
+    const char* name,
+    std::unique_ptr<QuicheFlagHelper> helper) {
+  flags_.emplace(std::string(name), std::move(helper));
+}
+
+bool QuicheFlagRegistry::SetFlags(const base::CommandLine& command_line,
+                                  std::string* error_msg) const {
+  for (const auto& kv : flags_) {
+    const std::string& name = kv.first;
+    const QuicheFlagHelper* helper = kv.second.get();
+    if (!command_line.HasSwitch(name)) {
+      continue;
+    }
+    std::string value = command_line.GetSwitchValueASCII(name);
+    if (!helper->SetFlag(value)) {
+      *error_msg =
+          base::StrCat({"Invalid value \"", value, "\" for flag --", name});
+      return false;
+    }
+    QUIC_LOG(INFO) << "Set flag --" << name << " = " << value;
+  }
+  return true;
+}
+
+void QuicheFlagRegistry::ResetFlags() const {
+  for (const auto& kv : flags_) {
+    kv.second->ResetFlag();
+    QUIC_LOG(INFO) << "Reset flag --" << kv.first;
+  }
+}
+
+std::string QuicheFlagRegistry::GetHelp() const {
+  std::string help;
+  AppendFlagDescription("help", "Print this help message.", &help);
+  for (const auto& kv : flags_) {
+    AppendFlagDescription(kv.first, kv.second->GetHelp(), &help);
+  }
+  return help;
+}
+
+template <>
+bool TypedQuicheFlagHelper<bool>::SetFlag(const std::string& s) const {
+  static const base::NoDestructor<std::set<std::string>> kTrueValues(
+      std::initializer_list<std::string>({"", "1", "t", "true", "y", "yes"}));
+  static const base::NoDestructor<std::set<std::string>> kFalseValues(
+      std::initializer_list<std::string>({"0", "f", "false", "n", "no"}));
+  if (kTrueValues->find(base::ToLowerASCII(s)) != kTrueValues->end()) {
+    *flag_ = true;
+    return true;
+  }
+  if (kFalseValues->find(base::ToLowerASCII(s)) != kFalseValues->end()) {
+    *flag_ = false;
+    return true;
+  }
+  return false;
+}
+
+template <>
+bool TypedQuicheFlagHelper<uint16_t>::SetFlag(const std::string& s) const {
+  int value;
+  if (!base::StringToInt(s, &value) ||
+      value < std::numeric_limits<uint16_t>::min() ||
+      value > std::numeric_limits<uint16_t>::max()) {
+    return false;
+  }
+  *flag_ = static_cast<uint16_t>(value);
+  return true;
+}
+
+template <>
+bool TypedQuicheFlagHelper<int32_t>::SetFlag(const std::string& s) const {
+  int32_t value;
+  if (!base::StringToInt(s, &value)) {
+    return false;
+  }
+  *flag_ = value;
+  return true;
+}
+
+template <>
+bool TypedQuicheFlagHelper<std::string>::SetFlag(const std::string& s) const {
+  *flag_ = s;
+  return true;
+}
+
+template class EXPORT_TEMPLATE_DEFINE(QUICHE_EXPORT_PRIVATE)
+    TypedQuicheFlagHelper<bool>;
+template class EXPORT_TEMPLATE_DEFINE(QUICHE_EXPORT_PRIVATE)
+    TypedQuicheFlagHelper<uint16_t>;
+template class EXPORT_TEMPLATE_DEFINE(QUICHE_EXPORT_PRIVATE)
+    TypedQuicheFlagHelper<int32_t>;
+template class EXPORT_TEMPLATE_DEFINE(QUICHE_EXPORT_PRIVATE)
+    TypedQuicheFlagHelper<std::string>;
+
+QuicheFlagRegistry::QuicheFlagRegistry() = default;
+QuicheFlagRegistry::~QuicheFlagRegistry() = default;
+
+std::vector<std::string> QuicheParseCommandLineFlagsImpl(
+    const char* usage,
+    int argc,
+    const char* const* argv) {
+  base::CommandLine::Init(argc, argv);
+  auto result = QuicheParseCommandLineFlagsHelper(
+      usage, *base::CommandLine::ForCurrentProcess());
+  if (result.exit_status.has_value()) {
+    exit(*result.exit_status);
+  }
+
+  logging::LoggingSettings settings;
+  settings.logging_dest = logging::LOG_TO_STDERR;
+  CHECK(logging::InitLogging(settings));
+
+  return result.non_flag_args;
+}
+
+QuicheParseCommandLineFlagsResult QuicheParseCommandLineFlagsHelper(
+    const char* usage,
+    const base::CommandLine& command_line) {
+  QuicheParseCommandLineFlagsResult result;
+  result.non_flag_args = ToQuicheStringVector(command_line.GetArgs());
+  if (command_line.HasSwitch("h") || command_line.HasSwitch("help")) {
+    QuichePrintCommandLineFlagHelpImpl(usage);
+    result.exit_status = 0;
+  } else {
+    std::string msg;
+    if (!QuicheFlagRegistry::GetInstance().SetFlags(command_line, &msg)) {
+      std::cerr << msg << std::endl;
+      result.exit_status = 1;
+    }
+  }
+  return result;
+}
+
+void QuichePrintCommandLineFlagHelpImpl(const char* usage) {
+  std::cout << usage << std::endl
+            << "Options:" << std::endl
+            << QuicheFlagRegistry::GetInstance().GetHelp() << std::endl;
+}
+
+QuicheParseCommandLineFlagsResult::QuicheParseCommandLineFlagsResult() =
+    default;
+QuicheParseCommandLineFlagsResult::QuicheParseCommandLineFlagsResult(
+    const QuicheParseCommandLineFlagsResult&) = default;
+QuicheParseCommandLineFlagsResult::~QuicheParseCommandLineFlagsResult() =
+    default;
+
+}  // namespace quiche
diff --git a/net/quiche/common/platform/impl/quiche_command_line_flags_impl.h b/net/quiche/common/platform/impl/quiche_command_line_flags_impl.h
new file mode 100644
index 0000000..bdc5bf8b
--- /dev/null
+++ b/net/quiche/common/platform/impl/quiche_command_line_flags_impl.h
@@ -0,0 +1,158 @@
+// 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 NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_COMMAND_LINE_FLAGS_IMPL_H_
+#define NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_COMMAND_LINE_FLAGS_IMPL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/export_template.h"
+#include "base/memory/raw_ptr.h"
+#include "base/no_destructor.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_export.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_flags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace quiche {
+
+// Abstract class for setting flags and fetching help strings.
+class QuicheFlagHelper {
+ public:
+  explicit QuicheFlagHelper(const char* help) : help_(help) {}
+  virtual ~QuicheFlagHelper() = default;
+
+  virtual bool SetFlag(const std::string& value) const = 0;
+  virtual void ResetFlag() const = 0;
+  std::string GetHelp() const { return help_; }
+
+ private:
+  std::string help_;
+};
+
+// Templated class for setting flags of various types.
+template <typename T>
+class TypedQuicheFlagHelper : public QuicheFlagHelper {
+ public:
+  TypedQuicheFlagHelper(T* flag, const T& default_value, const char* help)
+      : QuicheFlagHelper(help), flag_(flag), default_value_(default_value) {}
+  bool SetFlag(const std::string& value) const override;
+  void ResetFlag() const override { *flag_ = default_value_; }
+
+ private:
+  mutable raw_ptr<T> flag_;
+  T default_value_;
+};
+
+// SetFlag specializations. Implementations in .cc file.
+template <>
+QUICHE_EXPORT_PRIVATE bool TypedQuicheFlagHelper<bool>::SetFlag(
+    const std::string&) const;
+template <>
+QUICHE_EXPORT_PRIVATE bool TypedQuicheFlagHelper<uint16_t>::SetFlag(
+    const std::string&) const;
+template <>
+QUICHE_EXPORT_PRIVATE bool TypedQuicheFlagHelper<int32_t>::SetFlag(
+    const std::string&) const;
+template <>
+QUICHE_EXPORT_PRIVATE bool TypedQuicheFlagHelper<std::string>::SetFlag(
+    const std::string&) const;
+
+// TypedQuicheFlagHelper instantiations are in .cc file.
+extern template class EXPORT_TEMPLATE_DECLARE(QUICHE_EXPORT_PRIVATE)
+    TypedQuicheFlagHelper<bool>;
+extern template class EXPORT_TEMPLATE_DECLARE(QUICHE_EXPORT_PRIVATE)
+    TypedQuicheFlagHelper<uint16_t>;
+extern template class EXPORT_TEMPLATE_DECLARE(QUICHE_EXPORT_PRIVATE)
+    TypedQuicheFlagHelper<int32_t>;
+extern template class EXPORT_TEMPLATE_DECLARE(QUICHE_EXPORT_PRIVATE)
+    TypedQuicheFlagHelper<std::string>;
+
+// Registry of QuicheFlagHelpers.
+class QUICHE_EXPORT_PRIVATE QuicheFlagRegistry {
+ public:
+  ~QuicheFlagRegistry();
+
+  static QuicheFlagRegistry& GetInstance();
+
+  // Adds a flag to the registry.
+  void RegisterFlag(const char* name, std::unique_ptr<QuicheFlagHelper> helper);
+
+  // Sets any flags in the registry that are specified in |command_line|,
+  // returning true iff successful. If there is a failure, e.g. due to an
+  // invalid flag value, returns false and sets |error_msg|.
+  bool SetFlags(const base::CommandLine& command_line,
+                std::string* error_msg) const;
+
+  // Resets flags to their default values.
+  void ResetFlags() const;
+
+  // Returns a help string consisting of the names and help strings of all
+  // registered flags.
+  std::string GetHelp() const;
+
+ private:
+  friend class base::NoDestructor<QuicheFlagRegistry>;
+
+  // Should only be accessed as a singleton.
+  QuicheFlagRegistry();
+
+  std::map<std::string, std::unique_ptr<QuicheFlagHelper>> flags_;
+};
+
+// Class instantiated in DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL macro expansion,
+// that registers flag as a side effect of its constructor. Similar in spirit to
+// absl::flags_internal::FlagRegistrar.
+template <typename T>
+class QuicheFlagSetup {
+ public:
+  QuicheFlagSetup(T* flag,
+                  const char* name,
+                  const T& default_value,
+                  const char* help) {
+    QuicheFlagRegistry::GetInstance().RegisterFlag(
+        name,
+        std::make_unique<TypedQuicheFlagHelper<T>>(flag, default_value, help));
+  }
+  // Allow QuicheFlagSetup instance to convert to a bool in
+  // DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL macro expansion, so it can go away.
+  operator bool() const { return true; }
+};
+
+// ------------------------------------------------------------------------
+// DEFINE_QUICHE_COMMAND_LINE_FLAG implementation.
+// ------------------------------------------------------------------------
+
+#define DEFINE_QUICHE_COMMAND_LINE_FLAG_IMPL(type, name, default_value, help) \
+  type FLAGS_##name = default_value;                                          \
+  bool FLAGS_no##name =                                                       \
+      quiche::QuicheFlagSetup<type>(&FLAGS_##name, #name, default_value, help)
+
+QUICHE_EXPORT_PRIVATE std::vector<std::string> QuicheParseCommandLineFlagsImpl(
+    const char* usage,
+    int argc,
+    const char* const* argv);
+
+// Used internally by QuicheParseCommandLineFlagsImpl(), but exposed here for
+// testing.
+struct QUICHE_EXPORT_PRIVATE QuicheParseCommandLineFlagsResult {
+  QuicheParseCommandLineFlagsResult();
+  QuicheParseCommandLineFlagsResult(const QuicheParseCommandLineFlagsResult&);
+  ~QuicheParseCommandLineFlagsResult();
+
+  std::vector<std::string> non_flag_args;
+  absl::optional<int> exit_status;
+};
+
+QUICHE_EXPORT_PRIVATE QuicheParseCommandLineFlagsResult
+QuicheParseCommandLineFlagsHelper(const char* usage,
+                                  const base::CommandLine& command_line);
+
+QUICHE_EXPORT_PRIVATE void QuichePrintCommandLineFlagHelpImpl(
+    const char* usage);
+
+}  // namespace quiche
+
+#endif  // NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_COMMAND_LINE_FLAGS_IMPL_H_
diff --git a/net/quiche/common/platform/impl/quiche_command_line_flags_test.cc b/net/quiche/common/platform/impl/quiche_command_line_flags_test.cc
new file mode 100644
index 0000000..056922e1
--- /dev/null
+++ b/net/quiche/common/platform/impl/quiche_command_line_flags_test.cc
@@ -0,0 +1,188 @@
+// 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 "net/third_party/quiche/src/common/platform/api/quiche_command_line_flags.h"
+
+#include <string>
+
+#include "base/command_line.h"
+#include "base/cxx17_backports.h"
+#include "base/strings/strcat.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_command_line_flags.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_test.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, foo, false, "An old silent pond...");
+DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t,
+                                bar,
+                                123,
+                                "A frog jumps into the pond,");
+DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, baz, "splash!", "Silence again.");
+
+namespace quiche::test {
+
+class QuicheCommandLineFlagTest : public QuicheTest {
+ protected:
+  void SetUp() override { QuicheFlagRegistry::GetInstance().ResetFlags(); }
+
+  static QuicheParseCommandLineFlagsResult QuicheParseCommandLineFlagsForTest(
+      const char* usage,
+      int argc,
+      const char* const* argv) {
+    base::CommandLine::StringVector v;
+    FillCommandLineArgs(argc, argv, &v);
+    return QuicheParseCommandLineFlagsHelper(usage, base::CommandLine(v));
+  }
+
+ private:
+  // Overload for platforms where base::CommandLine::StringType == std::string.
+  static void FillCommandLineArgs(int argc,
+                                  const char* const* argv,
+                                  std::vector<std::string>* v) {
+    for (int i = 0; i < argc; ++i) {
+      v->push_back(argv[i]);
+    }
+  }
+
+  // Overload for platforms where base::CommandLine::StringType ==
+  // std::u16string.
+  static void FillCommandLineArgs(int argc,
+                                  const char* const* argv,
+                                  std::vector<std::u16string>* v) {
+    for (int i = 0; i < argc; ++i) {
+      v->push_back(base::UTF8ToUTF16(argv[i]));
+    }
+  }
+};
+
+TEST_F(QuicheCommandLineFlagTest, DefaultValues) {
+  EXPECT_EQ(false, GetQuicheFlag(FLAGS_foo));
+  EXPECT_EQ(123, GetQuicheFlag(FLAGS_bar));
+  EXPECT_EQ("splash!", GetQuicheFlag(FLAGS_baz));
+}
+
+TEST_F(QuicheCommandLineFlagTest, NotSpecified) {
+  const char* argv[]{"one", "two", "three"};
+  auto parse_result = QuicheParseCommandLineFlagsForTest(
+      "usage message", base::size(argv), argv);
+  EXPECT_FALSE(parse_result.exit_status.has_value());
+  std::vector<std::string> expected_args{"two", "three"};
+  EXPECT_EQ(expected_args, parse_result.non_flag_args);
+
+  EXPECT_EQ(false, GetQuicheFlag(FLAGS_foo));
+  EXPECT_EQ(123, GetQuicheFlag(FLAGS_bar));
+  EXPECT_EQ("splash!", GetQuicheFlag(FLAGS_baz));
+}
+
+TEST_F(QuicheCommandLineFlagTest, BoolFlag) {
+  for (const char* s :
+       {"--foo", "--foo=1", "--foo=t", "--foo=True", "--foo=Y", "--foo=yes"}) {
+    SetQuicheFlag(FLAGS_foo, false);
+    const char* argv[]{"argv0", s};
+    auto parse_result = QuicheParseCommandLineFlagsForTest(
+        "usage message", base::size(argv), argv);
+    EXPECT_FALSE(parse_result.exit_status.has_value());
+    EXPECT_TRUE(parse_result.non_flag_args.empty());
+    EXPECT_TRUE(GetQuicheFlag(FLAGS_foo));
+  }
+
+  for (const char* s :
+       {"--foo=0", "--foo=f", "--foo=False", "--foo=N", "--foo=no"}) {
+    SetQuicheFlag(FLAGS_foo, true);
+    const char* argv[]{"argv0", s};
+    auto parse_result = QuicheParseCommandLineFlagsForTest(
+        "usage message", base::size(argv), argv);
+    EXPECT_FALSE(parse_result.exit_status.has_value());
+    EXPECT_TRUE(parse_result.non_flag_args.empty());
+    EXPECT_FALSE(GetQuicheFlag(FLAGS_foo));
+  }
+
+  for (const char* s : {"--foo=7", "--foo=abc", "--foo=trueish"}) {
+    SetQuicheFlag(FLAGS_foo, false);
+    const char* argv[]{"argv0", s};
+
+    testing::internal::CaptureStderr();
+    auto parse_result = QuicheParseCommandLineFlagsForTest(
+        "usage message", base::size(argv), argv);
+    std::string captured_stderr = testing::internal::GetCapturedStderr();
+
+    EXPECT_TRUE(parse_result.exit_status.has_value());
+    EXPECT_EQ(1, *parse_result.exit_status);
+    EXPECT_THAT(captured_stderr,
+                testing::ContainsRegex("Invalid value.*for flag --foo"));
+    EXPECT_TRUE(parse_result.non_flag_args.empty());
+    EXPECT_FALSE(GetQuicheFlag(FLAGS_foo));
+  }
+}
+
+TEST_F(QuicheCommandLineFlagTest, Int32Flag) {
+  for (const int i : {-1, 0, 100, 38239832}) {
+    SetQuicheFlag(FLAGS_bar, 0);
+    std::string flag_str = base::StringPrintf("--bar=%d", i);
+    const char* argv[]{"argv0", flag_str.c_str()};
+    auto parse_result = QuicheParseCommandLineFlagsForTest(
+        "usage message", base::size(argv), argv);
+    EXPECT_FALSE(parse_result.exit_status.has_value());
+    EXPECT_TRUE(parse_result.non_flag_args.empty());
+    EXPECT_EQ(i, GetQuicheFlag(FLAGS_bar));
+  }
+
+  for (const char* s : {"--bar", "--bar=a", "--bar=9999999999999"}) {
+    SetQuicheFlag(FLAGS_bar, 0);
+    const char* argv[]{"argv0", s};
+
+    testing::internal::CaptureStderr();
+    auto parse_result = QuicheParseCommandLineFlagsForTest(
+        "usage message", base::size(argv), argv);
+    std::string captured_stderr = testing::internal::GetCapturedStderr();
+
+    EXPECT_TRUE(parse_result.exit_status.has_value());
+    EXPECT_EQ(1, *parse_result.exit_status);
+    EXPECT_THAT(captured_stderr,
+                testing::ContainsRegex("Invalid value.*for flag --bar"));
+    EXPECT_TRUE(parse_result.non_flag_args.empty());
+    EXPECT_EQ(0, GetQuicheFlag(FLAGS_bar));
+  }
+}
+
+TEST_F(QuicheCommandLineFlagTest, StringFlag) {
+  {
+    SetQuicheFlag(FLAGS_baz, "whee");
+    const char* argv[]{"argv0", "--baz"};
+    auto parse_result = QuicheParseCommandLineFlagsForTest(
+        "usage message", base::size(argv), argv);
+    EXPECT_FALSE(parse_result.exit_status.has_value());
+    EXPECT_TRUE(parse_result.non_flag_args.empty());
+    EXPECT_EQ("", GetQuicheFlag(FLAGS_baz));
+  }
+
+  for (const char* s : {"", "12345", "abcdefg"}) {
+    SetQuicheFlag(FLAGS_baz, "qux");
+    std::string flag_str = base::StrCat({"--baz=", s});
+    const char* argv[]{"argv0", flag_str.c_str()};
+    auto parse_result = QuicheParseCommandLineFlagsForTest(
+        "usage message", base::size(argv), argv);
+    EXPECT_FALSE(parse_result.exit_status.has_value());
+    EXPECT_TRUE(parse_result.non_flag_args.empty());
+    EXPECT_EQ(s, GetQuicheFlag(FLAGS_baz));
+  }
+}
+
+TEST_F(QuicheCommandLineFlagTest, PrintHelp) {
+  testing::internal::CaptureStdout();
+  QuichePrintCommandLineFlagHelp("usage message");
+  std::string captured_stdout = testing::internal::GetCapturedStdout();
+  EXPECT_THAT(captured_stdout, testing::HasSubstr("usage message"));
+  EXPECT_THAT(captured_stdout,
+              testing::ContainsRegex("--help +Print this help message."));
+  EXPECT_THAT(captured_stdout,
+              testing::ContainsRegex("--foo +An old silent pond..."));
+  EXPECT_THAT(captured_stdout,
+              testing::ContainsRegex("--bar +A frog jumps into the pond,"));
+  EXPECT_THAT(captured_stdout, testing::ContainsRegex("--baz +Silence again."));
+}
+
+}  // namespace quiche::test
diff --git a/net/tools/quic/quic_simple_client_bin.cc b/net/tools/quic/quic_simple_client_bin.cc
index 3f09694c8..9233b80 100644
--- a/net/tools/quic/quic_simple_client_bin.cc
+++ b/net/tools/quic/quic_simple_client_bin.cc
@@ -36,6 +36,7 @@
 #include "base/logging.h"
 #include "net/base/net_errors.h"
 #include "net/quic/address_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_command_line_flags.h"
 #include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
 #include "net/third_party/quiche/src/quic/core/quic_packets.h"
 #include "net/third_party/quiche/src/quic/core/quic_server_id.h"
@@ -91,9 +92,9 @@
 
   // All non-flag arguments should be interpreted as URLs to fetch.
   std::vector<std::string> urls =
-      quic::QuicParseCommandLineFlags(usage, argc, argv);
+      quiche::QuicheParseCommandLineFlags(usage, argc, argv);
   if (urls.size() != 1) {
-    quic::QuicPrintCommandLineFlagHelp(usage);
+    quiche::QuichePrintCommandLineFlagHelp(usage);
     exit(0);
   }
 
diff --git a/net/tools/quic/quic_simple_server_backend_factory.cc b/net/tools/quic/quic_simple_server_backend_factory.cc
index 364b7101..9ee3df7 100644
--- a/net/tools/quic/quic_simple_server_backend_factory.cc
+++ b/net/tools/quic/quic_simple_server_backend_factory.cc
@@ -3,17 +3,18 @@
 // found in the LICENSE file.
 
 #include "net/tools/quic/quic_simple_server_backend_factory.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_command_line_flags.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
 #include "net/tools/quic/quic_http_proxy_backend_stream.h"
 
-DEFINE_QUIC_COMMAND_LINE_FLAG(
+DEFINE_QUICHE_COMMAND_LINE_FLAG(
     std::string,
     quic_mode,
     "cache",
     "Specifies the mode for the server to operate in. Either "
     "'cache' or 'proxy'");
 
-DEFINE_QUIC_COMMAND_LINE_FLAG(
+DEFINE_QUICHE_COMMAND_LINE_FLAG(
     std::string,
     quic_proxy_backend_url,
     "",
diff --git a/net/tools/quic/quic_simple_server_bin.cc b/net/tools/quic/quic_simple_server_bin.cc
index c903d7d3..c9205c0 100644
--- a/net/tools/quic/quic_simple_server_bin.cc
+++ b/net/tools/quic/quic_simple_server_bin.cc
@@ -7,6 +7,7 @@
 
 #include <vector>
 
+#include "net/third_party/quiche/src/common/platform/api/quiche_command_line_flags.h"
 #include "net/third_party/quiche/src/quic/core/quic_versions.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h"
@@ -34,9 +35,9 @@
   QuicSystemEventLoop event_loop("quic_server");
   const char* usage = "Usage: quic_server [options]";
   std::vector<std::string> non_option_args =
-      quic::QuicParseCommandLineFlags(usage, argc, argv);
+      quiche::QuicheParseCommandLineFlags(usage, argc, argv);
   if (!non_option_args.empty()) {
-    quic::QuicPrintCommandLineFlagHelp(usage);
+    quiche::QuichePrintCommandLineFlagHelp(usage);
     exit(0);
   }
 
diff --git a/sandbox/win/src/app_container_test.cc b/sandbox/win/src/app_container_test.cc
index 5eef8895..73bb402 100644
--- a/sandbox/win/src/app_container_test.cc
+++ b/sandbox/win/src/app_container_test.cc
@@ -491,7 +491,8 @@
       ::CreateEvent(nullptr, false, false, event_name.c_str()));
   ASSERT_TRUE(event.IsValid());
 
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"AppContainerEvent_Open test"));
+  TestRunner runner2(JOB_UNPROTECTED, USER_UNPROTECTED, USER_UNPROTECTED);
+  EXPECT_EQ(SBOX_TEST_DENIED, runner2.RunTest(L"AppContainerEvent_Open test"));
 }
 
 TEST_F(AppContainerTest, CheckIncompatibleOptions) {
diff --git a/sandbox/win/src/broker_services.cc b/sandbox/win/src/broker_services.cc
index 089a41c..6bce0cc3 100644
--- a/sandbox/win/src/broker_services.cc
+++ b/sandbox/win/src/broker_services.cc
@@ -576,7 +576,7 @@
 
   // Now the policy is the owner of the target. TargetProcess will terminate
   // the process if it has not completed when it is destroyed.
-  result = policy_base->AddTarget(std::move(target));
+  result = policy_base->ApplyToTarget(std::move(target));
 
   if (result != SBOX_ALL_OK) {
     *last_error = ::GetLastError();
diff --git a/sandbox/win/src/file_policy_test.cc b/sandbox/win/src/file_policy_test.cc
index 08de096e..dd02b5c 100644
--- a/sandbox/win/src/file_policy_test.cc
+++ b/sandbox/win/src/file_policy_test.cc
@@ -277,49 +277,60 @@
   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.txt"));
   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 calc.exe"));
 
-  runner.SetTestState(BEFORE_REVERT);
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
+  TestRunner before_revert;
+  EXPECT_TRUE(
+      before_revert.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.txt"));
+  before_revert.SetTestState(BEFORE_REVERT);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED,
+            before_revert.RunTest(L"File_CreateSys32 calc.exe"));
 }
 
 TEST(FilePolicyTest, AllowNtCreateCalc) {
   TestRunner runner;
   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.exe"));
-
   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
 
-  runner.SetTestState(BEFORE_REVERT);
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
+  TestRunner before_revert;
+  EXPECT_TRUE(
+      before_revert.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.exe"));
+  before_revert.SetTestState(BEFORE_REVERT);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED,
+            before_revert.RunTest(L"File_CreateSys32 calc.exe"));
 }
 
 TEST(FilePolicyTest, AllowNtCreateWithNativePath) {
   std::wstring calc = MakePathToSys(L"calc.exe", false);
   std::wstring nt_path;
   ASSERT_TRUE(GetNtPathFromWin32Path(calc, &nt_path));
+
   TestRunner runner;
   runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, nt_path.c_str());
-
   wchar_t buff[MAX_PATH];
   ::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
 
+  TestRunner runner2;
+  runner2.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, nt_path.c_str());
   for (wchar_t& c : nt_path)
     c = std::tolower(c);
   ::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(buff));
+}
+
+std::unique_ptr<TestRunner> AllowReadOnlyRunner(wchar_t* temp_file_name) {
+  auto runner = std::make_unique<TestRunner>();
+  EXPECT_TRUE(
+      runner->AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_file_name));
+  return runner;
 }
 
 TEST(FilePolicyTest, AllowReadOnly) {
-  TestRunner runner;
-
   // Create a temp file because we need write access to it.
   wchar_t temp_directory[MAX_PATH];
   wchar_t temp_file_name[MAX_PATH];
   ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u);
 
-  EXPECT_TRUE(
-      runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_file_name));
-
   wchar_t command_read[MAX_PATH + 20] = {};
   wsprintf(command_read, L"File_Create Read \"%ls\"", temp_file_name);
   wchar_t command_read_create[MAX_PATH + 20] = {};
@@ -329,25 +340,27 @@
   wsprintf(command_write, L"File_Create Write \"%ls\"", temp_file_name);
 
   // Verify that we cannot create the file after revert.
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_read_create));
+  auto runner = AllowReadOnlyRunner(temp_file_name);
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command_read_create));
 
   // Verify that we don't have write access after revert.
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write));
+  runner = AllowReadOnlyRunner(temp_file_name);
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command_write));
 
   // Verify that we have read access after revert.
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_read));
+  runner = AllowReadOnlyRunner(temp_file_name);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(command_read));
 
   // Verify that we really have write access to the file.
-  runner.SetTestState(BEFORE_REVERT);
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write));
+  runner = AllowReadOnlyRunner(temp_file_name);
+  runner->SetTestState(BEFORE_REVERT);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(command_write));
 
   DeleteFile(temp_file_name);
 }
 
 // Tests support of "\\\\.\\DeviceName" kind of paths.
 TEST(FilePolicyTest, AllowImplicitDeviceName) {
-  TestRunner runner;
-
   wchar_t temp_directory[MAX_PATH];
   wchar_t temp_file_name[MAX_PATH];
   ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
@@ -362,9 +375,13 @@
   wsprintf(command, L"File_Create Read \"\\\\.\\%ls\"", path.c_str());
   path = std::wstring(kNTPrefix) + path;
 
+  TestRunner runner;
   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
-  EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, path.c_str()));
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command));
+
+  TestRunner runner_with_rule;
+  EXPECT_TRUE(
+      runner_with_rule.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, path.c_str()));
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner_with_rule.RunTest(command));
 
   DeleteFile(temp_file_name);
 }
@@ -390,18 +407,28 @@
   DeleteFile(temp_file_name);
 }
 
+std::unique_ptr<TestRunner> AllowNtCreatePatternRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  EXPECT_TRUE(runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"App*.dll"));
+  return runner;
+}
+
 TEST(FilePolicyTest, AllowNtCreatePatternRule) {
-  TestRunner runner;
-  EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"App*.dll"));
-
+  auto runner = AllowNtCreatePatternRunner();
   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"File_OpenSys32 apphelp.dll"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_OpenSys32 appwiz.cpl"));
+            runner->RunTest(L"File_OpenSys32 apphelp.dll"));
 
-  runner.SetTestState(BEFORE_REVERT);
+  runner = AllowNtCreatePatternRunner();
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"File_OpenSys32 appwiz.cpl"));
+
+  runner = AllowNtCreatePatternRunner();
+  runner->SetTestState(BEFORE_REVERT);
   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"File_OpenSys32 apphelp.dll"));
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_OpenSys32 appwiz.cpl"));
+            runner->RunTest(L"File_OpenSys32 apphelp.dll"));
+
+  runner = AllowNtCreatePatternRunner();
+  runner->SetTestState(BEFORE_REVERT);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"File_OpenSys32 appwiz.cpl"));
 }
 
 TEST(FilePolicyTest, CheckNotFound) {
@@ -417,30 +444,38 @@
   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 notfound.exe"));
 }
 
+std::unique_ptr<TestRunner> QueryAttributesFileRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  EXPECT_TRUE(
+      runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"apphelp.dll"));
+  EXPECT_TRUE(
+      runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"notfound.exe"));
+  EXPECT_TRUE(runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"drivers"));
+  EXPECT_TRUE(
+      runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_QUERY, L"ipconfig.exe"));
+  return runner;
+}
+
 TEST(FilePolicyTest, TestQueryAttributesFile) {
-  TestRunner runner;
-  EXPECT_TRUE(
-      runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"apphelp.dll"));
-  EXPECT_TRUE(
-      runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"notfound.exe"));
-  EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"drivers"));
-  EXPECT_TRUE(
-      runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_QUERY, L"ipconfig.exe"));
-
+  auto runner = QueryAttributesFileRunner();
   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"File_QueryAttributes drivers d"));
+            runner->RunTest(L"File_QueryAttributes drivers d"));
 
+  runner = QueryAttributesFileRunner();
   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"File_QueryAttributes apphelp.dll f"));
+            runner->RunTest(L"File_QueryAttributes apphelp.dll f"));
 
+  runner = QueryAttributesFileRunner();
   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"File_QueryAttributes ipconfig.exe f"));
+            runner->RunTest(L"File_QueryAttributes ipconfig.exe f"));
 
+  runner = QueryAttributesFileRunner();
   EXPECT_EQ(SBOX_TEST_DENIED,
-            runner.RunTest(L"File_QueryAttributes ftp.exe f"));
+            runner->RunTest(L"File_QueryAttributes ftp.exe f"));
 
+  runner = QueryAttributesFileRunner();
   EXPECT_EQ(SBOX_TEST_NOT_FOUND,
-            runner.RunTest(L"File_QueryAttributes notfound.exe f"));
+            runner->RunTest(L"File_QueryAttributes notfound.exe f"));
 }
 
 // Makes sure that we don't leak information when there is not policy to allow
@@ -450,121 +485,139 @@
   EXPECT_EQ(SBOX_TEST_DENIED,
             runner.RunTest(L"File_QueryAttributes ftp.exe f"));
 
+  TestRunner runner2;
   EXPECT_EQ(SBOX_TEST_DENIED,
-            runner.RunTest(L"File_QueryAttributes notfound.exe f"));
+            runner2.RunTest(L"File_QueryAttributes notfound.exe f"));
+}
+
+// Expects 8 file names. Attempts to copy even to odd files will happen.
+std::unique_ptr<TestRunner> RenameRunner(
+    std::vector<std::wstring>& temp_files) {
+  auto runner = std::make_unique<TestRunner>();
+  // Add rules to make file0->file1 succeed.
+  runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_files[0].c_str());
+  runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_files[1].c_str());
+
+  // Add rules to make file2->file3 fail.
+  runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_files[2].c_str());
+  runner->AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_files[3].c_str());
+
+  // Add rules to make file4->file5 fail.
+  runner->AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_files[4].c_str());
+  runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_files[5].c_str());
+
+  // Add rules to make file6->no_pol_file fail.
+  runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_files[6].c_str());
+  return runner;
 }
 
 TEST(FilePolicyTest, TestRename) {
-  TestRunner runner;
+  const size_t nFiles = 8;
 
   // Give access to the temp directory.
   wchar_t temp_directory[MAX_PATH];
-  wchar_t temp_file_name1[MAX_PATH];
-  wchar_t temp_file_name2[MAX_PATH];
-  wchar_t temp_file_name3[MAX_PATH];
-  wchar_t temp_file_name4[MAX_PATH];
-  wchar_t temp_file_name5[MAX_PATH];
-  wchar_t temp_file_name6[MAX_PATH];
-  wchar_t temp_file_name7[MAX_PATH];
-  wchar_t temp_file_name8[MAX_PATH];
+  std::vector<std::wstring> temp_files;
   ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
-  ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name1), 0u);
-  ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name2), 0u);
-  ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name3), 0u);
-  ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name4), 0u);
-  ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name5), 0u);
-  ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name6), 0u);
-  ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name7), 0u);
-  ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name8), 0u);
-
-  // Add rules to make file1->file2 succeed.
-  ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name1));
-  ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name2));
-
-  // Add rules to make file3->file4 fail.
-  ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name3));
-  ASSERT_TRUE(
-      runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_file_name4));
-
-  // Add rules to make file5->file6 fail.
-  ASSERT_TRUE(
-      runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_file_name5));
-  ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name6));
-
-  // Add rules to make file7->no_pol_file fail.
-  ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name7));
+  for (size_t i = 0; i < nFiles; i++) {
+    wchar_t temp_file[MAX_PATH];
+    ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file), 0u);
+    temp_files.push_back(std::wstring(temp_file));
+  }
 
   // Delete the files where the files are going to be renamed to.
-  ::DeleteFile(temp_file_name2);
-  ::DeleteFile(temp_file_name4);
-  ::DeleteFile(temp_file_name6);
-  ::DeleteFile(temp_file_name8);
+  ::DeleteFile(temp_files[1].c_str());
+  ::DeleteFile(temp_files[3].c_str());
+  ::DeleteFile(temp_files[5].c_str());
+  ::DeleteFile(temp_files[7].c_str());
 
+  auto runner = RenameRunner(temp_files);
   wchar_t command[MAX_PATH * 2 + 20] = {};
-  wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name1,
-           temp_file_name2);
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command));
+  wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_files[0].c_str(),
+           temp_files[1].c_str());
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(command));
 
-  wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name3,
-           temp_file_name4);
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
+  runner = RenameRunner(temp_files);
+  wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_files[2].c_str(),
+           temp_files[3].c_str());
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command));
 
-  wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name5,
-           temp_file_name6);
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
+  runner = RenameRunner(temp_files);
+  wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_files[4].c_str(),
+           temp_files[5].c_str());
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command));
 
-  wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name7,
-           temp_file_name8);
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
+  runner = RenameRunner(temp_files);
+  wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_files[6].c_str(),
+           temp_files[7].c_str());
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command));
 
   // Delete all the files in case they are still there.
-  ::DeleteFile(temp_file_name1);
-  ::DeleteFile(temp_file_name2);
-  ::DeleteFile(temp_file_name3);
-  ::DeleteFile(temp_file_name4);
-  ::DeleteFile(temp_file_name5);
-  ::DeleteFile(temp_file_name6);
-  ::DeleteFile(temp_file_name7);
-  ::DeleteFile(temp_file_name8);
+  for (auto& file : temp_files)
+    ::DeleteFile(file.c_str());
+}
+
+std::unique_ptr<TestRunner> AllowNotepadRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"notepad.exe");
+  return runner;
 }
 
 TEST(FilePolicyTest, OpenSys32FilesAllowNotepad) {
-  TestRunner runner;
-  EXPECT_TRUE(
-      runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"notepad.exe"));
-
+  auto runner = AllowNotepadRunner();
   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"File_Win32Create notepad.exe"));
+            runner->RunTest(L"File_Win32Create notepad.exe"));
 
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create calc.exe"));
+  runner = AllowNotepadRunner();
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"File_Win32Create calc.exe"));
 
-  runner.SetTestState(BEFORE_REVERT);
+  runner = AllowNotepadRunner();
+  runner->SetTestState(BEFORE_REVERT);
   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"File_Win32Create notepad.exe"));
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_Win32Create calc.exe"));
+            runner->RunTest(L"File_Win32Create notepad.exe"));
+
+  runner = AllowNotepadRunner();
+  runner->SetTestState(BEFORE_REVERT);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"File_Win32Create calc.exe"));
+}
+
+std::unique_ptr<TestRunner> FileGetDiskSpaceRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_READONLY, L"");
+  return runner;
 }
 
 TEST(FilePolicyTest, FileGetDiskSpace) {
-  TestRunner runner;
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_GetDiskSpace"));
-  runner.SetTestState(BEFORE_REVERT);
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
+  auto runner = std::make_unique<TestRunner>();
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"File_GetDiskSpace"));
+
+  runner = std::make_unique<TestRunner>();
+  runner->SetTestState(BEFORE_REVERT);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"File_GetDiskSpace"));
 
   // Add an 'allow' rule in the windows\system32 such that GetDiskFreeSpaceEx
   // succeeds (it does an NtOpenFile) but windows\system32\notepad.exe is
   // denied since there is no wild card in the rule.
-  EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_READONLY, L""));
-  runner.SetTestState(BEFORE_REVERT);
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
+  runner = FileGetDiskSpaceRunner();
+  runner->SetTestState(BEFORE_REVERT);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"File_GetDiskSpace"));
 
-  runner.SetTestState(AFTER_REVERT);
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create notepad.exe"));
+  runner = FileGetDiskSpaceRunner();
+  runner->SetTestState(AFTER_REVERT);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"File_GetDiskSpace"));
+
+  runner = FileGetDiskSpaceRunner();
+  runner->SetTestState(AFTER_REVERT);
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"File_Win32Create notepad.exe"));
+}
+
+std::unique_ptr<TestRunner> ReparsePointRunner(
+    std::wstring& temp_dir_wildcard) {
+  auto runner = std::make_unique<TestRunner>();
+  runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_dir_wildcard.c_str());
+  return runner;
 }
 
 TEST(FilePolicyTest, TestReparsePoint) {
-  TestRunner runner;
-
   // Create a temp file because we need write access to it.
   wchar_t temp_directory[MAX_PATH];
   wchar_t temp_file_name[MAX_PATH];
@@ -597,8 +650,7 @@
 
   // Give write access to the temp directory.
   std::wstring temp_dir_wildcard = temp_dir + L"*";
-  EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY,
-                               temp_dir_wildcard.c_str()));
+  auto runner = ReparsePointRunner(temp_dir_wildcard);
 
   // Prepare the command to execute.
   std::wstring command_write;
@@ -607,7 +659,7 @@
   command_write += L"\"";
 
   // Verify that we have write access to the original file
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write.c_str()));
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(command_write.c_str()));
 
   // Replace the subfolder by a reparse point to %temp%.
   ::DeleteFile(temp_file.c_str());
@@ -623,7 +675,8 @@
   EXPECT_TRUE(::CloseHandle(dir));
 
   // Try to open the file again.
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write.c_str()));
+  runner = ReparsePointRunner(temp_dir_wildcard);
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command_write.c_str()));
 
   // Remove the reparse point.
   dir = ::CreateFile(subfolder.c_str(), FILE_WRITE_DATA,
diff --git a/sandbox/win/src/integrity_level_test.cc b/sandbox/win/src/integrity_level_test.cc
index 0fa2627..b698cc1 100644
--- a/sandbox/win/src/integrity_level_test.cc
+++ b/sandbox/win/src/integrity_level_test.cc
@@ -42,31 +42,39 @@
   return SBOX_TEST_DENIED;
 }
 
+std::unique_ptr<TestRunner> LowILRealRunner() {
+  auto runner = std::make_unique<TestRunner>(JOB_LOCKDOWN, USER_INTERACTIVE,
+                                             USER_INTERACTIVE);
+  runner->SetTimeout(INFINITE);
+  runner->GetPolicy()->SetAlternateDesktop(true);
+  runner->GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
+  return runner;
+}
+
 TEST(IntegrityLevelTest, TestLowILReal) {
-  TestRunner runner(JOB_LOCKDOWN, USER_INTERACTIVE, USER_INTERACTIVE);
+  auto runner = LowILRealRunner();
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"CheckIntegrityLevel"));
 
-  runner.SetTimeout(INFINITE);
+  runner = LowILRealRunner();
+  runner->SetTestState(BEFORE_REVERT);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"CheckIntegrityLevel"));
+}
 
-  runner.GetPolicy()->SetAlternateDesktop(true);
-  runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
-
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckIntegrityLevel"));
-
-  runner.SetTestState(BEFORE_REVERT);
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckIntegrityLevel"));
+std::unique_ptr<TestRunner> LowILDelayedRunner() {
+  auto runner = std::make_unique<TestRunner>(JOB_LOCKDOWN, USER_INTERACTIVE,
+                                             USER_INTERACTIVE);
+  runner->SetTimeout(INFINITE);
+  runner->GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW);
+  return runner;
 }
 
 TEST(DelayedIntegrityLevelTest, TestLowILDelayed) {
-  TestRunner runner(JOB_LOCKDOWN, USER_INTERACTIVE, USER_INTERACTIVE);
+  auto runner = LowILDelayedRunner();
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"CheckIntegrityLevel"));
 
-  runner.SetTimeout(INFINITE);
-
-  runner.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW);
-
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckIntegrityLevel"));
-
-  runner.SetTestState(BEFORE_REVERT);
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"CheckIntegrityLevel"));
+  runner = LowILDelayedRunner();
+  runner->SetTestState(BEFORE_REVERT);
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"CheckIntegrityLevel"));
 }
 
 TEST(IntegrityLevelTest, TestNoILChange) {
diff --git a/sandbox/win/src/ipc_ping_test.cc b/sandbox/win/src/ipc_ping_test.cc
index 44f6be4..39aa632 100644
--- a/sandbox/win/src/ipc_ping_test.cc
+++ b/sandbox/win/src/ipc_ping_test.cc
@@ -48,11 +48,14 @@
 }
 
 TEST(IPCTest, IPCPingTestWithOutput) {
-  TestRunner runner;
-  runner.SetTimeout(2000);
-  runner.SetTestState(EVERY_STATE);
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"IPC_Ping 2"));
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"IPC_Ping 2"));
+  TestRunner runner1;
+  runner1.SetTimeout(2000);
+  runner1.SetTestState(EVERY_STATE);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner1.RunTest(L"IPC_Ping 2"));
+  TestRunner runner2;
+  runner2.SetTimeout(2000);
+  runner2.SetTestState(EVERY_STATE);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(L"IPC_Ping 2"));
 }
 
 }  // namespace sandbox
diff --git a/sandbox/win/src/named_pipe_policy_test.cc b/sandbox/win/src/named_pipe_policy_test.cc
index 3d8db97..817aa43 100644
--- a/sandbox/win/src/named_pipe_policy_test.cc
+++ b/sandbox/win/src/named_pipe_policy_test.cc
@@ -52,39 +52,52 @@
   return SBOX_TEST_SUCCEEDED;
 }
 
-// Tests if we can create a pipe in the sandbox.
-TEST(NamedPipePolicyTest, CreatePipe) {
-  TestRunner runner;
+std::unique_ptr<TestRunner> CreatePipeRunner() {
+  auto runner = std::make_unique<TestRunner>();
   // TODO(nsylvain): This policy is wrong because "*" is a valid char in a
   // namedpipe name. Here we apply it like a wildcard. http://b/893603
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
-                             TargetPolicy::NAMEDPIPES_ALLOW_ANY,
-                             L"\\\\.\\pipe\\test*"));
+  runner->AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
+                  TargetPolicy::NAMEDPIPES_ALLOW_ANY, L"\\\\.\\pipe\\test*");
+  return runner;
+}
 
+// Tests if we can create a pipe in the sandbox.
+TEST(NamedPipePolicyTest, CreatePipe) {
+  auto runner = CreatePipeRunner();
   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
+            runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
 
+  runner = CreatePipeRunner();
   EXPECT_EQ(SBOX_TEST_DENIED,
-            runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
+            runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
+}
+
+std::unique_ptr<TestRunner> PipeTraversalRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  // TODO(nsylvain): This policy is wrong because "*" is a valid char in a
+  // namedpipe name. Here we apply it like a wildcard. http://b/893603
+  runner->AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
+                  TargetPolicy::NAMEDPIPES_ALLOW_ANY, L"\\\\.\\pipe\\test*");
+  return runner;
 }
 
 // Tests if we can create a pipe with a path traversal in the sandbox.
 TEST(NamedPipePolicyTest, CreatePipeTraversal) {
-  TestRunner runner;
-  // TODO(nsylvain): This policy is wrong because "*" is a valid char in a
-  // namedpipe name. Here we apply it like a wildcard. http://b/893603
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
-                             TargetPolicy::NAMEDPIPES_ALLOW_ANY,
-                             L"\\\\.\\pipe\\test*"));
+  auto runner = PipeTraversalRunner();
+  EXPECT_EQ(SBOX_TEST_DENIED,
+            runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\..\\bleh"));
 
+  runner = PipeTraversalRunner();
   EXPECT_EQ(SBOX_TEST_DENIED,
-            runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\..\\bleh"));
+            runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/../bleh"));
+
+  runner = PipeTraversalRunner();
   EXPECT_EQ(SBOX_TEST_DENIED,
-            runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/../bleh"));
+            runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\../bleh"));
+
+  runner = PipeTraversalRunner();
   EXPECT_EQ(SBOX_TEST_DENIED,
-            runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\../bleh"));
-  EXPECT_EQ(SBOX_TEST_DENIED,
-            runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/..\\bleh"));
+            runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/..\\bleh"));
 }
 
 // This tests that path canonicalization is actually disabled if we use \\?\
@@ -100,22 +113,25 @@
             NamedPipe_Create(2, const_cast<wchar_t**>(argv)));
 }
 
-// The same test as CreatePipe but this time using strict interceptions.
-TEST(NamedPipePolicyTest, CreatePipeStrictInterceptions) {
-  TestRunner runner;
-  runner.GetPolicy()->SetStrictInterceptions();
-
+std::unique_ptr<TestRunner> StrictInterceptionsRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  runner->GetPolicy()->SetStrictInterceptions();
   // TODO(nsylvain): This policy is wrong because "*" is a valid char in a
   // namedpipe name. Here we apply it like a wildcard. http://b/893603
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
-                             TargetPolicy::NAMEDPIPES_ALLOW_ANY,
-                             L"\\\\.\\pipe\\test*"));
+  runner->AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
+                  TargetPolicy::NAMEDPIPES_ALLOW_ANY, L"\\\\.\\pipe\\test*");
+  return runner;
+}
 
+// The same test as CreatePipe but this time using strict interceptions.
+TEST(NamedPipePolicyTest, CreatePipeStrictInterceptions) {
+  auto runner = StrictInterceptionsRunner();
   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
+            runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
 
+  runner = StrictInterceptionsRunner();
   EXPECT_EQ(SBOX_TEST_DENIED,
-            runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
+            runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
 }
 
 }  // namespace sandbox
diff --git a/sandbox/win/src/policy_target_test.cc b/sandbox/win/src/policy_target_test.cc
index b8b6859..1712142 100644
--- a/sandbox/win/src/policy_target_test.cc
+++ b/sandbox/win/src/policy_target_test.cc
@@ -180,11 +180,13 @@
   runner.SetTestState(BEFORE_REVERT);
   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token"));
 
-  runner.SetTestState(AFTER_REVERT);
-  EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token"));
+  TestRunner runner1;
+  runner1.SetTestState(AFTER_REVERT);
+  EXPECT_EQ(ERROR_NO_TOKEN, runner1.RunTest(L"PolicyTargetTest_token"));
 
-  runner.SetTestState(EVERY_STATE);
-  EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"PolicyTargetTest_steal"));
+  TestRunner runner2;
+  runner2.SetTestState(EVERY_STATE);
+  EXPECT_EQ(SBOX_TEST_FAILED, runner2.RunTest(L"PolicyTargetTest_steal"));
 }
 
 TEST(PolicyTargetTest, OpenThreadToken) {
@@ -192,18 +194,19 @@
   runner.SetTestState(BEFORE_REVERT);
   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token2"));
 
-  runner.SetTestState(AFTER_REVERT);
-  EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token2"));
+  TestRunner runner2;
+  runner2.SetTestState(AFTER_REVERT);
+  EXPECT_EQ(ERROR_NO_TOKEN, runner2.RunTest(L"PolicyTargetTest_token2"));
 }
 
 TEST(PolicyTargetTest, OpenThreadTokenEx) {
   TestRunner runner;
-
   runner.SetTestState(BEFORE_REVERT);
   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token3"));
 
-  runner.SetTestState(AFTER_REVERT);
-  EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token3"));
+  TestRunner runner2;
+  runner2.SetTestState(AFTER_REVERT);
+  EXPECT_EQ(ERROR_NO_TOKEN, runner2.RunTest(L"PolicyTargetTest_token3"));
 }
 
 TEST(PolicyTargetTest, OpenThread) {
@@ -211,7 +214,8 @@
   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread"))
       << "Opens the current thread";
 
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread2"))
+  TestRunner runner2;
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(L"PolicyTargetTest_thread2"))
       << "Creates a new thread and opens it";
 }
 
diff --git a/sandbox/win/src/process_mitigations_dyncode_unittest.cc b/sandbox/win/src/process_mitigations_dyncode_unittest.cc
index 21d7021f..b4dc8f2 100644
--- a/sandbox/win/src/process_mitigations_dyncode_unittest.cc
+++ b/sandbox/win/src/process_mitigations_dyncode_unittest.cc
@@ -244,6 +244,15 @@
   int return_code_;
 };
 
+// Helpers to set up rules for dynamic code tests, needed as policy
+// (from the TestRunner) can only be applied to a single process.
+std::unique_ptr<sandbox::TestRunner> RunnerWithMitigation(
+    sandbox::MitigationFlags mitigations) {
+  auto runner = std::make_unique<sandbox::TestRunner>();
+  runner->GetPolicy()->SetDelayedProcessMitigations(mitigations);
+  return runner;
+}
+
 //------------------------------------------------------------------------------
 // DisableDynamicCode test harness helper function.  Tests numerous APIs.
 // - APIs fail with ERROR_DYNAMIC_CODE_BLOCKED if this mitigation is
@@ -265,14 +274,6 @@
     return;
   }
 
-  sandbox::TestRunner runner;
-  sandbox::TargetPolicy* policy = runner.GetPolicy();
-
-  if (enable_mitigation) {
-    EXPECT_EQ(policy->SetDelayedProcessMitigations(which_mitigation),
-              sandbox::SBOX_ALL_OK);
-  }
-
   std::wstring shared =
       (which_mitigation == sandbox::MITIGATION_DYNAMIC_CODE_DISABLE)
           ? L"TestWin81DynamicCode "
@@ -283,32 +284,34 @@
   }
 
   // Test 1:
+  auto runner = enable_mitigation ? RunnerWithMitigation(which_mitigation)
+                                  : std::make_unique<sandbox::TestRunner>();
   std::wstring test =
       base::StringPrintf(L"%ls %u", shared.c_str(), VIRTUALALLOC);
   EXPECT_EQ((expect_success ? sandbox::SBOX_TEST_SUCCEEDED
                             : ERROR_DYNAMIC_CODE_BLOCKED),
-            runner.RunTest(test.c_str()));
+            runner->RunTest(test.c_str()));
 
   // Test 2:
+  runner = enable_mitigation ? RunnerWithMitigation(which_mitigation)
+                             : std::make_unique<sandbox::TestRunner>();
   test = base::StringPrintf(L"%ls %u", shared.c_str(), VIRTUALPROTECT);
   EXPECT_EQ((expect_success ? sandbox::SBOX_TEST_SUCCEEDED
                             : ERROR_DYNAMIC_CODE_BLOCKED),
-            runner.RunTest(test.c_str()));
+            runner->RunTest(test.c_str()));
 
   // Test 3:
   // Need token level >= USER_LIMITED to be able to successfully run test 3.
-  policy->SetTokenLevel(sandbox::TokenLevel::USER_RESTRICTED_SAME_ACCESS,
-                        sandbox::TokenLevel::USER_LIMITED);
+  runner = enable_mitigation ? RunnerWithMitigation(which_mitigation)
+                             : std::make_unique<sandbox::TestRunner>();
+  runner->GetPolicy()->SetTokenLevel(
+      sandbox::TokenLevel::USER_RESTRICTED_SAME_ACCESS,
+      sandbox::TokenLevel::USER_LIMITED);
 
   test = base::StringPrintf(L"%ls %u", shared.c_str(), MAPVIEWCUSTOM);
   EXPECT_EQ((expect_success ? sandbox::SBOX_TEST_SUCCEEDED
                             : ERROR_DYNAMIC_CODE_BLOCKED),
-            runner.RunTest(test.c_str()));
-
-  // Test 4:
-  // Set token levels back to default.
-  policy->SetTokenLevel(sandbox::TokenLevel::USER_RESTRICTED_SAME_ACCESS,
-                        sandbox::TokenLevel::USER_LOCKDOWN);
+            runner->RunTest(test.c_str()));
 
   // Ensure sandbox access to the file on disk.
   base::FilePath dll_path;
@@ -322,14 +325,16 @@
       temp_dir.GetPath().Append(hooking_dll::g_hook_dll_file);
   ASSERT_TRUE(base::CopyFile(dll_path, temp_dll_path));
 
-  EXPECT_TRUE(runner.AddFsRule(sandbox::TargetPolicy::FILES_ALLOW_ANY,
-                               temp_dll_path.value().c_str()));
+  runner = enable_mitigation ? RunnerWithMitigation(which_mitigation)
+                             : std::make_unique<sandbox::TestRunner>();
+  EXPECT_TRUE(runner->AddFsRule(sandbox::TargetPolicy::FILES_ALLOW_ANY,
+                                temp_dll_path.value().c_str()));
 
   test = base::StringPrintf(L"%ls %u \"%ls\"", shared.c_str(), MAPVIEWFILE,
                             temp_dll_path.value().c_str());
   EXPECT_EQ((expect_success ? sandbox::SBOX_TEST_SUCCEEDED
                             : ERROR_DYNAMIC_CODE_BLOCKED),
-            runner.RunTest(test.c_str()));
+            runner->RunTest(test.c_str()));
 }
 
 }  // namespace
diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc
index 54ba38e..9e9de1b1 100644
--- a/sandbox/win/src/sandbox_policy_base.cc
+++ b/sandbox/win/src/sandbox_policy_base.cc
@@ -487,7 +487,10 @@
   return SBOX_ALL_OK;
 }
 
-ResultCode PolicyBase::AddTarget(std::unique_ptr<TargetProcess> target) {
+ResultCode PolicyBase::ApplyToTarget(std::unique_ptr<TargetProcess> target) {
+  if (target_)
+    return SBOX_ERROR_UNEXPECTED_CALL;
+
   if (policy_) {
     if (!policy_maker_->Done())
       return SBOX_ERROR_NO_SPACE;
@@ -536,27 +539,19 @@
   if (SBOX_ALL_OK != ret)
     return ret;
 
-  base::AutoLock lock(lock_);
-  targets_.push_back(std::move(target));
+  target_ = std::move(target);
   return SBOX_ALL_OK;
 }
 
 bool PolicyBase::OnJobEmpty(HANDLE job) {
-  base::AutoLock lock(lock_);
-  targets_.erase(
-      std::remove_if(targets_.begin(), targets_.end(),
-                     [&](auto&& p) -> bool { return p->Job() == job; }),
-      targets_.end());
+  if (target_->Job() == job)
+    target_.reset();
   return true;
 }
 
 bool PolicyBase::OnProcessFinished(DWORD process_id) {
-  base::AutoLock lock(lock_);
-  targets_.erase(std::remove_if(targets_.begin(), targets_.end(),
-                                [&](auto&& p) -> bool {
-                                  return p->ProcessId() == process_id;
-                                }),
-                 targets_.end());
+  if (target_->ProcessId() == process_id)
+    target_.reset();
   return true;
 }
 
diff --git a/sandbox/win/src/sandbox_policy_base.h b/sandbox/win/src/sandbox_policy_base.h
index 7297412..a88a95b 100644
--- a/sandbox/win/src/sandbox_policy_base.h
+++ b/sandbox/win/src/sandbox_policy_base.h
@@ -100,9 +100,9 @@
                         base::win::ScopedHandle* lockdown,
                         base::win::ScopedHandle* lowbox);
 
-  // Adds a target process to the internal list of targets. Internally a
+  // Applies the sandbox to |target| and takes ownership. Internally a
   // call to TargetProcess::Init() is issued.
-  ResultCode AddTarget(std::unique_ptr<TargetProcess> target);
+  ResultCode ApplyToTarget(std::unique_ptr<TargetProcess> target);
 
   // Called when there are no more active processes in a Job.
   // Removes a Job object associated with this policy and the target associated
@@ -136,12 +136,8 @@
                              Semantics semantics,
                              const wchar_t* pattern);
 
-  // This lock synchronizes operations on the targets_ collection.
-  base::Lock lock_;
-  // Maintains the list of target process associated with this policy.
-  // The policy takes ownership of them.
-  typedef std::list<std::unique_ptr<TargetProcess>> TargetSet;
-  TargetSet targets_;
+  // The policy takes ownership of a target as it is applied to it.
+  std::unique_ptr<TargetProcess> target_;
   // Standard object-lifetime reference counter.
   volatile LONG ref_count;
   // The user-defined global policy settings.
diff --git a/sandbox/win/src/sandbox_policy_diagnostic.cc b/sandbox/win/src/sandbox_policy_diagnostic.cc
index a76a63e..6c4608f 100644
--- a/sandbox/win/src/sandbox_policy_diagnostic.cc
+++ b/sandbox/win/src/sandbox_policy_diagnostic.cc
@@ -379,13 +379,8 @@
 PolicyDiagnostic::PolicyDiagnostic(PolicyBase* policy) {
   DCHECK(policy);
   // TODO(crbug/997273) Add more fields once webui plumbing is complete.
-  {
-    base::AutoLock lock(policy->lock_);
-    for (auto&& target_process : policy->targets_) {
-      process_ids_.push_back(
-          base::strict_cast<uint32_t>(target_process->ProcessId()));
-    }
-  }
+  process_ids_.push_back(
+      base::strict_cast<uint32_t>(policy->target_->ProcessId()));
   lockdown_level_ = policy->lockdown_level_;
   job_level_ = policy->job_level_;
 
diff --git a/sandbox/win/src/unload_dll_test.cc b/sandbox/win/src/unload_dll_test.cc
index fc85c0c..2067f77 100644
--- a/sandbox/win/src/unload_dll_test.cc
+++ b/sandbox/win/src/unload_dll_test.cc
@@ -42,6 +42,17 @@
   return SBOX_TEST_SUCCEEDED;
 }
 
+std::unique_ptr<TestRunner> BaselineAvicapRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  runner->SetTestState(BEFORE_REVERT);
+  runner->SetTimeout(2000);
+  // Add a registry rule, because that ensures that the interception agent has
+  // more than one item in its internal table.
+  runner->AddRule(TargetPolicy::SUBSYS_FILES, TargetPolicy::FILES_ALLOW_QUERY,
+                  L"\\??\\*.exe");
+  return runner;
+}
+
 // Fails on Windows ARM64: https://crbug.com/905526
 #if defined(ARCH_CPU_ARM64)
 #define MAYBE_BaselineAvicapDll DISABLED_BaselineAvicapDll
@@ -49,49 +60,51 @@
 #define MAYBE_BaselineAvicapDll BaselineAvicapDll
 #endif
 TEST(UnloadDllTest, MAYBE_BaselineAvicapDll) {
-  TestRunner runner;
-  runner.SetTestState(BEFORE_REVERT);
-  runner.SetTimeout(2000);
-  // Add a registry rule, because that ensures that the interception agent has
-  // more than one item in its internal table.
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_FILES,
-                             TargetPolicy::FILES_ALLOW_QUERY, L"\\??\\*.exe"));
-
+  auto runner = BaselineAvicapRunner();
   // Note for the puzzled: avicap32.dll is a 64-bit dll in 64-bit versions of
   // windows so this test and the others just work.
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"UseOneDLL L avicap32.dll"));
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"UseOneDLL B avicap32.dll"));
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"UseOneDLL L avicap32.dll"));
+  runner = BaselineAvicapRunner();
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"UseOneDLL B avicap32.dll"));
+}
+
+std::unique_ptr<TestRunner> UnloadAvicapNoPatchingRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  runner->SetTestState(BEFORE_REVERT);
+  runner->SetTimeout(2000);
+  runner->GetPolicy()->AddDllToUnload(L"avicap32.dll");
+  return runner;
 }
 
 TEST(UnloadDllTest, UnloadAviCapDllNoPatching) {
-  TestRunner runner;
-  runner.SetTestState(BEFORE_REVERT);
-  runner.SetTimeout(2000);
-  sandbox::TargetPolicy* policy = runner.GetPolicy();
-  policy->AddDllToUnload(L"avicap32.dll");
-  EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"UseOneDLL L avicap32.dll"));
-  EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"UseOneDLL B avicap32.dll"));
+  auto runner = UnloadAvicapNoPatchingRunner();
+  EXPECT_EQ(SBOX_TEST_FAILED, runner->RunTest(L"UseOneDLL L avicap32.dll"));
+  runner = UnloadAvicapNoPatchingRunner();
+  EXPECT_EQ(SBOX_TEST_FAILED, runner->RunTest(L"UseOneDLL B avicap32.dll"));
 }
 
-TEST(UnloadDllTest, UnloadAviCapDllWithPatching) {
-  TestRunner runner;
-  runner.SetTimeout(2000);
-  runner.SetTestState(BEFORE_REVERT);
-  sandbox::TargetPolicy* policy = runner.GetPolicy();
-  policy->AddDllToUnload(L"avicap32.dll");
-
+std::unique_ptr<TestRunner> UnloadAvicapWithPatchingRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  runner->SetTestState(BEFORE_REVERT);
+  runner->SetTimeout(2000);
+  runner->GetPolicy()->AddDllToUnload(L"avicap32.dll");
   // Add a couple of rules that ensures that the interception agent add EAT
   // patching on the client which makes sure that the unload dll record does
   // not interact badly with them.
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_FILES,
-                             TargetPolicy::FILES_ALLOW_QUERY, L"\\??\\*.exe"));
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_FILES,
-                             TargetPolicy::FILES_ALLOW_QUERY, L"\\??\\*.log"));
+  runner->AddRule(TargetPolicy::SUBSYS_FILES, TargetPolicy::FILES_ALLOW_QUERY,
+                  L"\\??\\*.exe");
+  runner->AddRule(TargetPolicy::SUBSYS_FILES, TargetPolicy::FILES_ALLOW_QUERY,
+                  L"\\??\\*.log");
+  return runner;
+}
 
-  EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"UseOneDLL L avicap32.dll"));
+TEST(UnloadDllTest, UnloadAviCapDllWithPatching) {
+  auto runner = UnloadAvicapWithPatchingRunner();
+  EXPECT_EQ(SBOX_TEST_FAILED, runner->RunTest(L"UseOneDLL L avicap32.dll"));
 
-  runner.SetTestState(AFTER_REVERT);
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"OpenExecutablePath"));
+  runner = UnloadAvicapWithPatchingRunner();
+  runner->SetTestState(AFTER_REVERT);
+  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"OpenExecutablePath"));
 }
 
 }  // namespace sandbox
diff --git a/sandbox/win/tests/common/controller.cc b/sandbox/win/tests/common/controller.cc
index 27bf646..ffab034e 100644
--- a/sandbox/win/tests/common/controller.cc
+++ b/sandbox/win/tests/common/controller.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "base/dcheck_is_on.h"
 #include "base/memory/platform_shared_memory_region.h"
 #include "base/memory/read_only_shared_memory_region.h"
 #include "base/process/process.h"
@@ -226,6 +227,11 @@
       return SBOX_ERROR_GENERIC;
     }
   } else {
+#if DCHECK_IS_ON()
+    // Policy can be applied to one target only.
+    DCHECK(!policy_applied_);
+    policy_applied_ = true;
+#endif
     result = broker_->SpawnTarget(prog_name, arguments.c_str(), policy_,
                                   &warning_result, &last_error, &target);
   }
diff --git a/sandbox/win/tests/common/controller.h b/sandbox/win/tests/common/controller.h
index eaa5bb3..2997244 100644
--- a/sandbox/win/tests/common/controller.h
+++ b/sandbox/win/tests/common/controller.h
@@ -8,6 +8,7 @@
 #include <windows.h>
 #include <string>
 
+#include "base/dcheck_is_on.h"
 #include "base/memory/raw_ptr.h"
 #include "base/time/time.h"
 #include "base/win/scoped_handle.h"
@@ -169,6 +170,10 @@
   bool disable_csrss_;
   bool kill_on_destruction_;
   bool release_policy_in_run_ = false;
+#if DCHECK_IS_ON()
+  // We only allow the policy to be applied to a target once.
+  bool policy_applied_ = false;
+#endif
   base::win::ScopedHandle target_process_;
   DWORD target_process_id_;
 };
diff --git a/sandbox/win/tests/integration_tests/integration_tests_test.cc b/sandbox/win/tests/integration_tests/integration_tests_test.cc
index 662b61ac..a040d1e 100644
--- a/sandbox/win/tests/integration_tests/integration_tests_test.cc
+++ b/sandbox/win/tests/integration_tests/integration_tests_test.cc
@@ -223,8 +223,12 @@
   runner.SetTimeout(TestTimeouts::action_timeout());
   runner.SetTestState(BEFORE_INIT);
   ASSERT_EQ(1, runner.RunTest(L"IntegrationTestsTest_args first"));
-  ASSERT_EQ(4, runner.RunTest(L"IntegrationTestsTest_args first second third "
-                              L"fourth"));
+
+  TestRunner runner2;
+  runner2.SetTimeout(TestTimeouts::action_timeout());
+  runner2.SetTestState(BEFORE_INIT);
+  ASSERT_EQ(4, runner2.RunTest(L"IntegrationTestsTest_args first second third "
+                               L"fourth"));
 }
 
 TEST(IntegrationTestsTest, WaitForStuckChild) {
@@ -306,37 +310,40 @@
   ::TerminateProcess(runner2.process(), 0);
 }
 
-TEST(IntegrationTestsTest, MultipleStuckChildrenSequential) {
-  TestRunner runner;
-  runner.SetTimeout(TestTimeouts::action_timeout());
-  runner.SetAsynchronous(true);
-  runner.SetKillOnDestruction(false);
-  TestRunner runner2(JOB_NONE, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
-  runner2.SetTimeout(TestTimeouts::action_timeout());
-  runner2.SetAsynchronous(true);
-  runner2.SetKillOnDestruction(false);
+std::unique_ptr<TestRunner> StuckChildrenRunner() {
+  auto runner = std::make_unique<TestRunner>(
+      JOB_NONE, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
+  runner->SetTimeout(TestTimeouts::action_timeout());
+  runner->SetAsynchronous(true);
+  runner->SetKillOnDestruction(false);
+  return runner;
+}
 
+TEST(IntegrationTestsTest, MultipleStuckChildrenSequential) {
+  auto runner = StuckChildrenRunner();
   ASSERT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"IntegrationTestsTest_stuck 100"));
-  // Actually both runners share the same singleton broker.
-  ASSERT_EQ(SBOX_ALL_OK, runner.broker()->WaitForAllTargets());
+            runner->RunTest(L"IntegrationTestsTest_stuck 100"));
+  // All runners share the same singleton broker.
+  auto* broker = runner->broker();
+  ASSERT_EQ(SBOX_ALL_OK, broker->WaitForAllTargets());
+
+  runner = StuckChildrenRunner();
   ASSERT_EQ(SBOX_TEST_SUCCEEDED,
-            runner2.RunTest(L"IntegrationTestsTest_stuck 2000"));
-  // Actually both runners share the same singleton broker.
-  ASSERT_EQ(SBOX_ALL_OK, runner.broker()->WaitForAllTargets());
+            runner->RunTest(L"IntegrationTestsTest_stuck 2000"));
+  ASSERT_EQ(SBOX_ALL_OK, broker->WaitForAllTargets());
 
   DWORD exit_code;
   // Checking the exit code for |runner| is flaky on the slow bots but at
   // least we know that the wait above has succeeded if we are here.
-  ASSERT_TRUE(::GetExitCodeProcess(runner2.process(), &exit_code));
+  ASSERT_TRUE(::GetExitCodeProcess(runner->process(), &exit_code));
   ASSERT_EQ(STILL_ACTIVE, exit_code);
   // Terminate the test process now.
-  ::TerminateProcess(runner2.process(), 0);
+  ::TerminateProcess(runner->process(), 0);
 
+  runner = StuckChildrenRunner();
   ASSERT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"IntegrationTestsTest_stuck 100"));
-  // Actually both runners share the same singleton broker.
-  ASSERT_EQ(SBOX_ALL_OK, runner.broker()->WaitForAllTargets());
+            runner->RunTest(L"IntegrationTestsTest_stuck 100"));
+  ASSERT_EQ(SBOX_ALL_OK, broker->WaitForAllTargets());
 }
 
 // Running from inside job that allows us to escape from it should be ok.
diff --git a/sandbox/win/tests/validation_tests/suite.cc b/sandbox/win/tests/validation_tests/suite.cc
index dbfd80233..684ac70d5 100644
--- a/sandbox/win/tests/validation_tests/suite.cc
+++ b/sandbox/win/tests/validation_tests/suite.cc
@@ -13,32 +13,55 @@
 #include "sandbox/win/tests/common/controller.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+// Callback that generates fresh TestRunners for process access tests.
+typedef std::unique_ptr<sandbox::TestRunner> (*RunnerGenerator)();
+
 namespace {
 
-void TestProcessAccess(sandbox::TestRunner* runner, DWORD target) {
+void TestProcessAccess(RunnerGenerator runner_gen, DWORD target) {
   const wchar_t *kCommandTemplate = L"OpenProcessCmd %d %d";
   wchar_t command[1024] = {0};
+  std::unique_ptr<sandbox::TestRunner> runner = nullptr;
 
   // Test all the scary process permissions.
   wsprintf(command, kCommandTemplate, target, PROCESS_CREATE_THREAD);
+  runner = runner_gen();
   EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+
   wsprintf(command, kCommandTemplate, target, PROCESS_DUP_HANDLE);
+  runner = runner_gen();
   EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+
   wsprintf(command, kCommandTemplate, target, PROCESS_SET_INFORMATION);
+  runner = runner_gen();
   EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+
   wsprintf(command, kCommandTemplate, target, PROCESS_VM_OPERATION);
+  runner = runner_gen();
   EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+
   wsprintf(command, kCommandTemplate, target, PROCESS_VM_READ);
+  runner = runner_gen();
   EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+
   wsprintf(command, kCommandTemplate, target, PROCESS_VM_WRITE);
+  runner = runner_gen();
   EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+
   wsprintf(command, kCommandTemplate, target, PROCESS_QUERY_INFORMATION);
+  runner = runner_gen();
   EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+
   wsprintf(command, kCommandTemplate, target, WRITE_DAC);
+  runner = runner_gen();
   EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+
   wsprintf(command, kCommandTemplate, target, WRITE_OWNER);
+  runner = runner_gen();
   EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+
   wsprintf(command, kCommandTemplate, target, READ_CONTROL);
+  runner = runner_gen();
   EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
 }
 
@@ -78,50 +101,86 @@
   ASSERT_TRUE(VolumeSupportsACLs(L"%Temp%\\"));
   ASSERT_TRUE(VolumeSupportsACLs(L"%AppData%\\"));
 
-  TestRunner runner;
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %SystemDrive%"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %SystemRoot%"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %ProgramFiles%"));
+  TestRunner runner_sysdrive;
   EXPECT_EQ(SBOX_TEST_DENIED,
-      runner.RunTest(L"OpenFileCmd %SystemRoot%\\System32"));
+            runner_sysdrive.RunTest(L"OpenFileCmd %SystemDrive%"));
+
+  TestRunner runner_sysroot;
   EXPECT_EQ(SBOX_TEST_DENIED,
-      runner.RunTest(L"OpenFileCmd %SystemRoot%\\explorer.exe"));
+            runner_sysroot.RunTest(L"OpenFileCmd %SystemRoot%"));
+
+  TestRunner runner_programfiles;
   EXPECT_EQ(SBOX_TEST_DENIED,
-      runner.RunTest(L"OpenFileCmd %SystemRoot%\\Cursors\\arrow_i.cur"));
+            runner_programfiles.RunTest(L"OpenFileCmd %ProgramFiles%"));
+
+  TestRunner runner_system32;
   EXPECT_EQ(SBOX_TEST_DENIED,
-      runner.RunTest(L"OpenFileCmd %AllUsersProfile%"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %Temp%"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %AppData%"));
+            runner_system32.RunTest(L"OpenFileCmd %SystemRoot%\\System32"));
+
+  TestRunner runner_explorer;
+  EXPECT_EQ(SBOX_TEST_DENIED,
+            runner_explorer.RunTest(L"OpenFileCmd %SystemRoot%\\explorer.exe"));
+
+  TestRunner runner_cursors;
+  EXPECT_EQ(SBOX_TEST_DENIED,
+            runner_cursors.RunTest(
+                L"OpenFileCmd %SystemRoot%\\Cursors\\arrow_i.cur"));
+
+  TestRunner runner_profiles;
+  EXPECT_EQ(SBOX_TEST_DENIED,
+            runner_profiles.RunTest(L"OpenFileCmd %AllUsersProfile%"));
+
+  TestRunner runner_temp;
+  EXPECT_EQ(SBOX_TEST_DENIED, runner_temp.RunTest(L"OpenFileCmd %Temp%"));
+
+  TestRunner runner_appdata;
+  EXPECT_EQ(SBOX_TEST_DENIED, runner_appdata.RunTest(L"OpenFileCmd %AppData%"));
 }
 
 // Tests if the registry is correctly protected by the sandbox.
 TEST(ValidationSuite, TestRegistry) {
-  TestRunner runner;
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKLM"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKCU"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKU"));
-  EXPECT_EQ(SBOX_TEST_DENIED,
-      runner.RunTest(
+  TestRunner runner_hklm;
+  EXPECT_EQ(SBOX_TEST_DENIED, runner_hklm.RunTest(L"OpenKey HKLM"));
+
+  TestRunner runner_hkcu;
+  EXPECT_EQ(SBOX_TEST_DENIED, runner_hkcu.RunTest(L"OpenKey HKCU"));
+
+  TestRunner runner_hku;
+  EXPECT_EQ(SBOX_TEST_DENIED, runner_hku.RunTest(L"OpenKey HKU"));
+
+  TestRunner runner_hklm_key;
+  EXPECT_EQ(
+      SBOX_TEST_DENIED,
+      runner_hklm_key.RunTest(
           L"OpenKey HKLM "
           L"\"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon\""));
 }
 
+std::unique_ptr<TestRunner> DesktopRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  runner->GetPolicy()->SetAlternateDesktop(true);
+  runner->GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
+  return runner;
+}
+
 // Tests that the permissions on the Windowstation does not allow the sandbox
 // to get to the interactive desktop or to make the sbox desktop interactive.
 TEST(ValidationSuite, TestDesktop) {
-  TestRunner runner;
-  runner.GetPolicy()->SetAlternateDesktop(true);
-  runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenInteractiveDesktop NULL"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"SwitchToSboxDesktop NULL"));
+  auto runner = DesktopRunner();
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"OpenInteractiveDesktop NULL"));
+
+  runner = DesktopRunner();
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"SwitchToSboxDesktop NULL"));
 }
 
 // Tests that the permissions on the Windowstation does not allow the sandbox
 // to get to the interactive desktop or to make the sbox desktop interactive.
 TEST(ValidationSuite, TestAlternateDesktop) {
-  TestRunner runner;
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"EnumAlternateWinsta NULL"));
+  TestRunner runner_no_policy;
+  EXPECT_EQ(SBOX_TEST_DENIED,
+            runner_no_policy.RunTest(L"EnumAlternateWinsta NULL"));
 
+  TestRunner runner;
   wchar_t command[1024] = {0};
   runner.SetTimeout(3600000);
   runner.GetPolicy()->SetAlternateDesktop(true);
@@ -132,14 +191,21 @@
   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
 }
 
+std::unique_ptr<TestRunner> AlternateDesktopLocalWinstationRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  runner->GetPolicy()->SetAlternateDesktop(false);
+  runner->GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
+  return runner;
+}
+
 // Same as TestDesktop, but uses the local winstation, instead of an alternate
 // one.
 TEST(ValidationSuite, TestAlternateDesktopLocalWinstation) {
-  TestRunner runner;
-  runner.GetPolicy()->SetAlternateDesktop(false);
-  runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenInteractiveDesktop NULL"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"SwitchToSboxDesktop NULL"));
+  auto runner = AlternateDesktopLocalWinstationRunner();
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"OpenInteractiveDesktop NULL"));
+
+  runner = AlternateDesktopLocalWinstationRunner();
+  EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"SwitchToSboxDesktop NULL"));
 }
 
 // Tests if the windows are correctly protected by the sandbox.
@@ -152,65 +218,72 @@
     return;
   }
 
-  TestRunner runner;
   wchar_t command[1024] = {0};
 
+  TestRunner runner_getshellwindow;
   wsprintf(command, L"ValidWindow %Id",
            reinterpret_cast<size_t>(::GetShellWindow()));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
+  EXPECT_EQ(SBOX_TEST_DENIED, runner_getshellwindow.RunTest(command));
 
+  TestRunner runner_findwindow;
   wsprintf(command, L"ValidWindow %Id",
            reinterpret_cast<size_t>(::FindWindow(NULL, NULL)));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
+  EXPECT_EQ(SBOX_TEST_DENIED, runner_findwindow.RunTest(command));
+}
+
+std::unique_ptr<TestRunner> ProcessDenyLockdownRunner() {
+  return std::make_unique<TestRunner>();
 }
 
 // Tests that a locked-down process cannot open another locked-down process.
 TEST(ValidationSuite, TestProcessDenyLockdown) {
-  TestRunner runner;
   TestRunner target;
-
   target.SetAsynchronous(true);
 
   EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000"));
 
-  TestProcessAccess(&runner, target.process_id());
+  TestProcessAccess(ProcessDenyLockdownRunner, target.process_id());
+}
+
+std::unique_ptr<TestRunner> ProcessDenyLowIntegrityRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  runner->GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
+  runner->GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS,
+                                     USER_INTERACTIVE);
+  return runner;
 }
 
 // Tests that a low-integrity process cannot open a locked-down process (due
 // to the integrity label changing after startup via SetDelayedIntegrityLevel).
 TEST(ValidationSuite, TestProcessDenyLowIntegrity) {
-  TestRunner runner;
   TestRunner target;
-
   target.SetAsynchronous(true);
   target.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW);
 
-  runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
-  runner.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS,
-                                    USER_INTERACTIVE);
-
   EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000"));
 
-  TestProcessAccess(&runner, target.process_id());
+  TestProcessAccess(ProcessDenyLowIntegrityRunner, target.process_id());
+}
+
+std::unique_ptr<TestRunner> ProcessDenyBelowLowIntegrityRunner() {
+  auto runner = std::make_unique<TestRunner>();
+  runner->GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_UNTRUSTED);
+  runner->GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS,
+                                     USER_INTERACTIVE);
+  return runner;
 }
 
 // Tests that a locked-down process cannot open a low-integrity process.
 TEST(ValidationSuite, TestProcessDenyBelowLowIntegrity) {
-  TestRunner runner;
   TestRunner target;
-
   target.SetAsynchronous(true);
   target.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
   target.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS,
                                     USER_INTERACTIVE);
 
-  runner.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_UNTRUSTED);
-  runner.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS,
-                                    USER_INTERACTIVE);
-
   EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000"));
 
-  TestProcessAccess(&runner, target.process_id());
+  TestProcessAccess(ProcessDenyBelowLowIntegrityRunner, target.process_id());
 }
 
 // Tests if the threads are correctly protected by the sandbox.
diff --git a/services/device/geolocation/network_location_provider_unittest.cc b/services/device/geolocation/network_location_provider_unittest.cc
index beef6db..e038d93 100644
--- a/services/device/geolocation/network_location_provider_unittest.cc
+++ b/services/device/geolocation/network_location_provider_unittest.cc
@@ -265,7 +265,7 @@
       return testing::AssertionFailure()
              << "Actual dictionary " << PrettyJson(actual)
              << " is missing field " << field;
-    if (!expected_value->Equals(actual_value))
+    if (*expected_value != *actual_value)
       return testing::AssertionFailure()
              << "Field " << field
              << " mismatch: " << PrettyJson(*expected_value)
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn
index 9ddb57d..678a48b6 100644
--- a/services/network/BUILD.gn
+++ b/services/network/BUILD.gn
@@ -161,6 +161,7 @@
     "upload_progress_tracker.h",
     "url_loader.cc",
     "url_loader.h",
+    "url_loader_context.h",
     "url_loader_factory.cc",
     "url_loader_factory.h",
     "url_request_context_builder_mojo.cc",
@@ -520,6 +521,8 @@
     "test/test_utils.h",
     "test/udp_socket_test_util.cc",
     "test/udp_socket_test_util.h",
+    "test/url_loader_context_for_tests.cc",
+    "test/url_loader_context_for_tests.h",
   ]
 
   if (is_chromeos_ash) {
diff --git a/services/network/test/url_loader_context_for_tests.cc b/services/network/test/url_loader_context_for_tests.cc
new file mode 100644
index 0000000..1434fe4
--- /dev/null
+++ b/services/network/test/url_loader_context_for_tests.cc
@@ -0,0 +1,73 @@
+// Copyright 2022 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/network/test/url_loader_context_for_tests.h"
+
+namespace network {
+
+URLLoaderContextForTests::URLLoaderContextForTests() = default;
+URLLoaderContextForTests::~URLLoaderContextForTests() = default;
+
+bool URLLoaderContextForTests::ShouldRequireNetworkIsolationKey() const {
+  return false;
+}
+
+const cors::OriginAccessList& URLLoaderContextForTests::GetOriginAccessList()
+    const {
+  return origin_access_list_;
+}
+
+const mojom::URLLoaderFactoryParams&
+URLLoaderContextForTests::GetFactoryParams() const {
+  return factory_params_;
+}
+
+mojom::CookieAccessObserver* URLLoaderContextForTests::GetCookieAccessObserver()
+    const {
+  return nullptr;
+}
+
+mojom::CrossOriginEmbedderPolicyReporter*
+URLLoaderContextForTests::GetCoepReporter() const {
+  return nullptr;
+}
+
+mojom::DevToolsObserver* URLLoaderContextForTests::GetDevToolsObserver() const {
+  return nullptr;
+}
+
+mojom::NetworkContextClient* URLLoaderContextForTests::GetNetworkContextClient()
+    const {
+  return network_context_client_;
+}
+
+mojom::OriginPolicyManager* URLLoaderContextForTests::GetOriginPolicyManager()
+    const {
+  return origin_policy_manager_;
+}
+
+mojom::TrustedURLLoaderHeaderClient*
+URLLoaderContextForTests::GetUrlLoaderHeaderClient() const {
+  return nullptr;
+}
+
+mojom::URLLoaderNetworkServiceObserver*
+URLLoaderContextForTests::GetURLLoaderNetworkServiceObserver() const {
+  return nullptr;
+}
+
+net::URLRequestContext* URLLoaderContextForTests::GetUrlRequestContext() const {
+  return url_request_context_;
+}
+
+scoped_refptr<ResourceSchedulerClient>
+URLLoaderContextForTests::GetResourceSchedulerClient() const {
+  return resource_scheduler_client_;
+}
+
+uintptr_t URLLoaderContextForTests::GetFactoryId() const {
+  return 0;
+}
+
+}  // namespace network
diff --git a/services/network/test/url_loader_context_for_tests.h b/services/network/test/url_loader_context_for_tests.h
new file mode 100644
index 0000000..1876394
--- /dev/null
+++ b/services/network/test/url_loader_context_for_tests.h
@@ -0,0 +1,71 @@
+// Copyright 2022 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_NETWORK_TEST_URL_LOADER_CONTEXT_FOR_TESTS_H_
+#define SERVICES_NETWORK_TEST_URL_LOADER_CONTEXT_FOR_TESTS_H_
+
+#include "services/network/public/cpp/cors/origin_access_list.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/resource_scheduler/resource_scheduler_client.h"
+#include "services/network/url_loader_context.h"
+
+namespace network {
+
+class URLLoaderContextForTests : public URLLoaderContext {
+ public:
+  URLLoaderContextForTests();
+  ~URLLoaderContextForTests() override;
+
+  URLLoaderContextForTests(const URLLoaderContextForTests&) = delete;
+  URLLoaderContextForTests& operator=(const URLLoaderContextForTests&) = delete;
+
+  // Accessors to let tests configure some aspects of `this` object.
+  mojom::URLLoaderFactoryParams& mutable_factory_params() {
+    return factory_params_;
+  }
+  void set_network_context_client(mojom::NetworkContextClient* new_value) {
+    network_context_client_ = new_value;
+  }
+  void set_origin_policy_manager(mojom::OriginPolicyManager* new_value) {
+    origin_policy_manager_ = new_value;
+  }
+  void set_url_request_context(net::URLRequestContext* new_value) {
+    url_request_context_ = new_value;
+  }
+  void set_resource_scheduler_client(
+      const scoped_refptr<ResourceSchedulerClient>& new_value) {
+    resource_scheduler_client_ = new_value;
+  }
+
+  // URLLoaderContext implementation.
+  bool ShouldRequireNetworkIsolationKey() const override;
+  const cors::OriginAccessList& GetOriginAccessList() const override;
+  const mojom::URLLoaderFactoryParams& GetFactoryParams() const override;
+  mojom::CookieAccessObserver* GetCookieAccessObserver() const override;
+  mojom::CrossOriginEmbedderPolicyReporter* GetCoepReporter() const override;
+  mojom::DevToolsObserver* GetDevToolsObserver() const override;
+  mojom::NetworkContextClient* GetNetworkContextClient() const override;
+  mojom::OriginPolicyManager* GetOriginPolicyManager() const override;
+  mojom::TrustedURLLoaderHeaderClient* GetUrlLoaderHeaderClient()
+      const override;
+  mojom::URLLoaderNetworkServiceObserver* GetURLLoaderNetworkServiceObserver()
+      const override;
+  net::URLRequestContext* GetUrlRequestContext() const override;
+  scoped_refptr<ResourceSchedulerClient> GetResourceSchedulerClient()
+      const override;
+  uintptr_t GetFactoryId() const override;
+
+ private:
+  mojom::URLLoaderFactoryParams factory_params_;
+  cors::OriginAccessList origin_access_list_;
+
+  mojom::NetworkContextClient* network_context_client_ = nullptr;
+  mojom::OriginPolicyManager* origin_policy_manager_ = nullptr;
+  net::URLRequestContext* url_request_context_ = nullptr;
+  scoped_refptr<ResourceSchedulerClient> resource_scheduler_client_;
+};
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_TEST_URL_LOADER_CONTEXT_FOR_TESTS_H_
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index 8dfd13c5..0621f51 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -469,6 +469,11 @@
   }
 }
 
+template <typename T>
+T* PtrOrFallback(const mojo::Remote<T>& remote, T* fallback) {
+  return remote.is_bound() ? remote.get() : fallback;
+}
+
 }  // namespace
 
 URLLoader::MaybeSyncURLLoaderClient::MaybeSyncURLLoaderClient(
@@ -499,9 +504,7 @@
 }
 
 URLLoader::URLLoader(
-    net::URLRequestContext* url_request_context,
-    URLLoaderFactory* url_loader_factory,
-    mojom::NetworkContextClient* network_context_client,
+    const URLLoaderContext& context,
     DeleteCallback delete_callback,
     mojo::PendingReceiver<mojom::URLLoader> url_loader_receiver,
     int32_t options,
@@ -509,32 +512,25 @@
     mojo::PendingRemote<mojom::URLLoaderClient> url_loader_client,
     base::WeakPtr<mojom::URLLoaderClient> sync_url_loader_client,
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
-    const mojom::URLLoaderFactoryParams* factory_params,
-    mojom::CrossOriginEmbedderPolicyReporter* coep_reporter,
     uint32_t request_id,
     int keepalive_request_size,
-    bool require_network_isolation_key,
-    scoped_refptr<ResourceSchedulerClient> resource_scheduler_client,
     base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder,
-    mojom::TrustedURLLoaderHeaderClient* url_loader_header_client,
-    mojom::OriginPolicyManager* origin_policy_manager,
     std::unique_ptr<TrustTokenRequestHelperFactory> trust_token_helper_factory,
-    const cors::OriginAccessList& origin_access_list,
     mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer,
     mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>
         url_loader_network_observer,
     mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer,
     mojo::PendingRemote<mojom::AcceptCHFrameObserver> accept_ch_frame_observer)
-    : url_request_context_(url_request_context),
-      url_loader_factory_(url_loader_factory),
-      network_context_client_(network_context_client),
+    : url_request_context_(context.GetUrlRequestContext()),
+      url_loader_factory_id_(context.GetFactoryId()),
+      network_context_client_(context.GetNetworkContextClient()),
       delete_callback_(std::move(delete_callback)),
       options_(options),
       corb_detachable_(request.corb_detachable),
       resource_type_(request.resource_type),
       is_load_timing_enabled_(request.enable_load_timing),
-      factory_params_(factory_params),
-      coep_reporter_(coep_reporter),
+      factory_params_(context.GetFactoryParams()),
+      coep_reporter_(context.GetCoepReporter()),
       request_id_(request_id),
       keepalive_request_size_(keepalive_request_size),
       keepalive_(request.keepalive),
@@ -552,17 +548,25 @@
       request_mode_(request.mode),
       request_credentials_mode_(request.credentials_mode),
       request_destination_(request.destination),
-      resource_scheduler_client_(std::move(resource_scheduler_client)),
+      resource_scheduler_client_(context.GetResourceSchedulerClient()),
       keepalive_statistics_recorder_(std::move(keepalive_statistics_recorder)),
       custom_proxy_pre_cache_headers_(request.custom_proxy_pre_cache_headers),
       custom_proxy_post_cache_headers_(request.custom_proxy_post_cache_headers),
       fetch_window_id_(request.fetch_window_id),
       target_ip_address_space_(request.target_ip_address_space),
       trust_token_helper_factory_(std::move(trust_token_helper_factory)),
-      origin_access_list_(origin_access_list),
-      cookie_observer_(std::move(cookie_observer)),
-      url_loader_network_observer_(std::move(url_loader_network_observer)),
-      devtools_observer_(std::move(devtools_observer)),
+      origin_access_list_(context.GetOriginAccessList()),
+      cookie_observer_remote_(std::move(cookie_observer)),
+      cookie_observer_(PtrOrFallback(cookie_observer_remote_,
+                                     context.GetCookieAccessObserver())),
+      url_loader_network_observer_remote_(
+          std::move(url_loader_network_observer)),
+      url_loader_network_observer_(
+          PtrOrFallback(url_loader_network_observer_remote_,
+                        context.GetURLLoaderNetworkServiceObserver())),
+      devtools_observer_remote_(std::move(devtools_observer)),
+      devtools_observer_(PtrOrFallback(devtools_observer_remote_,
+                                       context.GetDevToolsObserver())),
       has_fetch_streaming_upload_body_(HasFetchStreamingUploadBody(&request)),
       allow_http1_for_streaming_upload_(
           request.request_body &&
@@ -571,8 +575,9 @@
   TRACE_EVENT("loading", "URLLoader::URLLoader",
               perfetto::Flow::FromPointer(this));
   DCHECK(delete_callback_);
-  DCHECK(factory_params_);
 
+  mojom::TrustedURLLoaderHeaderClient* url_loader_header_client =
+      context.GetUrlLoaderHeaderClient();
   if (url_loader_header_client &&
       (options_ & mojom::kURLLoadOptionUseHeaderClient)) {
     if (options_ & mojom::kURLLoadOptionAsCorsPreflight) {
@@ -609,8 +614,8 @@
   url_request_->set_referrer_policy(request.referrer_policy);
   url_request_->set_upgrade_if_insecure(request.upgrade_if_insecure);
 
-  if (!factory_params_->isolation_info.IsEmpty()) {
-    url_request_->set_isolation_info(factory_params_->isolation_info);
+  if (!factory_params_.isolation_info.IsEmpty()) {
+    url_request_->set_isolation_info(factory_params_.isolation_info);
   } else if (request.trusted_params &&
              !request.trusted_params->isolation_info.IsEmpty()) {
     url_request_->set_isolation_info(request.trusted_params->isolation_info);
@@ -618,14 +623,14 @@
       DCHECK(url_request_->isolation_info().site_for_cookies().IsEquivalent(
           request.site_for_cookies));
     }
-  } else if (factory_params_->automatically_assign_isolation_info) {
+  } else if (factory_params_.automatically_assign_isolation_info) {
     url::Origin origin = url::Origin::Create(request.url);
     url_request_->set_isolation_info(
         net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther,
                                    origin, origin, net::SiteForCookies()));
   }
 
-  if (require_network_isolation_key)
+  if (context.ShouldRequireNetworkIsolationKey())
     DCHECK(!url_request_->isolation_info().IsEmpty());
 
   if (ShouldForceIgnoreTopFramePartyForCookies())
@@ -643,7 +648,7 @@
     url_request_->set_force_main_frame_for_same_site_cookies(true);
   }
 
-  if (factory_params_->disable_secure_dns ||
+  if (factory_params_.disable_secure_dns ||
       (request.trusted_params && request.trusted_params->disable_secure_dns)) {
     url_request_->SetSecureDnsPolicy(net::SecureDnsPolicy::kDisable);
   }
@@ -654,8 +659,8 @@
   net::HttpRequestHeaders merged_headers = request.headers;
   merged_headers.MergeFrom(request.cors_exempt_headers);
   if (request.obey_origin_policy) {
-    DCHECK(origin_policy_manager);
-    origin_policy_manager_ = origin_policy_manager;
+    origin_policy_manager_ = context.GetOriginPolicyManager();
+    DCHECK(origin_policy_manager_);
   }
   // This should be ensured by the CorsURLLoaderFactory(), which is called
   // before URLLoaders are created.
@@ -670,7 +675,7 @@
   if (request.trusted_params) {
     has_user_activation_ = request.trusted_params->has_user_activation;
 
-    if (factory_params_->client_security_state) {
+    if (factory_params_.client_security_state) {
       // Enforce that only one ClientSecurityState is ever given to us, as this
       // is an invariant in the current codebase. In case of a compromised
       // renderer process, we might be passed both, in which case we prefer to
@@ -693,7 +698,7 @@
 
   SetFetchMetadataHeaders(url_request_.get(), request_mode_,
                           has_user_activation_, request_destination_, nullptr,
-                          *factory_params_, origin_access_list_);
+                          factory_params_, origin_access_list_);
 
   if (request.update_first_party_url_on_redirect) {
     url_request_->set_first_party_url_policy(
@@ -715,8 +720,8 @@
       &URLLoader::NotifyEarlyResponse, base::Unretained(this)));
 
   if (keepalive_ && keepalive_statistics_recorder_) {
-    keepalive_statistics_recorder_->OnLoadStarted(
-        *factory_params_->top_frame_id, keepalive_request_size_);
+    keepalive_statistics_recorder_->OnLoadStarted(*factory_params_.top_frame_id,
+                                                  keepalive_request_size_);
   }
 
   if (request.net_log_reference_info) {
@@ -868,7 +873,7 @@
   }
   url_request_->LogBlockedBy("Opening Files");
   file_opener_for_upload_ = std::make_unique<FileOpenerForUpload>(
-      std::move(paths), this, factory_params_->process_id,
+      std::move(paths), this, factory_params_.process_id,
       network_context_client_,
       base::BindOnce(&URLLoader::SetUpUpload, base::Unretained(this), request));
 }
@@ -932,13 +937,12 @@
                                   weak_ptr_factory_.GetWeakPtr(),
                                   net::ERR_TRUST_TOKEN_OPERATION_FAILED));
 
-    auto* devtools_observer = GetDevToolsObserver();
-    if (devtools_observer && devtools_request_id()) {
+    if (devtools_observer_ && devtools_request_id()) {
       mojom::TrustTokenOperationResultPtr operation_result =
           mojom::TrustTokenOperationResult::New();
       operation_result->status = *trust_token_status_;
       operation_result->type = type;
-      devtools_observer->OnTrustTokenOperationDone(
+      devtools_observer_->OnTrustTokenOperationDone(
           devtools_request_id().value(), std::move(operation_result));
     }
     return;
@@ -1008,7 +1012,7 @@
   RecordBodyReadFromNetBeforePausedIfNeeded();
   if (keepalive_ && keepalive_statistics_recorder_) {
     keepalive_statistics_recorder_->OnLoadFinished(
-        *factory_params_->top_frame_id, keepalive_request_size_);
+        *factory_params_.top_frame_id, keepalive_request_size_);
   }
 }
 
@@ -1103,8 +1107,8 @@
   // a factory) or the URLLoaderFactory's params. We prefer the factory params
   // over the request params, as the former always come from the browser
   // process.
-  if (factory_params_->client_security_state) {
-    return factory_params_->client_security_state.get();
+  if (factory_params_.client_security_state) {
+    return factory_params_.client_security_state.get();
   }
 
   return request_client_security_state_.get();
@@ -1157,8 +1161,8 @@
   // the policy set in `security_state->private_network_request_policy`.
   DCHECK(security_state);
 
-  if (auto* devtools_observer = GetDevToolsObserver()) {
-    devtools_observer->OnPrivateNetworkRequest(
+  if (devtools_observer_) {
+    devtools_observer_->OnPrivateNetworkRequest(
         devtools_request_id(), url_request_->url(), is_warning,
         resource_ip_address_space_, security_state->Clone());
   }
@@ -1233,8 +1237,8 @@
   const CrossOriginEmbedderPolicy kEmpty;
   // Enforce the Cross-Origin-Resource-Policy (CORP) header.
   const CrossOriginEmbedderPolicy& cross_origin_embedder_policy =
-      factory_params_->client_security_state
-          ? factory_params_->client_security_state->cross_origin_embedder_policy
+      factory_params_.client_security_state
+          ? factory_params_.client_security_state->cross_origin_embedder_policy
           : kEmpty;
 
   if (absl::optional<mojom::BlockedByResponseReason> blocked_reason =
@@ -1268,7 +1272,7 @@
   MaybeRemoveSecHeaders(url_request_.get(), redirect_info.new_url);
   SetFetchMetadataHeaders(url_request_.get(), request_mode_,
                           has_user_activation_, request_destination_,
-                          &redirect_info.new_url, *factory_params_,
+                          &redirect_info.new_url, factory_params_,
                           origin_access_list_);
 
   // The target IP address space is no longer relevant, it only applied to the
@@ -1315,8 +1319,7 @@
     // |this| may have been deleted.
     return;
   }
-  auto* url_loader_network_observer = GetURLLoaderNetworkServiceObserver();
-  if (!url_loader_network_observer) {
+  if (!url_loader_network_observer_) {
     OnAuthCredentials(absl::nullopt);
     return;
   }
@@ -1328,7 +1331,7 @@
 
   DCHECK(!auth_challenge_responder_receiver_.is_bound());
 
-  url_loader_network_observer->OnAuthRequired(
+  url_loader_network_observer_->OnAuthRequired(
       fetch_window_id_, request_id_, url_request_->url(), first_auth_attempt_,
       auth_info, url_request->response_headers(),
       auth_challenge_responder_receiver_.BindNewPipeAndPassRemote());
@@ -1342,8 +1345,7 @@
 void URLLoader::OnCertificateRequested(net::URLRequest* unused,
                                        net::SSLCertRequestInfo* cert_info) {
   DCHECK(!client_cert_responder_receiver_.is_bound());
-  auto* url_loader_network_observer = GetURLLoaderNetworkServiceObserver();
-  if (!url_loader_network_observer) {
+  if (!url_loader_network_observer_) {
     CancelRequest();
     return;
   }
@@ -1351,7 +1353,7 @@
   // Set up mojo endpoints for ClientCertificateResponder and bind to the
   // Receiver. This enables us to receive messages regarding the client
   // certificate selection.
-  url_loader_network_observer->OnCertificateRequested(
+  url_loader_network_observer_->OnCertificateRequested(
       fetch_window_id_, cert_info,
       client_cert_responder_receiver_.BindNewPipeAndPassRemote());
   client_cert_responder_receiver_.set_disconnect_handler(
@@ -1362,12 +1364,11 @@
                                       int net_error,
                                       const net::SSLInfo& ssl_info,
                                       bool fatal) {
-  auto* url_loader_network_observer = GetURLLoaderNetworkServiceObserver();
-  if (!url_loader_network_observer) {
+  if (!url_loader_network_observer_) {
     OnSSLCertificateErrorResponse(ssl_info, net::ERR_INSECURE_RESPONSE);
     return;
   }
-  url_loader_network_observer->OnSSLCertificateError(
+  url_loader_network_observer_->OnSSLCertificateError(
       url_request_->url(), net_error, ssl_info, fatal,
       base::BindOnce(&URLLoader::OnSSLCertificateErrorResponse,
                      weak_ptr_factory_.GetWeakPtr(), ssl_info));
@@ -1425,15 +1426,14 @@
 void URLLoader::MaybeSendTrustTokenOperationResultToDevTools() {
   CHECK(trust_token_helper_ && trust_token_status_);
 
-  auto* devtools_observer = GetDevToolsObserver();
-  if (!devtools_observer || !devtools_request_id())
+  if (!devtools_observer_ || !devtools_request_id())
     return;
 
   mojom::TrustTokenOperationResultPtr operation_result =
       trust_token_helper_->CollectOperationResultWithStatus(
           *trust_token_status_);
-  devtools_observer->OnTrustTokenOperationDone(devtools_request_id().value(),
-                                               std::move(operation_result));
+  devtools_observer_->OnTrustTokenOperationDone(devtools_request_id().value(),
+                                                std::move(operation_result));
 }
 
 void URLLoader::ContinueOnResponseStarted() {
@@ -1475,8 +1475,8 @@
   // Enforce the Cross-Origin-Resource-Policy (CORP) header.
   const CrossOriginEmbedderPolicy kEmpty;
   const CrossOriginEmbedderPolicy& cross_origin_embedder_policy =
-      factory_params_->client_security_state
-          ? factory_params_->client_security_state->cross_origin_embedder_policy
+      factory_params_.client_security_state
+          ? factory_params_.client_security_state->cross_origin_embedder_policy
           : kEmpty;
   if (absl::optional<mojom::BlockedByResponseReason> blocked_reason =
           CrossOriginResourcePolicy::IsBlocked(
@@ -1498,7 +1498,7 @@
   corb::LogUmaForOpaqueResponseBlocking(
       url_request_->url(), url_request_->initiator(), request_mode_,
       request_destination_, *response_);
-  if (factory_params_->is_corb_enabled) {
+  if (factory_params_.is_corb_enabled) {
     corb_analyzer_ = corb::ResponseAnalyzer::Create();
     auto decision =
         corb_analyzer_->Init(url_request_->url(), url_request_->initiator(),
@@ -1812,7 +1812,7 @@
 }
 
 int32_t URLLoader::GetProcessId() const {
-  return factory_params_->process_id;
+  return factory_params_.process_id;
 }
 
 void URLLoader::SetEnableReportingRawHeaders(bool allow) {
@@ -1929,11 +1929,10 @@
     upload_progress_tracker_ = nullptr;
   }
 
-  auto* url_loader_network_observer = GetURLLoaderNetworkServiceObserver();
-  if (url_loader_network_observer &&
+  if (url_loader_network_observer_ &&
       (url_request_->GetTotalReceivedBytes() > 0 ||
        url_request_->GetTotalSentBytes() > 0)) {
-    url_loader_network_observer->OnDataUseUpdate(
+    url_loader_network_observer_->OnDataUseUpdate(
         url_request_->traffic_annotation().unique_id_hash_code,
         url_request_->GetTotalReceivedBytes(),
         url_request_->GetTotalSentBytes());
@@ -2068,10 +2067,9 @@
 
 void URLLoader::SetRawRequestHeadersAndNotify(
     net::HttpRawRequestHeaders headers) {
-  auto* devtools_observer = GetDevToolsObserver();
   // If we have seen_raw_request_headers_, then don't notify DevTools to prevent
   // duplicate ExtraInfo events.
-  if (!seen_raw_request_headers_ && devtools_observer &&
+  if (!seen_raw_request_headers_ && devtools_observer_ &&
       devtools_request_id()) {
     std::vector<network::mojom::HttpRawHeaderPairPtr> header_array;
     header_array.reserve(headers.headers().size());
@@ -2086,7 +2084,7 @@
     DispatchOnRawRequest(std::move(header_array));
   }
 
-  if (auto* cookie_observer = GetCookieAccessObserver()) {
+  if (cookie_observer_) {
     std::vector<mojom::CookieOrLineWithAccessResultPtr> reported_cookies;
     for (const auto& cookie_with_access_result :
          url_request_->maybe_sent_cookies()) {
@@ -2099,7 +2097,7 @@
     }
 
     if (!reported_cookies.empty()) {
-      cookie_observer->OnCookiesAccessed(mojom::CookieAccessDetails::New(
+      cookie_observer_->OnCookiesAccessed(mojom::CookieAccessDetails::New(
           mojom::CookieAccessDetails::Type::kRead, url_request_->url(),
           url_request_->site_for_cookies(), std::move(reported_cookies),
           devtools_request_id()));
@@ -2109,14 +2107,13 @@
 
 void URLLoader::DispatchOnRawRequest(
     std::vector<network::mojom::HttpRawHeaderPairPtr> headers) {
-  auto* devtools_observer = GetDevToolsObserver();
-  DCHECK(devtools_observer && devtools_request_id());
+  DCHECK(devtools_observer_ && devtools_request_id());
 
   seen_raw_request_headers_ = true;
 
   mojom::ClientSecurityStatePtr client_security_state;
-  if (factory_params_->client_security_state) {
-    client_security_state = factory_params_->client_security_state->Clone();
+  if (factory_params_.client_security_state) {
+    client_security_state = factory_params_.client_security_state->Clone();
   } else if (request_client_security_state_) {
     client_security_state = request_client_security_state_->Clone();
   }
@@ -2125,15 +2122,14 @@
   url_request_->GetLoadTimingInfo(&load_timing_info);
 
   emitted_devtools_raw_request_ = true;
-  devtools_observer->OnRawRequest(
+  devtools_observer_->OnRawRequest(
       devtools_request_id().value(), url_request_->maybe_sent_cookies(),
       std::move(headers), load_timing_info.request_start,
       std::move(client_security_state));
 }
 
 bool URLLoader::DispatchOnRawResponse() {
-  auto* devtools_observer = GetDevToolsObserver();
-  if (!devtools_observer || !devtools_request_id() ||
+  if (!devtools_observer_ || !devtools_request_id() ||
       !url_request_->response_headers()) {
     return false;
   }
@@ -2183,7 +2179,7 @@
   }
 
   emitted_devtools_raw_response_ = true;
-  devtools_observer->OnRawResponse(
+  devtools_observer_->OnRawResponse(
       devtools_request_id().value(), url_request_->maybe_stored_cookies(),
       std::move(header_array), raw_response_headers, resource_ip_address_space_,
       response_headers->response_code());
@@ -2361,7 +2357,7 @@
 }
 
 void URLLoader::ReportFlaggedResponseCookies() {
-  if (auto* cookie_observer = GetCookieAccessObserver()) {
+  if (cookie_observer_) {
     std::vector<mojom::CookieOrLineWithAccessResultPtr> reported_cookies;
     for (const auto& cookie_line_and_access_result :
          url_request_->maybe_stored_cookies()) {
@@ -2383,7 +2379,7 @@
     }
 
     if (!reported_cookies.empty()) {
-      cookie_observer->OnCookiesAccessed(mojom::CookieAccessDetails::New(
+      cookie_observer_->OnCookiesAccessed(mojom::CookieAccessDetails::New(
           mojom::CookieAccessDetails::Type::kChange, url_request_->url(),
           url_request_->site_for_cookies(), std::move(reported_cookies),
           devtools_request_id()));
@@ -2502,31 +2498,6 @@
       });
 }
 
-mojom::DevToolsObserver* URLLoader::GetDevToolsObserver() const {
-  if (devtools_observer_)
-    return devtools_observer_.get();
-  if (url_loader_factory_)
-    return url_loader_factory_->GetDevToolsObserver();
-  return nullptr;
-}
-
-mojom::CookieAccessObserver* URLLoader::GetCookieAccessObserver() const {
-  if (cookie_observer_)
-    return cookie_observer_.get();
-  if (url_loader_factory_)
-    return url_loader_factory_->GetCookieAccessObserver();
-  return nullptr;
-}
-
-mojom::URLLoaderNetworkServiceObserver*
-URLLoader::GetURLLoaderNetworkServiceObserver() const {
-  if (url_loader_network_observer_)
-    return url_loader_network_observer_.get();
-  if (url_loader_factory_)
-    return url_loader_factory_->GetURLLoaderNetworkServiceObserver();
-  return nullptr;
-}
-
 void URLLoader::SetRequestCredentials(const GURL& url) {
   bool coep_allow_credentials = CoepAllowCredentials(url);
 
@@ -2574,12 +2545,12 @@
   }
 
   // [spec]: 2. If request’s client is null, then return true.
-  if (!factory_params_->client_security_state)
+  if (!factory_params_.client_security_state)
     return true;
 
   // [spec]: 3. If request’s client’s policy container’s embedder policy’s value
   //            is not "credentialless", then return true.
-  if (factory_params_->client_security_state->cross_origin_embedder_policy
+  if (factory_params_.client_security_state->cross_origin_embedder_policy
           .value != mojom::CrossOriginEmbedderPolicyValue::kCredentialless) {
     return true;
   }
diff --git a/services/network/url_loader.h b/services/network/url_loader.h
index dac720bb..959a22d 100644
--- a/services/network/url_loader.h
+++ b/services/network/url_loader.h
@@ -49,6 +49,7 @@
 #include "services/network/trust_tokens/trust_token_request_helper.h"
 #include "services/network/trust_tokens/trust_token_request_helper_factory.h"
 #include "services/network/upload_progress_tracker.h"
+#include "services/network/url_loader_context.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace net {
@@ -129,19 +130,25 @@
   };
 
   // |delete_callback| tells the URLLoader's owner to destroy the URLLoader.
-  // The URLLoader must be destroyed before the |url_request_context|.
-  // The |origin_policy_manager| must always be provided for requests that
-  // have the |obey_origin_policy| flag set.
+  //
+  // The |context.origin_policy_manager| must always be provided for requests
+  // that have the |obey_origin_policy| flag set.
+  //
   // |trust_token_helper_factory| must be non-null exactly when the request has
   // Trust Tokens parameters.
-  // |url_loader_factory| is the factory that created this URLLoader, it will
-  // outlive the lifecycle of this URLLoader. It may be null in tests. The
-  // factory will be used for callbacks if |dev_tools_observer|,
-  // |cookie_access_observer| or |url_loader_network_observer| are not provided.
+  //
+  // The caller needs to guarantee that the pointers/references in the
+  // |context| will live longer than the constructed URLLoader.  One
+  // (incomplete) reason why this guarantee is true in production code is that
+  // |context| is implemented by URLLoaderFactory which outlives the lifecycle
+  // of the URLLoader (and some pointers in |context| point to objects owned by
+  // URLLoaderFactory).
+  //
+  // Pointers from the |url_loader_context| will be used if
+  // |dev_tools_observer|, |cookie_access_observer| or
+  // |url_loader_network_observer| are not provided.
   URLLoader(
-      net::URLRequestContext* url_request_context,
-      URLLoaderFactory* url_loader_factory,
-      mojom::NetworkContextClient* network_context_client,
+      const URLLoaderContext& context,
       DeleteCallback delete_callback,
       mojo::PendingReceiver<mojom::URLLoader> url_loader_receiver,
       int32_t options,
@@ -149,18 +156,11 @@
       mojo::PendingRemote<mojom::URLLoaderClient> url_loader_client,
       base::WeakPtr<mojom::URLLoaderClient> sync_url_loader_client,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
-      const mojom::URLLoaderFactoryParams* factory_params,
-      mojom::CrossOriginEmbedderPolicyReporter* reporter,
       uint32_t request_id,
       int keepalive_request_size,
-      bool require_network_isolation_key,
-      scoped_refptr<ResourceSchedulerClient> resource_scheduler_client,
       base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder,
-      mojom::TrustedURLLoaderHeaderClient* url_loader_header_client,
-      mojom::OriginPolicyManager* origin_policy_manager,
       std::unique_ptr<TrustTokenRequestHelperFactory>
           trust_token_helper_factory,
-      const cors::OriginAccessList& origin_access_list,
       mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer,
       mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>
           url_loader_network_observer,
@@ -215,7 +215,9 @@
       absl::optional<GURL>* preserve_fragment_on_redirect_url);
 
   mojom::URLLoaderNetworkServiceObserver* GetURLLoaderNetworkServiceObserver()
-      const;
+      const {
+    return url_loader_network_observer_;
+  }
 
   // mojom::AuthChallengeResponder:
   void OnAuthCredentials(
@@ -258,9 +260,7 @@
     return devtools_request_id_;
   }
 
-  const URLLoaderFactory* url_loader_factory() const {
-    return url_loader_factory_;
-  }
+  uintptr_t url_loader_factory_id() const { return url_loader_factory_id_; }
 
   void SetEnableReportingRawHeaders(bool enable);
 
@@ -427,9 +427,6 @@
   PrivateNetworkAccessCheckResult PrivateNetworkAccessCheck(
       const net::TransportInfo& info);
 
-  mojom::DevToolsObserver* GetDevToolsObserver() const;
-  mojom::CookieAccessObserver* GetCookieAccessObserver() const;
-
   // Determine given the |url|, whether the |url_request_| should include
   // credentials and client certificates.
   void SetRequestCredentials(const GURL& url);
@@ -443,9 +440,9 @@
 
   raw_ptr<net::URLRequestContext> url_request_context_;
 
-  // |url_loader_factory_| is guaranteed to outlive URLLoader, so it is safe to
-  // store a raw pointer here. It can also be null in tests.
-  const raw_ptr<URLLoaderFactory> url_loader_factory_;
+  // A helper for checking if `this` URLLoader came from the given
+  // URLLoaderFactory.
+  const uintptr_t url_loader_factory_id_ = 0;
 
   raw_ptr<mojom::NetworkContextClient> network_context_client_;
   DeleteCallback delete_callback_;
@@ -458,7 +455,7 @@
 
   // URLLoaderFactory is guaranteed to outlive URLLoader, so it is safe to
   // store a raw pointer to mojom::URLLoaderFactoryParams.
-  const raw_ptr<const mojom::URLLoaderFactoryParams> factory_params_;
+  const mojom::URLLoaderFactoryParams& factory_params_;
   // This also belongs to URLLoaderFactory and outlives this loader.
   const raw_ptr<mojom::CrossOriginEmbedderPolicyReporter> coep_reporter_;
 
@@ -600,15 +597,21 @@
   // Outlives `this`.
   const cors::OriginAccessList& origin_access_list_;
 
-  // Observers bound to this specific URLLoader. There may be observers
-  // bound to an URLLoaderFactory as well so these members should not be
-  // used directly, but the GetXXXObserver APIs should be used instead as that
-  // will load the appropriate Observer from the |url_loader_factory_| if
-  // these observers aren't bound.
-  mojo::Remote<mojom::CookieAccessObserver> cookie_observer_;
-  mojo::Remote<mojom::URLLoaderNetworkServiceObserver>
-      url_loader_network_observer_;
-  mojo::Remote<mojom::DevToolsObserver> devtools_observer_;
+  // Observers bound to this specific URLLoader. There may be observers bound to
+  // an URLLoaderFactory as well so these `mojo::Remote`s should not be used
+  // directly, but the pointer fields should be used instead (e.g.
+  // `cookie_observer_` should be used since, it can be set to *either*
+  // `cookie_observer_.get()` *or* is can be pointing to some other
+  // CookieAccessObserver implementation from the URLLoaderContext aka
+  // URLLoaderFactory).
+  const mojo::Remote<mojom::CookieAccessObserver> cookie_observer_remote_;
+  mojom::CookieAccessObserver* const cookie_observer_ = nullptr;
+  const mojo::Remote<mojom::URLLoaderNetworkServiceObserver>
+      url_loader_network_observer_remote_;
+  mojom::URLLoaderNetworkServiceObserver* const url_loader_network_observer_ =
+      nullptr;
+  const mojo::Remote<mojom::DevToolsObserver> devtools_observer_remote_;
+  mojom::DevToolsObserver* const devtools_observer_ = nullptr;
 
   // Client security state copied from the input ResourceRequest.
   //
diff --git a/services/network/url_loader_context.h b/services/network/url_loader_context.h
new file mode 100644
index 0000000..ca5fa3b
--- /dev/null
+++ b/services/network/url_loader_context.h
@@ -0,0 +1,66 @@
+// Copyright 2022 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_NETWORK_URL_LOADER_CONTEXT_H_
+#define SERVICES_NETWORK_URL_LOADER_CONTEXT_H_
+
+#include "base/component_export.h"
+#include "base/memory/ref_counted.h"
+
+namespace net {
+class URLRequestContext;
+}  // namespace net
+
+namespace network {
+
+class ResourceSchedulerClient;
+
+namespace cors {
+class OriginAccessList;
+}  // namespace cors
+
+namespace mojom {
+class CookieAccessObserver;
+class CrossOriginEmbedderPolicyReporter;
+class DevToolsObserver;
+class NetworkContextClient;
+class OriginPolicyManager;
+class TrustedURLLoaderHeaderClient;
+class URLLoaderFactoryParams;
+class URLLoaderNetworkServiceObserver;
+}  // namespace mojom
+
+// An interface implemented in production code by network::URLLoaderFactory (or
+// by URLLoaderContextForTests in unit tests).
+class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoaderContext {
+ public:
+  virtual bool ShouldRequireNetworkIsolationKey() const = 0;
+  virtual const cors::OriginAccessList& GetOriginAccessList() const = 0;
+  virtual const mojom::URLLoaderFactoryParams& GetFactoryParams() const = 0;
+  virtual mojom::CookieAccessObserver* GetCookieAccessObserver() const = 0;
+  virtual mojom::CrossOriginEmbedderPolicyReporter* GetCoepReporter() const = 0;
+  virtual mojom::DevToolsObserver* GetDevToolsObserver() const = 0;
+  virtual mojom::NetworkContextClient* GetNetworkContextClient() const = 0;
+  virtual mojom::OriginPolicyManager* GetOriginPolicyManager() const = 0;
+  virtual mojom::TrustedURLLoaderHeaderClient* GetUrlLoaderHeaderClient()
+      const = 0;
+  virtual mojom::URLLoaderNetworkServiceObserver*
+  GetURLLoaderNetworkServiceObserver() const = 0;
+  virtual net::URLRequestContext* GetUrlRequestContext() const = 0;
+  virtual scoped_refptr<ResourceSchedulerClient> GetResourceSchedulerClient()
+      const = 0;
+
+  // TODO(https://crbug.com/1276591): Remove GetFactoryId once
+  // kOptimizeUpdateLoadInfo is enabled.
+  virtual uintptr_t GetFactoryId() const = 0;
+
+ protected:
+  // `protected` destructor = can only destruct via concrete implementations
+  // (and not via an URLLoaderContext pointer).
+  virtual ~URLLoaderContext() {}
+};
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_URL_LOADER_CONTEXT_H_
diff --git a/services/network/url_loader_factory.cc b/services/network/url_loader_factory.cc
index a549715..d89f4bf 100644
--- a/services/network/url_loader_factory.cc
+++ b/services/network/url_loader_factory.cc
@@ -126,6 +126,50 @@
   NOTREACHED();
 }
 
+net::URLRequestContext* URLLoaderFactory::GetUrlRequestContext() const {
+  return context_->url_request_context();
+}
+
+mojom::NetworkContextClient* URLLoaderFactory::GetNetworkContextClient() const {
+  return context_->client();
+}
+
+const mojom::URLLoaderFactoryParams& URLLoaderFactory::GetFactoryParams()
+    const {
+  return *params_;
+}
+
+mojom::CrossOriginEmbedderPolicyReporter* URLLoaderFactory::GetCoepReporter()
+    const {
+  return cors_url_loader_factory_->coep_reporter();
+}
+
+bool URLLoaderFactory::ShouldRequireNetworkIsolationKey() const {
+  return context_->require_network_isolation_key();
+}
+
+scoped_refptr<ResourceSchedulerClient>
+URLLoaderFactory::GetResourceSchedulerClient() const {
+  return resource_scheduler_client_;
+}
+
+mojom::TrustedURLLoaderHeaderClient*
+URLLoaderFactory::GetUrlLoaderHeaderClient() const {
+  return header_client_.is_bound() ? header_client_.get() : nullptr;
+}
+
+mojom::OriginPolicyManager* URLLoaderFactory::GetOriginPolicyManager() const {
+  return context_->origin_policy_manager();
+}
+
+const cors::OriginAccessList& URLLoaderFactory::GetOriginAccessList() const {
+  return context_->cors_origin_access_list();
+}
+
+uintptr_t URLLoaderFactory::GetFactoryId() const {
+  return reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(this));
+}
+
 void URLLoaderFactory::CreateLoaderAndStartWithSyncClient(
     mojo::PendingReceiver<mojom::URLLoader> receiver,
     int32_t request_id,
@@ -275,20 +319,16 @@
   }
 
   auto loader = std::make_unique<URLLoader>(
-      context_->url_request_context(), this, context_->client(),
+      *this,
       base::BindOnce(&cors::CorsURLLoaderFactory::DestroyURLLoader,
                      base::Unretained(cors_url_loader_factory_)),
       std::move(receiver), options, url_request, std::move(client),
       std::move(sync_client),
       static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
-      params_.get(), cors_url_loader_factory_->coep_reporter(), request_id,
-      keepalive_request_size, context_->require_network_isolation_key(),
-      resource_scheduler_client_, std::move(keepalive_statistics_recorder),
-      header_client_.is_bound() ? header_client_.get() : nullptr,
-      context_->origin_policy_manager(), std::move(trust_token_factory),
-      context_->cors_origin_access_list(), std::move(cookie_observer),
-      std::move(url_loader_network_observer), std::move(devtools_observer),
-      std::move(accept_ch_frame_observer));
+      request_id, keepalive_request_size,
+      std::move(keepalive_statistics_recorder), std::move(trust_token_factory),
+      std::move(cookie_observer), std::move(url_loader_network_observer),
+      std::move(devtools_observer), std::move(accept_ch_frame_observer));
 
   cors_url_loader_factory_->OnURLLoaderCreated(std::move(loader));
 }
@@ -352,7 +392,7 @@
   } else {
     for (auto* request : *context_->url_request_context()->url_requests()) {
       auto* loader = URLLoader::ForRequest(*request);
-      if (!loader || loader->url_loader_factory() != this)
+      if (!loader || loader->url_loader_factory_id() != GetFactoryId())
         continue;
       mojom::LoadInfoPtr load_info = loader->CreateLoadInfo();
       if (!most_interesting ||
diff --git a/services/network/url_loader_factory.h b/services/network/url_loader_factory.h
index 095ccf87..7a9b47c 100644
--- a/services/network/url_loader_factory.h
+++ b/services/network/url_loader_factory.h
@@ -16,6 +16,7 @@
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "services/network/public/mojom/url_loader_network_service_observer.mojom.h"
+#include "services/network/url_loader_context.h"
 
 namespace network {
 
@@ -39,7 +40,8 @@
 // Note that the CORS related part is implemented in CorsURLLoader[Factory]
 // and NetworkContext::CreateURLLoaderFactory returns a CorsURLLoaderFactory,
 // instead of a URLLoaderFactory.
-class URLLoaderFactory : public mojom::URLLoaderFactory {
+class URLLoaderFactory : public mojom::URLLoaderFactory,
+                         public URLLoaderContext {
  public:
   // NOTE: |context| must outlive this instance.
   URLLoaderFactory(
@@ -63,6 +65,24 @@
                                 traffic_annotation) override;
   void Clone(mojo::PendingReceiver<mojom::URLLoaderFactory> receiver) override;
 
+  // URLLoaderContext implementation.
+  bool ShouldRequireNetworkIsolationKey() const override;
+  const cors::OriginAccessList& GetOriginAccessList() const override;
+  const mojom::URLLoaderFactoryParams& GetFactoryParams() const override;
+  mojom::CookieAccessObserver* GetCookieAccessObserver() const override;
+  mojom::CrossOriginEmbedderPolicyReporter* GetCoepReporter() const override;
+  mojom::DevToolsObserver* GetDevToolsObserver() const override;
+  mojom::NetworkContextClient* GetNetworkContextClient() const override;
+  mojom::OriginPolicyManager* GetOriginPolicyManager() const override;
+  mojom::TrustedURLLoaderHeaderClient* GetUrlLoaderHeaderClient()
+      const override;
+  mojom::URLLoaderNetworkServiceObserver* GetURLLoaderNetworkServiceObserver()
+      const override;
+  net::URLRequestContext* GetUrlRequestContext() const override;
+  scoped_refptr<ResourceSchedulerClient> GetResourceSchedulerClient()
+      const override;
+  uintptr_t GetFactoryId() const override;
+
   // Allows starting a URLLoader with a synchronous URLLoaderClient as an
   // optimization.
   void CreateLoaderAndStartWithSyncClient(
@@ -74,11 +94,6 @@
       base::WeakPtr<mojom::URLLoaderClient> sync_client,
       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);
 
-  mojom::DevToolsObserver* GetDevToolsObserver() const;
-  mojom::CookieAccessObserver* GetCookieAccessObserver() const;
-  mojom::URLLoaderNetworkServiceObserver* GetURLLoaderNetworkServiceObserver()
-      const;
-
   static constexpr int kMaxKeepaliveConnections = 2048;
   static constexpr int kMaxKeepaliveConnectionsPerTopLevelFrame = 256;
   static constexpr int kMaxTotalKeepaliveRequestSize = 512 * 1024;
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc
index 5193f36b..d816188d 100644
--- a/services/network/url_loader_unittest.cc
+++ b/services/network/url_loader_unittest.cc
@@ -102,6 +102,7 @@
 #include "services/network/test/test_network_context_client.h"
 #include "services/network/test/test_url_loader_client.h"
 #include "services/network/test/test_url_loader_network_observer.h"
+#include "services/network/test/url_loader_context_for_tests.h"
 #include "services/network/test_chunked_data_pipe_getter.h"
 #include "services/network/trust_tokens/trust_token_key_commitment_getter.h"
 #include "services/network/trust_tokens/trust_token_request_helper.h"
@@ -636,10 +637,12 @@
     unowned_test_network_delegate_ = test_network_delegate.get();
     context_builder.set_network_delegate(std::move(test_network_delegate));
     context_builder.set_client_socket_factory_for_testing(GetSocketFactory());
-    context_ = context_builder.Build();
+    url_request_context_ = context_builder.Build();
+    context().set_url_request_context(url_request_context_.get());
     resource_scheduler_client_ = base::MakeRefCounted<ResourceSchedulerClient>(
         kProcessId, kRouteId, &resource_scheduler_,
-        context_->network_quality_estimator());
+        url_request_context_->network_quality_estimator());
+    context().set_resource_scheduler_client(resource_scheduler_client_.get());
 
     test_server_.AddDefaultHandlers(
         base::FilePath(FILE_PATH_LITERAL("services/test/data")));
@@ -660,7 +663,8 @@
   }
 
   void TearDown() override {
-    context_.reset();
+    context().set_resource_scheduler_client(nullptr);
+    url_request_context_.reset();
     net::QuicSimpleTestServer::Shutdown();
   }
 
@@ -707,6 +711,7 @@
       network_context_client->set_ignore_last_upload_file(
           ignore_last_upload_file_);
     }
+    context().set_network_context_client(network_context_client.get());
     if (ignore_certificate_errors_) {
       url_loader_network_observer =
           std::make_unique<TestURLLoaderNetworkObserver>();
@@ -717,27 +722,23 @@
     mojo::Remote<mojom::URLLoader> loader;
     std::unique_ptr<URLLoader> url_loader;
 
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = mojom::kBrowserProcessId;
-    params.is_corb_enabled = corb_enabled_;
-    params.client_security_state.Swap(&factory_client_security_state_);
+    context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+    context().mutable_factory_params().is_corb_enabled = corb_enabled_;
+    context().mutable_factory_params().client_security_state.Swap(
+        &factory_client_security_state_);
+    context().mutable_factory_params().isolation_info =
+        net::IsolationInfo::CreateForInternalRequest(
+            url::Origin::Create(request.url));
+    context().mutable_factory_params().is_trusted = true;
 
-    url::Origin origin = url::Origin::Create(request.url);
-    params.isolation_info =
-        net::IsolationInfo::CreateForInternalRequest(origin);
-    params.is_trusted = true;
     url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr, network_context_client.get(),
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.BindNewPipeAndPassReceiver(), options, request,
         client_.CreateRemote(), nullptr /* sync_url_loader_client */,
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-        /*coep_reporter=*/nullptr, 0 /* request_id */,
-        0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+        0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         url_loader_network_observer
             ? url_loader_network_observer->Bind()
             : mojo::NullRemote() /* url_loader_network_observer */,
@@ -843,12 +844,11 @@
   }
 
   net::EmbeddedTestServer* test_server() { return &test_server_; }
-  net::URLRequestContext* context() { return context_.get(); }
-  TestURLLoaderClient* client() { return &client_; }
-  void DestroyContext() {
-    resource_scheduler_client_ = nullptr;
-    context_.reset();
+  net::URLRequestContext* url_request_context() {
+    return url_request_context_.get();
   }
+  URLLoaderContextForTests& context() { return url_loader_context_for_tests_; }
+  TestURLLoaderClient* client() { return &client_; }
 
   // Returns the path of the requested file in the test data directory.
   base::FilePath GetTestFilePath(const std::string& file_name) {
@@ -1040,8 +1040,9 @@
   net::EmbeddedTestServer test_server_;
   std::unique_ptr<net::ScopedDefaultHostResolverProc> mock_host_resolver_;
   raw_ptr<net::TestNetworkDelegate>
-      unowned_test_network_delegate_;  // owned by |context_|
-  std::unique_ptr<net::URLRequestContext> context_;
+      unowned_test_network_delegate_;  // owned by |url_request_context_|
+  std::unique_ptr<net::URLRequestContext> url_request_context_;
+  URLLoaderContextForTests url_loader_context_for_tests_;
   ResourceScheduler resource_scheduler_;
   scoped_refptr<ResourceSchedulerClient> resource_scheduler_client_;
 
@@ -1070,8 +1071,6 @@
   net::test_server::HttpRequest sent_request_;
   TestURLLoaderClient client_;
 
-  const cors::OriginAccessList kEmptyOriginAccessList;
-
   raw_ptr<MockAcceptCHFrameObserver> accept_ch_frame_observer_ = nullptr;
 };
 
@@ -2178,21 +2177,15 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -2238,21 +2231,15 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -2299,20 +2286,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
       nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
-      &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+      nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -2380,20 +2362,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
       nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
-      &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+      nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -2451,20 +2428,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
       nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
-      &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+      nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -2517,20 +2489,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
       nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
-      &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+      nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -2772,21 +2739,18 @@
 
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
-  static mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   auto network_context_client =
       std::make_unique<CallbackSavingNetworkContextClient>();
+  context().set_network_context_client(network_context_client.get());
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr, network_context_client.get(),
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
       nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
-      &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+      nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -2907,21 +2871,16 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
       nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
-      &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      nullptr /* resource_scheduler_client */,
-      nullptr /* keepalive_statistics_reporter */, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      0 /* request_id */, 0 /* keepalive_request_size */,
+      nullptr /* keepalive_statistics_reporter */,
+      nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -2961,21 +2920,16 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
       nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
-      &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      nullptr /* resource_scheduler_client */,
-      nullptr /* keepalive_statistics_reporter */, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      0 /* request_id */, 0 /* keepalive_request_size */,
+      nullptr /* keepalive_statistics_reporter */,
+      nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3070,25 +3024,21 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   auto network_context_client = std::make_unique<TestNetworkContextClient>();
+  context().set_network_context_client(network_context_client.get());
   TestURLLoaderNetworkObserver url_loader_network_observer;
   url_loader_network_observer.set_ignore_certificate_errors(true);
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr, network_context_client.get(),
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(),
       mojom::kURLLoadOptionSendSSLInfoWithResponse |
           mojom::kURLLoadOptionSendSSLInfoForCertificateError,
       request, client.CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       url_loader_network_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3110,21 +3060,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3170,22 +3114,16 @@
     base::RunLoop delete_run_loop;
     mojo::Remote<mojom::URLLoader> loader;
     std::unique_ptr<URLLoader> url_loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = mojom::kBrowserProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        nullptr /* network_context_client */,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
         client.CreateRemote(), nullptr /* sync_url_loader_client */,
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-        /*coep_reporter=*/nullptr, 0 /* request_id */,
-        0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+        0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3216,21 +3154,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       client.CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3275,21 +3207,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3324,21 +3250,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3378,20 +3298,14 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3435,20 +3349,14 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3501,20 +3409,14 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3573,20 +3475,14 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
       request, client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3611,20 +3507,14 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
       request, client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3714,26 +3604,20 @@
   std::vector<
       std::pair<std::unique_ptr<URLLoader>, mojo::Remote<mojom::URLLoader>>>
       loaders;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   for (int i = 0; i < kRepeat; ++i) {
     TestURLLoaderClient client;
     mojo::PendingRemote<mojom::URLLoader> loader_remote;
 
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        nullptr /* network_context_client */,
-        NeverInvokedDeleteLoaderCallback(),
+        context(), NeverInvokedDeleteLoaderCallback(),
         loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
         client.CreateRemote(), nullptr /* sync_url_loader_client */,
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-        /*coep_reporter=*/nullptr, 0 /* request_id */,
-        0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+        0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3751,16 +3635,12 @@
 
   mojo::PendingRemote<mojom::URLLoader> loader_remote;
   std::unique_ptr<URLLoader> loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */, NeverInvokedDeleteLoaderCallback(),
+      context(), NeverInvokedDeleteLoaderCallback(),
       loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -3788,21 +3668,15 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
       request, client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4073,21 +3947,15 @@
       CreateResourceRequest("GET", test_server()->GetURL(kTestAuthURL));
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_auth_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4123,21 +3991,15 @@
       CreateResourceRequest("GET", test_server()->GetURL(kTestAuthURL));
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_auth_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4173,21 +4035,15 @@
       CreateResourceRequest("GET", test_server()->GetURL(kTestAuthURL));
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_auth_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4224,21 +4080,15 @@
       CreateResourceRequest("GET", test_server()->GetURL(kFaviconTestPage));
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_auth_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4274,21 +4124,15 @@
       CreateResourceRequest("GET", test_server()->GetURL(kTestAuthURL));
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_auth_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4325,22 +4169,16 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = 234;
+  context().mutable_factory_params().process_id = 234;
   // No call to NetworkService::AddAllowedRequestInitiatorForPlugin - this is
   // what we primarily want to cover in this test.
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4367,21 +4205,15 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
       request, client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4475,21 +4307,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_cert_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4532,20 +4358,15 @@
       CreateResourceRequest("GET", test_server.GetURL("/defaultresponse"));
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
       nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
-      &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+      nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_cert_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4579,20 +4400,15 @@
       CreateResourceRequest("GET", test_server.GetURL("/defaultresponse"));
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
       nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
-      &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+      nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_cert_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4625,21 +4441,15 @@
       CreateResourceRequest("GET", test_server.GetURL("/defaultresponse"));
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_cert_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4681,21 +4491,15 @@
       CreateResourceRequest("GET", test_server.GetURL("/defaultresponse"));
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_cert_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4741,21 +4545,15 @@
       CreateResourceRequest("GET", test_server.GetURL("/defaultresponse"));
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_cert_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4803,21 +4601,15 @@
       CreateResourceRequest("GET", test_server.GetURL("/defaultresponse"));
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_cert_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4846,21 +4638,16 @@
   ResourceRequest request = CreateResourceRequest("GET", first_party_url);
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(),
       mojom::kURLLoadOptionBlockAllCookies, request, client()->CreateRemote(),
       nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
-      &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+      nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4878,22 +4665,16 @@
   ResourceRequest request = CreateResourceRequest("GET", first_party_url);
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(),
       mojom::kURLLoadOptionBlockThirdPartyCookies, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4911,21 +4692,15 @@
   ResourceRequest request = CreateResourceRequest("GET", first_party_url);
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
       request, client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -4968,21 +4743,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_cert_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5027,21 +4796,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_cert_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5088,21 +4851,15 @@
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       client_cert_observer.Bind() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5124,23 +4881,17 @@
     MockCookieObserver cookie_observer;
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
         nullptr /* sync_url_loader_client */,
 
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, cookie_observer.GetRemote(),
+        TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+        0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */, cookie_observer.GetRemote(),
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5165,23 +4916,15 @@
     MockCookieObserver cookie_observer;
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, cookie_observer.GetRemote(),
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */, cookie_observer.GetRemote(),
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5206,23 +4949,15 @@
     MockCookieObserver cookie_observer;
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, cookie_observer.GetRemote(),
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */, cookie_observer.GetRemote(),
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5258,21 +4993,15 @@
 
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
       loader_client.CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, cookie_observer.GetRemote(),
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      cookie_observer.GetRemote(),
       mojo::NullRemote() /* url_loader_network_observer */,
       /*devtools_observer=*/mojo::NullRemote(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5309,23 +5038,15 @@
 
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, cookie_observer.GetRemote(),
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */, cookie_observer.GetRemote(),
         client_auth_observer.Bind() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5357,29 +5078,22 @@
     auto cookie = net::CanonicalCookie::Create(
         cookie_url, "a=b", base::Time::Now(), absl::nullopt /* server_time */,
         absl::nullopt /* cookie_partition_key */);
-    context()->cookie_store()->SetCanonicalCookieAsync(
+    url_request_context()->cookie_store()->SetCanonicalCookieAsync(
         std::move(cookie), cookie_url, net::CookieOptions::MakeAllInclusive(),
         base::DoNothing());
 
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         devtools_observer.Bind(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5414,29 +5128,22 @@
         cookie_url, "a=b;Path=/something-else", base::Time::Now(),
         absl::nullopt /* server_time */,
         absl::nullopt /* cookie_partition_key */);
-    context()->cookie_store()->SetCanonicalCookieAsync(
+    url_request_context()->cookie_store()->SetCanonicalCookieAsync(
         std::move(cookie), cookie_url, net::CookieOptions::MakeAllInclusive(),
         base::DoNothing());
 
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         devtools_observer.Bind(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5468,23 +5175,16 @@
 
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         devtools_observer.Bind(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5519,23 +5219,16 @@
 
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         devtools_observer.Bind(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5572,23 +5265,16 @@
 
     base::RunLoop delete_run_loop;
     mojo::Remote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
         loader_client.CreateRemote(), nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-        /*coep_reporter=*/nullptr, 0 /* request_id */,
-        0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+        0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         devtools_observer.Bind(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5631,23 +5317,16 @@
 
     base::RunLoop delete_run_loop;
     mojo::Remote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
         loader_client.CreateRemote(), nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-        /*coep_reporter=*/nullptr, 0 /* request_id */,
-        0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+        0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         devtools_observer.Bind(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5685,23 +5364,16 @@
 
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         devtools_observer.Bind(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5738,23 +5410,16 @@
 
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         devtools_observer.Bind(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5786,23 +5451,16 @@
 
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
+        mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         devtools_observer.Bind(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5845,22 +5503,15 @@
 
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /*network_context_client=*/nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
       request, loader_client.CreateRemote(),
-      nullptr /* sync_url_loader_client */,
-
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-      /*request_id=*/0, /*keepalive_request_size=*/0,
-      /*require_network_isolation_key=*/false, resource_scheduler_client(),
-      nullptr, /*header_client=*/nullptr, /* origin_policy_manager=*/nullptr,
-      /*trust_token_helper=*/nullptr, kEmptyOriginAccessList,
+      nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+      /*request_id=*/0, /*keepalive_request_size=*/0, nullptr,
+      /*trust_token_helper=*/nullptr,
       /*cookie_observer=*/mojo::NullRemote(),
       /*url_loader_network_observer=*/mojo::NullRemote(),
       /*devtools_observer=*/mojo::NullRemote(),
@@ -5903,23 +5554,15 @@
 
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, cookie_observer.GetRemote(),
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */, cookie_observer.GetRemote(),
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -5961,23 +5604,15 @@
 
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, cookie_observer.GetRemote(),
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */, cookie_observer.GetRemote(),
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -6011,23 +5646,15 @@
 
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
-    mojom::URLLoaderFactoryParams params;
-    params.process_id = kProcessId;
-    params.is_corb_enabled = false;
+    context().mutable_factory_params().process_id = kProcessId;
+    context().mutable_factory_params().is_corb_enabled = false;
     std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        /*network_context_client=*/nullptr,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
         request, loader_client.CreateRemote(),
-        nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
-        0 /* request_id */, 0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */,
-        nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-        kEmptyOriginAccessList, cookie_observer.GetRemote(),
+        nullptr /* sync_url_loader_client */, TRAFFIC_ANNOTATION_FOR_TESTS,
+        0 /* request_id */, 0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */, cookie_observer.GetRemote(),
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
         /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -6095,6 +5722,7 @@
   // response.
   {
     MockOriginPolicyManager mock_origin_policy_manager;
+    context().set_origin_policy_manager(&mock_origin_policy_manager);
     ResourceRequest request =
         CreateResourceRequest("GET", server.GetURL("/with_policy"));
     // This is what the IsolationInfo for a main frame will normally look like.
@@ -6110,23 +5738,16 @@
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
     std::unique_ptr<URLLoader> url_loader;
-    mojom::URLLoaderFactoryParams params;
     TestURLLoaderClient loader_client;
-    params.process_id = mojom::kBrowserProcessId;
+    context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
 
     url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        nullptr /* network_context_client */,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), 0, request,
         loader_client.CreateRemote(), nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-        /*coep_reporter=*/nullptr, 0 /* request_id */,
-        0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */, &mock_origin_policy_manager,
-        nullptr /* trust_token_helper */, kEmptyOriginAccessList,
+        TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+        0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
         mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
@@ -6161,6 +5782,7 @@
   // call the origin policy manager with an empty header value.
   {
     MockOriginPolicyManager mock_origin_policy_manager;
+    context().set_origin_policy_manager(&mock_origin_policy_manager);
     ResourceRequest request =
         CreateResourceRequest("GET", server.GetURL("/without_policy"));
     request.obey_origin_policy = true;
@@ -6168,23 +5790,16 @@
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
     std::unique_ptr<URLLoader> url_loader;
-    mojom::URLLoaderFactoryParams params;
     TestURLLoaderClient loader_client;
-    params.process_id = mojom::kBrowserProcessId;
+    context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
 
     url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        nullptr /* network_context_client */,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), 0, request,
         loader_client.CreateRemote(), nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-        /*coep_reporter=*/nullptr, 0 /* request_id */,
-        0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */, &mock_origin_policy_manager,
-        nullptr /* trust_token_helper */, kEmptyOriginAccessList,
+        TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+        0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
         mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
@@ -6206,6 +5821,7 @@
   // regardless of the presence of the "Sec-Origin-Policy" header.
   {
     MockOriginPolicyManager mock_origin_policy_manager;
+    context().set_origin_policy_manager(&mock_origin_policy_manager);
     ResourceRequest request =
         CreateResourceRequest("GET", server.GetURL("/with_policy"));
     request.obey_origin_policy = false;
@@ -6213,23 +5829,16 @@
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
     std::unique_ptr<URLLoader> url_loader;
-    mojom::URLLoaderFactoryParams params;
     TestURLLoaderClient loader_client;
-    params.process_id = mojom::kBrowserProcessId;
+    context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
 
     url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        nullptr /* network_context_client */,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), 0, request,
         loader_client.CreateRemote(), nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-        /*coep_reporter=*/nullptr, 0 /* request_id */,
-        0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */, &mock_origin_policy_manager,
-        nullptr /* trust_token_helper */, kEmptyOriginAccessList,
+        TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+        0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
         mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
@@ -6250,6 +5859,7 @@
         url::Origin::Create(GURL("http://top-frame.test/"));
 
     MockOriginPolicyManager mock_origin_policy_manager;
+    context().set_origin_policy_manager(&mock_origin_policy_manager);
     ResourceRequest request =
         CreateResourceRequest("GET", server.GetURL("/with_policy"));
     // IsolationInfo used for the ResourceRequest. This is what the
@@ -6264,23 +5874,16 @@
     base::RunLoop delete_run_loop;
     mojo::PendingRemote<mojom::URLLoader> loader;
     std::unique_ptr<URLLoader> url_loader;
-    mojom::URLLoaderFactoryParams params;
     TestURLLoaderClient loader_client;
-    params.process_id = mojom::kBrowserProcessId;
+    context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
 
     url_loader = std::make_unique<URLLoader>(
-        context(), /*url_loader_factory=*/nullptr,
-        nullptr /* network_context_client */,
-        DeleteLoaderCallback(&delete_run_loop, &url_loader),
+        context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
         loader.InitWithNewPipeAndPassReceiver(), 0, request,
         loader_client.CreateRemote(), nullptr /* sync_url_loader_client */,
-
-        TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-        /*coep_reporter=*/nullptr, 0 /* request_id */,
-        0 /* keepalive_request_size */,
-        false /* require_network_isolation_key */, resource_scheduler_client(),
-        nullptr, nullptr /* header_client */, &mock_origin_policy_manager,
-        nullptr /* trust_token_helper */, kEmptyOriginAccessList,
+        TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+        0 /* keepalive_request_size */, nullptr,
+        nullptr /* trust_token_helper */,
         mojo::NullRemote() /* cookie_observer */,
         mojo::NullRemote() /* url_loader_network_observer */,
         /*devtools_observer=*/mojo::NullRemote(),
@@ -6562,26 +6165,20 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader_remote;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
   MockTrustTokenDevToolsObserver devtools_observer;
 
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr,
       std::make_unique<MockTrustTokenRequestHelperFactory>(
           mojom::TrustTokenOperationStatus::kOk /* on_begin */,
           mojom::TrustTokenOperationStatus::kOk /* on_finalize */, GetParam(),
           &outbound_trust_token_operation_was_successful_),
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       devtools_observer.Bind(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -6622,26 +6219,20 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader_remote;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
   MockTrustTokenDevToolsObserver devtools_observer;
 
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr,
       std::make_unique<MockTrustTokenRequestHelperFactory>(
           mojom::TrustTokenOperationStatus::kAlreadyExists /* on_begin */,
           absl::nullopt /* on_finalize */, GetParam(),
           &outbound_trust_token_operation_was_successful_),
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       devtools_observer.Bind(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -6670,26 +6261,20 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader_remote;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
   MockTrustTokenDevToolsObserver devtools_observer;
 
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr,
       std::make_unique<MockTrustTokenRequestHelperFactory>(
           mojom::TrustTokenOperationStatus::kFailedPrecondition /* on_begin */,
           absl::nullopt /* on_finalize */, GetParam(),
           &outbound_trust_token_operation_was_successful_),
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       devtools_observer.Bind(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -6718,26 +6303,20 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader_remote;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
   MockTrustTokenDevToolsObserver devtools_observer;
 
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr,
       std::make_unique<MockTrustTokenRequestHelperFactory>(
           mojom::TrustTokenOperationStatus::kOk /* on_begin */,
           mojom::TrustTokenOperationStatus::kBadResponse /* on_finalize */,
           GetParam(), &outbound_trust_token_operation_was_successful_),
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       devtools_observer.Bind(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -6766,26 +6345,20 @@
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader_remote;
   std::unique_ptr<URLLoader> url_loader;
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = mojom::kBrowserProcessId;
+  context().mutable_factory_params().process_id = mojom::kBrowserProcessId;
   MockTrustTokenDevToolsObserver devtools_observer;
 
   url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      nullptr /* network_context_client */,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr,
       std::make_unique<MockTrustTokenRequestHelperFactory>(
           mojom::TrustTokenOperationStatus::
               kInternalError /* helper_creation_error */,
           GetParam()),
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       devtools_observer.Bind(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -6813,25 +6386,20 @@
   client_security_state->private_network_request_policy =
       mojom::PrivateNetworkRequestPolicy::kAllow;
   client_security_state->ip_address_space = mojom::IPAddressSpace::kPublic;
-  mojom::URLLoaderFactoryParams params;
-  params.client_security_state = std::move(client_security_state);
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().client_security_state =
+      std::move(client_security_state);
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
 
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /* network_context_client */ nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       devtools_observer.Bind(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -6864,24 +6432,18 @@
   request.trusted_params->client_security_state =
       std::move(client_security_state);
 
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
 
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /* network_context_client */ nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       devtools_observer.Bind(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -6906,24 +6468,18 @@
       CreateResourceRequest("GET", test_server()->GetURL("/simple_page.html"));
   request.devtools_request_id = "fake-id";
 
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
 
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /* network_context_client */ nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList, mojo::NullRemote() /* cookie_observer */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
+      mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       devtools_observer.Bind(),
       /*accept_ch_frame_observer=*/mojo::NullRemote());
@@ -6941,24 +6497,17 @@
       CreateResourceRequest("GET", test_server()->GetURL("/simple_page.html"));
   request.devtools_request_id = "fake-id";
 
-  mojom::URLLoaderFactoryParams params;
-  params.process_id = kProcessId;
-  params.is_corb_enabled = false;
+  context().mutable_factory_params().process_id = kProcessId;
+  context().mutable_factory_params().is_corb_enabled = false;
 
   base::RunLoop delete_run_loop;
   mojo::PendingRemote<mojom::URLLoader> loader;
   std::unique_ptr<URLLoader> url_loader = std::make_unique<URLLoader>(
-      context(), /*url_loader_factory=*/nullptr,
-      /* network_context_client */ nullptr,
-      DeleteLoaderCallback(&delete_run_loop, &url_loader),
+      context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
       loader.InitWithNewPipeAndPassReceiver(), 0, request,
       client()->CreateRemote(), nullptr /* sync_url_loader_client */,
-      TRAFFIC_ANNOTATION_FOR_TESTS, &params,
-      /*coep_reporter=*/nullptr, 0 /* request_id */,
-      0 /* keepalive_request_size */, false /* require_network_isolation_key */,
-      resource_scheduler_client(), nullptr, nullptr /* header_client */,
-      nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
-      kEmptyOriginAccessList /* origin_access_list */,
+      TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* request_id */,
+      0 /* keepalive_request_size */, nullptr, nullptr /* trust_token_helper */,
       mojo::NullRemote() /* cookie_observer */,
       mojo::NullRemote() /* url_loader_network_observer */,
       devtools_observer.Bind(),
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 68f94ab..f635815 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -1781,7 +1781,8 @@
         "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android31.textpb"
+          "--avd-config=../../tools/android/avd/proto/generic_android31.textpb",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_12.content_shell_test_apk.filter"
         ],
         "merge": {
           "args": [
@@ -5702,7 +5703,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M99",
-              "revision": "version:99.0.4844.14"
+              "revision": "version:99.0.4844.22"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -5966,7 +5967,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M99",
-              "revision": "version:99.0.4844.14"
+              "revision": "version:99.0.4844.22"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index f0962df..827be02 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -43369,7 +43369,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M99",
-              "revision": "version:99.0.4844.14"
+              "revision": "version:99.0.4844.22"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -43633,7 +43633,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M99",
-              "revision": "version:99.0.4844.14"
+              "revision": "version:99.0.4844.22"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -43972,7 +43972,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M99",
-              "revision": "version:99.0.4844.14"
+              "revision": "version:99.0.4844.22"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -44236,7 +44236,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M99",
-              "revision": "version:99.0.4844.14"
+              "revision": "version:99.0.4844.22"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -44575,7 +44575,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M99",
-              "revision": "version:99.0.4844.14"
+              "revision": "version:99.0.4844.22"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -44839,7 +44839,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M99",
-              "revision": "version:99.0.4844.14"
+              "revision": "version:99.0.4844.22"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index 2a13eae9..9f26ad2b 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -770,9 +770,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -810,9 +810,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -857,9 +857,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -904,9 +904,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -960,9 +960,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -1004,9 +1004,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -1048,9 +1048,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -1096,9 +1096,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -1149,9 +1149,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -1202,9 +1202,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -1247,9 +1247,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -1291,9 +1291,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
@@ -1336,9 +1336,9 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
+              "device_os": "P",
+              "device_os_type": "userdebug",
+              "device_type": "mdarcy",
               "os": "Android",
               "pool": "chromium.tests.gpu"
             }
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index ad4d4106..8f63bc18 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -141,6 +141,7 @@
 
   data = [
     "//testing/buildbot/filters/android.emulator_11.content_shell_test_apk.filter",
+    "//testing/buildbot/filters/android.emulator_12.content_shell_test_apk.filter",
     "//testing/buildbot/filters/android.emulator_m.content_shell_test_apk.filter",
   ]
 }
diff --git a/testing/buildbot/filters/android.emulator_12.content_shell_test_apk.filter b/testing/buildbot/filters/android.emulator_12.content_shell_test_apk.filter
new file mode 100644
index 0000000..4f1a866
--- /dev/null
+++ b/testing/buildbot/filters/android.emulator_12.content_shell_test_apk.filter
@@ -0,0 +1,23 @@
+# crbug.com/1189746
+-org.chromium.net.NetworkChangeNotifierTest.testNetworkChangeNotifierJavaObservers
+-org.chromium.net.NetworkChangeNotifierTest.testVpnAccessibleDoesNotLeak
+
+# crbug.com/1189804
+-org.chromium.content.browser.input.ImeInputModeTest.testShowAndHideInputMode
+-org.chromium.content.browser.input.ImeInputModeTest.testShowAndHideInputModeWithPhysicalKeyboard
+
+# crbug.com/1220151
+-org.chromium.base.task.AsyncTaskTest.testChromeThreadPoolExecutorOsAsyncTask
+
+# crbug.com/1233312
+-org.chromium.content.browser.font.AndroidFontLookupImplTest.testFetchAllFontFiles_Available
+-org.chromium.content.browser.font.AndroidFontLookupImplTest.testFetchAllFontFiles_OneNotAvailable
+-org.chromium.content.browser.font.AndroidFontLookupImplTest.testMatchLocalFontByUniqueName_Success
+
+# crbug.com/1294427
+-org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_copy
+-org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_cut
+-org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_paste
+-org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBar*Copy
+-org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBar*Cut
+-org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBar*Paste
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 3499bcdc..5c92526 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -415,16 +415,6 @@
       },
     },
   },
-  'foster': {
-    # NVIDIA SHIELD TV
-    'swarming': {
-      'dimensions': {
-        'device_os_type': 'user',
-        'device_type': 'foster',
-        'os': 'Android',
-      },
-    },
-  },
   'fuchsia-code-coverage': {
     '$mixin_append': {
       'args': [
@@ -904,6 +894,15 @@
       },
     },
   },
+  'mdarcy': {
+    # NVIDIA Shield TV 2019
+    'swarming': {
+      'dimensions': {
+        'device_type': 'mdarcy',
+        'os': 'Android',
+      },
+    },
+  },
   'no_gpu': {
     'swarming': {
       'dimensions': {
@@ -1005,6 +1004,13 @@
       },
     },
   },
+  'pie_generic': {
+    'swarming': {
+      'dimensions': {
+        'device_os': 'P',
+      },
+    },
+  },
   'skia_gold_test': {
     '$mixin_append': {
       'args': [
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 7b58f71..4f00dd0 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1447,6 +1447,11 @@
           '--timeout-scale=2.0',
         ],
       },
+      'android-12-x64-fyi-rel': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_12.content_shell_test_apk.filter',
+        ],
+      },
       'android-marshmallow-x86-rel': {
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_m.content_shell_test_apk.filter',
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 93f03c5..805e724 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -624,12 +624,12 @@
           'bullhead',
           'flame',
           'flounder',
-          'foster',
           'hammerhead',
           'kitkat',
           'lollipop',
           'marshmallow',
           'marshmallow_generic',
+          'mdarcy',
           'nougat_generic',
           'oreo_fleet',
           'pie_fleet',
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 9a276e4..59456cf 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -435,7 +435,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M99',
-          'revision': 'version:99.0.4844.14',
+          'revision': 'version:99.0.4844.22',
         }
       ],
     },
@@ -507,7 +507,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M99',
-          'revision': 'version:99.0.4844.14',
+          'revision': 'version:99.0.4844.22',
         }
       ],
     },
@@ -579,7 +579,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M99',
-          'revision': 'version:99.0.4844.14',
+          'revision': 'version:99.0.4844.22',
         }
       ],
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 5757172..1a6d591 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -4009,9 +4009,9 @@
         'skip_merge_script': True,
         'mixins': [
           'has_native_resultdb_integration',
-          'foster',
+          'mdarcy',
           'gpu-swarming-pool',
-          'nougat_generic',
+          'pie_generic',
         ],
         'test_suites': {
           'gtest_tests': 'gpu_fyi_android_shieldtv_gtests',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 3f641fa7..64fc65f 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3686,27 +3686,6 @@
             ]
         }
     ],
-    "IncludeIpcOverheadInNavigationStart": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "IncludeIpcOverheadInNavigationStart"
-                    ]
-                }
-            ]
-        }
-    ],
     "KeyboardAccessoryAddressIPH": [
         {
             "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 3ed1f0a4..12c951f 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -208,6 +208,32 @@
 const base::FeatureParam<int>
     kSharedStorageURLSelectionOperationInputURLSizeLimit{
         &kSharedStorageAPI, "url_selection_operation_input_url_size_limit", 5};
+const base::FeatureParam<int> kMaxSharedStorageStringLength = {
+    &kSharedStorageAPI, "MaxSharedStorageStringLength", 1024};
+const base::FeatureParam<int> kMaxSharedStorageEntriesPerOrigin = {
+    &kSharedStorageAPI, "MaxSharedStorageEntriesPerOrigin", 10000};
+const base::FeatureParam<int> kMaxSharedStoragePageSize = {
+    &kSharedStorageAPI, "MaxSharedStoragePageSize", 4096};
+const base::FeatureParam<int> kMaxSharedStorageCacheSize = {
+    &kSharedStorageAPI, "MaxSharedStorageCacheSize", 1024};
+const base::FeatureParam<int> kMaxSharedStorageInitTries = {
+    &kSharedStorageAPI, "MaxSharedStorageInitTries", 2};
+const base::FeatureParam<int>
+    kMaxSharedStorageConsecutiveOperationErrorsAllowed = {
+        &kSharedStorageAPI, "MaxSharedStorageConsecutiveOperationErrorsAllowed",
+        8};
+const base::FeatureParam<base::TimeDelta>
+    kSharedStorageStaleOriginPurgeInitialInterval = {
+        &kSharedStorageAPI, "SharedStorageStaleOriginPurgeInitialInterval",
+        base::Minutes(15)};
+const base::FeatureParam<base::TimeDelta>
+    kSharedStorageStaleOriginPurgeRecurringInterval = {
+        &kSharedStorageAPI, "SharedStorageStaleOriginPurgeRecurringInterval",
+        base::Hours(2)};
+const base::FeatureParam<base::TimeDelta>
+    kSharedStorageOriginStalenessThreshold = {
+        &kSharedStorageAPI, "SharedStorageOriginStalenessThreshold",
+        base::Days(60)};
 
 // Enables the Prerender2 feature: https://crbug.com/1126305
 // Note that default enabling this does not enable the Prerender2 features
@@ -890,16 +916,6 @@
     "SendCnameAliasesToSubresourceFilterFromRenderer",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Kill switch for the InterestCohort API origin trial, i.e. if disabled, the
-// API exposure will be disabled regardless of the OT config.
-// (See https://github.com/WICG/floc.)
-const base::Feature kInterestCohortAPIOriginTrial{
-    "InterestCohortAPIOriginTrial", base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Enable the availability of the "interest-cohort" permissions policy.
-const base::Feature kInterestCohortFeaturePolicy{
-    "InterestCohortFeaturePolicy", base::FEATURE_DISABLED_BY_DEFAULT};
-
 const base::Feature kDisableDocumentDomainByDefault{
     "DisableDocumentDomainByDefault", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/third_party/blink/common/navigation/navigation_params.cc b/third_party/blink/common/navigation/navigation_params.cc
index 2ef8781..48e121d0 100644
--- a/third_party/blink/common/navigation/navigation_params.cc
+++ b/third_party/blink/common/navigation/navigation_params.cc
@@ -21,6 +21,7 @@
   auto commit_params = mojom::CommitNavigationParams::New();
   commit_params->navigation_token = base::UnguessableToken::Create();
   commit_params->navigation_timing = mojom::NavigationTiming::New();
+  commit_params->app_history_entry_arrays = mojom::AppHistoryEntryArrays::New();
 
   return commit_params;
 }
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 3a7e08e..158c0d9c 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -70,8 +70,48 @@
     kFencedFramesImplementationTypeParam;
 
 BLINK_COMMON_EXPORT extern const base::Feature kSharedStorageAPI;
+// Maximum number of URLs allowed to be included in the input parameter for
+// runURLSelectionOperation().
 BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
     kSharedStorageURLSelectionOperationInputURLSizeLimit;
+// Maximum length of Shared Storage script key and script value.
+BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
+    kMaxSharedStorageStringLength;
+// Maximum number of database entries at a time that any single origin is
+// permitted.
+BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
+    kMaxSharedStorageEntriesPerOrigin;
+// Maximum database page size in bytes. Must be a power of two between
+// 512 and 65536, inclusive.
+BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
+    kMaxSharedStoragePageSize;
+// Maximum database in-memory cache size, in pages.
+BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
+    kMaxSharedStorageCacheSize;
+// Maximum number of tries to initialize the database.
+BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
+    kMaxSharedStorageInitTries;
+// Maximum number of consecutive database errors allowed before the database is
+// razed. Consecutive errors are tallied, and if the next database operation
+// returns successfully, the consecutive error count is reset back to zero. If
+// the consecutive error count exceeds the threshold, then the database is
+// destroyed and recreated.
+BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
+    kMaxSharedStorageConsecutiveOperationErrorsAllowed;
+// The length of the initial interval from service startup after which
+// SharedStorageManager first checks for any stale origins, purging any that it
+// finds.
+BLINK_COMMON_EXPORT extern const base::FeatureParam<base::TimeDelta>
+    kSharedStorageStaleOriginPurgeInitialInterval;
+// The length of the second and subsequent intervals from service startup after
+// which SharedStorageManager checks for any stale origins, purging any that it
+// finds.
+BLINK_COMMON_EXPORT extern const base::FeatureParam<base::TimeDelta>
+    kSharedStorageStaleOriginPurgeRecurringInterval;
+// The length of time that an origin must be inactive for it to be deemed stale
+// and hence necessary to auto-purge.
+BLINK_COMMON_EXPORT extern const base::FeatureParam<base::TimeDelta>
+    kSharedStorageOriginStalenessThreshold;
 
 // Prerender2:
 // Enables the Prerender2 feature: https://crbug.com/1126305
@@ -359,10 +399,6 @@
 BLINK_COMMON_EXPORT extern const base::Feature
     kSendCnameAliasesToSubresourceFilterFromRenderer;
 
-BLINK_COMMON_EXPORT extern const base::Feature kInterestCohortAPIOriginTrial;
-
-BLINK_COMMON_EXPORT extern const base::Feature kInterestCohortFeaturePolicy;
-
 BLINK_COMMON_EXPORT extern const base::Feature kDisableDocumentDomainByDefault;
 
 BLINK_COMMON_EXPORT extern const base::Feature kScopeMemoryCachePerContext;
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index 67641c1..02beb676 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -6914,7 +6914,6 @@
       gyroscope
       hid
       idle-detection
-      interest-cohort
       join-ad-interest-group
       keyboard-map
       magnetometer
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 1e9892b..83b1faa 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -65,7 +65,6 @@
     "drag/drag.mojom",
     "favicon/favicon_url.mojom",
     "feature_observer/feature_observer.mojom",
-    "federated_learning/floc.mojom",
     "fenced_frame/fenced_frame.mojom",
     "fetch/fetch_api_request.mojom",
     "fetch/fetch_api_response.mojom",
@@ -131,6 +130,7 @@
     "mediastream/media_stream.mojom",
     "mime/mime_registry.mojom",
     "native_io/native_io.mojom",
+    "navigation/app_history_entry_arrays.mojom",
     "navigation/navigation_policy.mojom",
     "navigation/prefetched_signed_exchange_info.mojom",
     "navigation/renderer_eviction_reason.mojom",
diff --git a/third_party/blink/public/mojom/federated_learning/OWNERS b/third_party/blink/public/mojom/federated_learning/OWNERS
deleted file mode 100644
index 08850f4..0000000
--- a/third_party/blink/public/mojom/federated_learning/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/federated_learning/floc.mojom b/third_party/blink/public/mojom/federated_learning/floc.mojom
deleted file mode 100644
index 794ffa6..0000000
--- a/third_party/blink/public/mojom/federated_learning/floc.mojom
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module blink.mojom;
-
-struct InterestCohort {
-  // The string representation of the interest cohort integer value in decimal.
-  // If empty, it means the access permission is denied, or the algorithm is
-  // unavailable, or the cohort is unassigned or invalidated.
-  string id;
-
-  // The version that identifies the algorithm used to compute the interest
-  // cohort |id|. If empty, it means the access permission is denied, or the
-  // algorithm is unavailable, or the cohort is unassigned or invalidated.
-  // TODO(yaoxia): when it's just that the cohort is unassigned or invalidated,
-  // while all other conditions are met, we still want to expose the version.
-  string version;
-};
-
-// The Floc service provides a method to request the interest cohort. It is
-// a per-frame interface hosted in the browser process.
-// https://github.com/jkarlin/floc
-interface FlocService {
-
-  // Asynchronously get the interest cohort. See the comments in the
-  // InterestCohort mojom struct for more details.
-  GetInterestCohort() => (InterestCohort interest_cohort);
-};
diff --git a/third_party/blink/public/mojom/navigation/app_history_entry_arrays.mojom b/third_party/blink/public/mojom/navigation/app_history_entry_arrays.mojom
new file mode 100644
index 0000000..b3ae9b3
--- /dev/null
+++ b/third_party/blink/public/mojom/navigation/app_history_entry_arrays.mojom
@@ -0,0 +1,29 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+import "mojo/public/mojom/base/string16.mojom";
+
+// AppHistoryEntry contains a subset of a session history item that is used by
+// the appHistory API to represent a non-current history entry. The browser
+// ensures that an AppHistoryEntry is only sent to the renderer if its |url| is
+// same-origin to the navigation being committed.
+struct AppHistoryEntry {
+  mojo_base.mojom.String16 key;
+  mojo_base.mojom.String16 id;
+  // |url| is represented as a string rather than a url.mojom.Url in keeping
+  // with the FrameState mojo struct doing so (from which |url| is derived).
+  mojo_base.mojom.String16 url;
+  int64 item_sequence_number;
+  int64 document_sequence_number;
+  mojo_base.mojom.String16 state;
+};
+
+// A same-origin subset of the back/forward list exposed by the appHistory
+// API.
+struct AppHistoryEntryArrays {
+  array<AppHistoryEntry> back_entries;
+  array<AppHistoryEntry> forward_entries;
+};
diff --git a/third_party/blink/public/mojom/navigation/navigation_params.mojom b/third_party/blink/public/mojom/navigation/navigation_params.mojom
index 918df74a..24a3498 100644
--- a/third_party/blink/public/mojom/navigation/navigation_params.mojom
+++ b/third_party/blink/public/mojom/navigation/navigation_params.mojom
@@ -21,6 +21,7 @@
 import "third_party/blink/public/mojom/frame/frame_policy.mojom";
 import "third_party/blink/public/mojom/loader/mixed_content.mojom";
 import "third_party/blink/public/mojom/loader/referrer.mojom";
+import "third_party/blink/public/mojom/navigation/app_history_entry_arrays.mojom";
 import "third_party/blink/public/mojom/navigation/navigation_policy.mojom";
 import "third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom";
 import "third_party/blink/public/mojom/navigation/was_activated_option.mojom";
@@ -262,19 +263,6 @@
   blink.mojom.PageLifecycleState new_lifecycle_state_for_old_page;
 };
 
-// AppHistoryEntry contains a subset of a session history item that is used by
-// the appHistory API to represent a non-current history entry. The browser
-// ensures that an AppHistoryEntry is only sent to the renderer if its |url| is
-// same-origin to the navigation being committed.
-struct AppHistoryEntry {
-  mojo_base.mojom.String16 key;
-  mojo_base.mojom.String16 id;
-  mojo_base.mojom.String16 url;
-  int64 item_sequence_number;
-  int64 document_sequence_number;
-  mojo_base.mojom.String16 state;
-};
-
 // Used by commit IPC messages. Holds the parameters needed by the renderer to
 // commit a navigation besides those in CommonNavigationParams.
 struct CommitNavigationParams {
@@ -467,8 +455,7 @@
 
   // A same-origin subset of the back/forward list exposed by the appHistory
   // API.
-  array<AppHistoryEntry> app_history_back_entries;
-  array<AppHistoryEntry> app_history_forward_entries;
+  AppHistoryEntryArrays app_history_entry_arrays;
 
   array<url.mojom.Url> early_hints_preloaded_resources;
 
diff --git a/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom b/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom
index 3ad6080..cf48d85 100644
--- a/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom
+++ b/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom
@@ -125,10 +125,8 @@
   // Controls access to screen capture via getDisplayMedia().
   kDisplayCapture = 81,
 
-  // Controls the access to the interest cohort as well as the eligibility for
-  // the navigation history entry to be included in the interest cohort
-  // computation. (https://github.com/WICG/floc)
-  kInterestCohort = 82,
+  // [Deprecated]
+  // kInterestCohort = 82,
 
   // Controls whether Autofill may fill fields in that frame when triggered on
   // a field with the main frame's origin.
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index b99f91b..393aa9f 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2988,7 +2988,7 @@
   kXRFrameGetDepthInformation = 3684,
   kXRCPUDepthInformationGetDepth = 3685,
   kXRCPUDepthInformationDataAttribute = 3686,
-  kInterestCohortAPI_interestCohort_Method = 3687,
+  kOBSOLETE_InterestCohortAPI_interestCohort_Method = 3687,
   kOBSOLETE_AddressSpaceLocalEmbeddedInPrivateSecureContext = 3688,
   kOBSOLETE_AddressSpaceLocalEmbeddedInPrivateNonSecureContext = 3689,
   kOBSOLETE_AddressSpaceLocalEmbeddedInPublicSecureContext = 3690,
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni
index 6418026..b9dd64f 100644
--- a/third_party/blink/renderer/bindings/generated_in_core.gni
+++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -203,8 +203,6 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_input_device_capabilities_init.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_input_event_init.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_input_event_init.h",
-  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_interest_cohort.cc",
-  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_interest_cohort.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_init.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_init.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_intrinsic_sizes_result_options.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni
index 208e4aa3..921f0c2 100644
--- a/third_party/blink/renderer/bindings/idl_in_core.gni
+++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -170,7 +170,6 @@
           "//third_party/blink/renderer/core/dom/idle_deadline.idl",
           "//third_party/blink/renderer/core/dom/idle_request_callback.idl",
           "//third_party/blink/renderer/core/dom/idle_request_options.idl",
-          "//third_party/blink/renderer/core/dom/interest_cohort.idl",
           "//third_party/blink/renderer/core/dom/iterator.idl",
           "//third_party/blink/renderer/core/dom/mutation_observer.idl",
           "//third_party/blink/renderer/core/dom/mutation_observer_init.idl",
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index d7c3ca4a..bdfc91c2 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -78,7 +78,6 @@
 #include "third_party/blink/renderer/bindings/core/v8/source_location.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_element_creation_options.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_element_registration_options.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_interest_cohort.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_observable_array_css_style_sheet.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_elementcreationoptions_string.h"
@@ -6007,68 +6006,6 @@
   return promise;
 }
 
-mojom::blink::FlocService* Document::GetFlocService(
-    ExecutionContext* execution_context) {
-  if (!data_->floc_service_.is_bound()) {
-    execution_context->GetBrowserInterfaceBroker().GetInterface(
-        data_->floc_service_.BindNewPipeAndPassReceiver(
-            execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
-  }
-  return data_->floc_service_.get();
-}
-
-ScriptPromise Document::interestCohort(ScriptState* script_state,
-                                       ExceptionState& exception_state) {
-  if (!GetFrame()) {
-    exception_state.ThrowDOMException(
-        DOMExceptionCode::kInvalidAccessError,
-        "A browsing context is required when calling document.interestCohort.");
-    return ScriptPromise();
-  }
-
-  if (!GetExecutionContext()->IsFeatureEnabled(
-          mojom::blink::PermissionsPolicyFeature::kInterestCohort)) {
-    exception_state.ThrowDOMException(
-        DOMExceptionCode::kInvalidAccessError,
-        "The \"interest-cohort\" Permissions Policy denied the use of "
-        "document.interestCohort.");
-    return ScriptPromise();
-  }
-
-  ScriptPromiseResolver* resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(script_state);
-
-  ScriptPromise promise = resolver->Promise();
-
-  GetFlocService(ExecutionContext::From(script_state))
-      ->GetInterestCohort(WTF::Bind(
-          [](ScriptPromiseResolver* resolver, Document* document,
-             mojom::blink::InterestCohortPtr interest_cohort) {
-            DCHECK(resolver);
-            DCHECK(document);
-
-            if (interest_cohort->version.IsEmpty()) {
-              ScriptState* state = resolver->GetScriptState();
-              ScriptState::Scope scope(state);
-
-              resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
-                  state->GetIsolate(), DOMExceptionCode::kDataError,
-                  "Failed to get the interest cohort: either it is "
-                  "unavailable, or preferences or content settings have "
-                  "denied access."));
-            } else {
-              InterestCohort* result = InterestCohort::Create();
-              result->setId(interest_cohort->id);
-              result->setVersion(interest_cohort->version);
-
-              resolver->Resolve(result);
-            }
-          },
-          WrapPersistent(resolver), WrapPersistent(this)));
-
-  return promise;
-}
-
 void Document::HasTrustTokensAnswererConnectionError() {
   data_->has_trust_tokens_answerer_.reset();
   for (const auto& resolver : data_->pending_has_trust_tokens_resolvers_) {
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index 1d58655d..ce32dcd 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -45,7 +45,6 @@
 #include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/metrics/document_update_reason.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/frame/color_scheme.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/permissions/permission.mojom-blink-forward.h"
@@ -1129,17 +1128,6 @@
                               const String& issuer,
                               ExceptionState&);
 
-  // Floc service helper methods to facilitate querying the floc (i.e.
-  // interestCohort).
-  mojom::blink::FlocService* GetFlocService(
-      ExecutionContext* execution_context);
-
-  // Sends a query via Mojo to ask for the interest cohort. This can reject on
-  // permissions errors (e.g. preferences, content settings, permissions policy,
-  // etc.) or when the interest cohort is unavailable.
-  // https://github.com/jkarlin/floc
-  ScriptPromise interestCohort(ScriptState* script_state, ExceptionState&);
-
   // The following implements the rule from HTML 4 for what valid names are.
   // To get this right for all the XML cases, we probably have to improve this
   // or move it and make it sensitive to the type of document.
diff --git a/third_party/blink/renderer/core/dom/document.idl b/third_party/blink/renderer/core/dom/document.idl
index 087efff..a2411dd 100644
--- a/third_party/blink/renderer/core/dom/document.idl
+++ b/third_party/blink/renderer/core/dom/document.idl
@@ -191,10 +191,6 @@
     [CallWith=ScriptState, NewObject, RuntimeEnabled=StorageAccessAPI, MeasureAs=StorageAccessAPI_HasStorageAccess_Method] Promise<boolean> hasStorageAccess();
     [CallWith=ScriptState, NewObject, RuntimeEnabled=StorageAccessAPI, MeasureAs=StorageAccessAPI_requestStorageAccess_Method] Promise<void> requestStorageAccess();
 
-    // Interest Cohort API
-    // TODO(yaoxia): Add web tests. http://crbug/1130074.
-    [CallWith=ScriptState, RaisesException, NewObject, SecureContext, RuntimeEnabled=InterestCohortAPI, MeasureAs=InterestCohortAPI_interestCohort_Method] Promise<InterestCohort> interestCohort();
-
     // Text fragment directive API
     // https://wicg.github.io/scroll-to-text-fragment/#feature-detectability
     [SameObject, Measure, RuntimeEnabled=TextFragmentIdentifiers] readonly attribute FragmentDirective fragmentDirective;
diff --git a/third_party/blink/renderer/core/dom/document_data.h b/third_party/blink/renderer/core/dom/document_data.h
index 40d00499..bf48efea 100644
--- a/third_party/blink/renderer/core/dom/document_data.h
+++ b/third_party/blink/renderer/core/dom/document_data.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_DATA_H_
 
 #include "services/network/public/mojom/trust_tokens.mojom-blink.h"
-#include "third_party/blink/public/mojom/federated_learning/floc.mojom-blink.h"
 #include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_regexp.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
@@ -24,13 +23,10 @@
 class DocumentData final : public GarbageCollected<DocumentData> {
  public:
   explicit DocumentData(ExecutionContext* context)
-      : permission_service_(context),
-        floc_service_(context),
-        has_trust_tokens_answerer_(context) {}
+      : permission_service_(context), has_trust_tokens_answerer_(context) {}
 
   void Trace(Visitor* visitor) const {
     visitor->Trace(permission_service_);
-    visitor->Trace(floc_service_);
     visitor->Trace(has_trust_tokens_answerer_);
     visitor->Trace(pending_has_trust_tokens_resolvers_);
     visitor->Trace(email_regexp_);
@@ -41,9 +37,6 @@
   // storage or not.
   HeapMojoRemote<mojom::blink::PermissionService> permission_service_;
 
-  // Mojo remote used to query the floc (i.e. interestCohort).
-  HeapMojoRemote<mojom::blink::FlocService> floc_service_;
-
   // Mojo remote used to answer API calls asking whether the user has trust
   // tokens (https://github.com/wicg/trust-token-api). The other endpoint
   // is in the network service, which may crash and restart. To handle this:
diff --git a/third_party/blink/renderer/core/dom/interest_cohort.idl b/third_party/blink/renderer/core/dom/interest_cohort.idl
deleted file mode 100644
index d334a29..0000000
--- a/third_party/blink/renderer/core/dom/interest_cohort.idl
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2021 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.
-
-// https://wicg.github.io/floc/#dictdef-interestcohort
-
-dictionary InterestCohort {
-  DOMString id;
-  DOMString version;
-};
diff --git a/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc b/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
index ee512c2..c9ddc79 100644
--- a/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
+++ b/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
@@ -502,10 +502,6 @@
   if (trial_name == "TrustTokens")
     return base::FeatureList::IsEnabled(network::features::kTrustTokens);
 
-  if (trial_name == "InterestCohortAPI") {
-    return base::FeatureList::IsEnabled(
-        features::kInterestCohortAPIOriginTrial);
-  }
   if (trial_name == "SpeculationRulesPrefetch") {
     return base::FeatureList::IsEnabled(
         features::kSpeculationRulesPrefetchProxy);
diff --git a/third_party/blink/renderer/core/paint/box_painter.cc b/third_party/blink/renderer/core/paint/box_painter.cc
index f658871..63819bd 100644
--- a/third_party/blink/renderer/core/paint/box_painter.cc
+++ b/third_party/blink/renderer/core/paint/box_painter.cc
@@ -320,8 +320,15 @@
     // instead of the contents properties so that the scroll hit test is not
     // clipped or scrolled.
     auto& paint_controller = paint_info.context.GetPaintController();
-    DCHECK_EQ(fragment->LocalBorderBoxProperties(),
-              paint_controller.CurrentPaintChunkProperties());
+    // TODO(crbug.com/1256990): This should be
+    // DCHECK_EQ(fragment->LocalBorderBoxProperties(),
+    //           paint_controller.CurrentPaintChunkProperties());
+    // but we have problems about the effect node with CompositingReason::
+    // kTransform3DSceneLeaf on non-stacking-context elements.
+    DCHECK_EQ(&fragment->LocalBorderBoxProperties().Transform(),
+              &paint_controller.CurrentPaintChunkProperties().Transform());
+    DCHECK_EQ(&fragment->LocalBorderBoxProperties().Clip(),
+              &paint_controller.CurrentPaintChunkProperties().Clip());
     paint_controller.RecordScrollHitTestData(
         background_client, DisplayItem::kScrollHitTest,
         properties->ScrollTranslation(), VisualRect(fragment->PaintOffset()));
diff --git a/third_party/blink/renderer/core/paint/box_painter_test.cc b/third_party/blink/renderer/core/paint/box_painter_test.cc
index 404fa8b..ec8190d4 100644
--- a/third_party/blink/renderer/core/paint/box_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/box_painter_test.cc
@@ -262,4 +262,19 @@
             scroll_hit_test_chunk.hit_test_data->scroll_translation);
 }
 
+// crbug.com/1256990
+TEST_P(BoxPainterTest, ScrollerUnderInlineTransform3DSceneLeafCrash) {
+  SetBodyInnerHTML(R"HTML(
+    <div style="transform-style: preserve-3d">
+      <div style="display:inline">
+        <div style="display: inline-block; overflow: scroll;
+                    width: 100px; height: 100px">
+          <div style="height: 200px"></div>
+        </div>
+      </div>
+    </div>
+  )HTML");
+  // This should not crash.
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 b/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5
index e0c40608..435f3bb 100644
--- a/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5
+++ b/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5
@@ -255,12 +255,6 @@
       depends_on: ["IdleDetection"],
     },
     {
-      name: "InterestCohort",
-      permissions_policy_name: "interest-cohort",
-      feature_default: "EnableForAll",
-      depends_on: ["InterestCohortFeaturePolicy"],
-    },
-    {
       name: "JoinAdInterestGroup",
       permissions_policy_name: "join-ad-interest-group",
       feature_default: "EnableForAll",
diff --git a/third_party/blink/renderer/modules/credentialmanager/federated_credential.idl b/third_party/blink/renderer/modules/credentialmanager/federated_credential.idl
index ee532ecc..b5bee99 100644
--- a/third_party/blink/renderer/modules/credentialmanager/federated_credential.idl
+++ b/third_party/blink/renderer/modules/credentialmanager/federated_credential.idl
@@ -16,13 +16,13 @@
     [RaisesException] constructor(FederatedCredentialInit data);
     readonly attribute USVString provider;
 
-    // https://github.com/WICG/FedCM
+    // https://github.com/fedidcg/FedCM
     [RuntimeEnabled=WebID] readonly attribute USVString idToken;
 
     // Allows the RP to distinguish whether an "auto" sign-in [1] happened or an
     // "explicit" sign-in [2] happened.
-    // [1] https://wicg.github.io/WebID/#use-cases-auto-sign-in
-    // [2] https://wicg.github.io/WebID/#use-cases-explicit-sign-in
+    // [1] https://fedidcg.github.io/FedCM/#use-cases-auto-sign-in
+    // [2] https://fedidcg.github.io/FedCM/#use-cases-explicit-sign-in
     [RuntimeEnabled=WebID] readonly attribute FederatedCredentialApprover approvedBy;
 
     // Allows IDPs to logout the user out of all of the logged in RPs.
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 3f9d3ba..575fd66 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -2263,6 +2263,7 @@
     "//third_party/libjxl:libjxl",
     "//third_party/libyuv",
     "//third_party/webrtc/api/task_queue:task_queue_test",
+    "//third_party/webrtc_overrides:metronome_like_task_queue_test",
     "//third_party/webrtc_overrides:webrtc_component",
     "//ui/base:features",
     "//ui/base/prediction",
diff --git a/third_party/blink/renderer/platform/peerconnection/metronome_task_queue_factory_test.cc b/third_party/blink/renderer/platform/peerconnection/metronome_task_queue_factory_test.cc
index f0adfc0..528ef3f 100644
--- a/third_party/blink/renderer/platform/peerconnection/metronome_task_queue_factory_test.cc
+++ b/third_party/blink/renderer/platform/peerconnection/metronome_task_queue_factory_test.cc
@@ -15,23 +15,30 @@
 #include "third_party/webrtc/api/task_queue/task_queue_test.h"
 #include "third_party/webrtc/rtc_base/task_utils/to_queued_task.h"
 #include "third_party/webrtc_overrides/metronome_source.h"
+#include "third_party/webrtc_overrides/test/metronome_like_task_queue_test.h"
 
 namespace blink {
 
 namespace {
 
-using ::testing::ElementsAre;
 using ::webrtc::TaskQueueTest;
 
 constexpr base::TimeDelta kMetronomeTick = base::Hertz(64);
 
-// Wrapper needed for the TaskQueueTest suite.
+// Wrapper needed for the TaskQueueTest and MetronomeLikeTaskQueueTest suites.
 class TestMetronomeTaskQueueFactory final : public webrtc::TaskQueueFactory {
  public:
-  TestMetronomeTaskQueueFactory()
-      : metronome_source_(
-            base::MakeRefCounted<blink::MetronomeSource>(kMetronomeTick)),
-        factory_(CreateWebRtcMetronomeTaskQueueFactory(metronome_source_)) {}
+  static std::unique_ptr<TestMetronomeTaskQueueFactory>
+  CreateWithTestEnvironment() {
+    return std::unique_ptr<TestMetronomeTaskQueueFactory>(
+        new TestMetronomeTaskQueueFactory(
+            std::make_unique<base::test::TaskEnvironment>()));
+  }
+  static std::unique_ptr<TestMetronomeTaskQueueFactory>
+  CreateWithoutTestEnvironment() {
+    return std::unique_ptr<TestMetronomeTaskQueueFactory>(
+        new TestMetronomeTaskQueueFactory(nullptr));
+  }
 
   std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
   CreateTaskQueue(absl::string_view name, Priority priority) const override {
@@ -39,194 +46,38 @@
   }
 
  private:
-  base::test::TaskEnvironment task_environment_;
+  explicit TestMetronomeTaskQueueFactory(
+      std::unique_ptr<base::test::TaskEnvironment> task_environment)
+      : task_environment_(std::move(task_environment)),
+        metronome_source_(
+            base::MakeRefCounted<blink::MetronomeSource>(kMetronomeTick)),
+        factory_(CreateWebRtcMetronomeTaskQueueFactory(metronome_source_)) {}
+
+  std::unique_ptr<base::test::TaskEnvironment> task_environment_;
   scoped_refptr<blink::MetronomeSource> metronome_source_;
   std::unique_ptr<webrtc::TaskQueueFactory> factory_;
 };
 
 // Instantiate suite to run all tests defined in
-// /third_party/webrtc/api/task_queue/task_queue_test.h.
+// third_party/webrtc/api/task_queue/task_queue_test.h.
 INSTANTIATE_TEST_SUITE_P(
     WebRtcMetronomeTaskQueue,
     TaskQueueTest,
-    ::testing::Values(std::make_unique<TestMetronomeTaskQueueFactory>));
+    ::testing::Values([]() {
+      return TestMetronomeTaskQueueFactory::CreateWithTestEnvironment();
+    }));
 
-class MetronomeTaskQueueFactoryTest : public ::testing::Test {
- public:
-  MetronomeTaskQueueFactoryTest()
-      : task_environment_(
-            base::test::TaskEnvironment::ThreadingMode::MULTIPLE_THREADS,
-            base::test::TaskEnvironment::TimeSource::MOCK_TIME),
-        metronome_source_(
-            base::MakeRefCounted<MetronomeSource>(kMetronomeTick)),
-        task_queue_factory_(
-            CreateWebRtcMetronomeTaskQueueFactory(metronome_source_)) {}
-
- protected:
-  base::test::TaskEnvironment task_environment_;
-  scoped_refptr<MetronomeSource> metronome_source_;
-  std::unique_ptr<webrtc::TaskQueueFactory> task_queue_factory_;
-};
-
-TEST_F(MetronomeTaskQueueFactoryTest, PostTaskRunsPriorToTick) {
-  auto task_queue = task_queue_factory_->CreateTaskQueue(
-      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
-
-  bool did_run = false;
-  task_queue->PostTask(webrtc::ToQueuedTask([&did_run]() { did_run = true; }));
-
-  EXPECT_FALSE(did_run);
-  task_environment_.FastForwardBy(base::Nanoseconds(1));
-  EXPECT_TRUE(did_run);
-}
-
-TEST_F(MetronomeTaskQueueFactoryTest, NormalPriorityDelayedTasksRunOnTicks) {
-  auto task_queue = task_queue_factory_->CreateTaskQueue(
-      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
-
-  int task_run_counter = 0;
-
-  // Delay task until next tick.
-  task_queue->PostDelayedTask(
-      webrtc::ToQueuedTask([&task_run_counter]() { ++task_run_counter; }),
-      kMetronomeTick.InMilliseconds());
-  EXPECT_EQ(task_run_counter, 0);
-  task_environment_.FastForwardBy(kMetronomeTick);
-  EXPECT_EQ(task_run_counter, 1);
-
-  // Delay half a tick. A full tick must pass before it runs.
-  task_queue->PostDelayedTask(
-      webrtc::ToQueuedTask([&task_run_counter]() { ++task_run_counter; }),
-      (kMetronomeTick / 2).InMilliseconds());
-  task_environment_.FastForwardBy(kMetronomeTick - base::Milliseconds(1));
-  EXPECT_EQ(task_run_counter, 1);
-  task_environment_.FastForwardBy(base::Milliseconds(1));
-  EXPECT_EQ(task_run_counter, 2);
-
-  // Delay several ticks.
-  task_queue->PostDelayedTask(
-      webrtc::ToQueuedTask([&task_run_counter]() { ++task_run_counter; }),
-      (kMetronomeTick * 3).InMilliseconds());
-  task_environment_.FastForwardBy(kMetronomeTick * 2);
-  EXPECT_EQ(task_run_counter, 2);
-  task_environment_.FastForwardBy(kMetronomeTick);
-  EXPECT_EQ(task_run_counter, 3);
-}
-
-TEST_F(MetronomeTaskQueueFactoryTest,
-       NormalPriorityHighPrecisionDelayedTasksRunOutsideTicks) {
-  auto task_queue = task_queue_factory_->CreateTaskQueue(
-      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
-
-  bool did_run = false;
-  task_queue->PostDelayedHighPrecisionTask(
-      webrtc::ToQueuedTask([&did_run]() { did_run = true; }),
-      /*milliseconds=*/1);
-
-  EXPECT_FALSE(did_run);
-  task_environment_.FastForwardBy(base::Milliseconds(1));
-  EXPECT_TRUE(did_run);
-}
-
-TEST_F(MetronomeTaskQueueFactoryTest, CanDeleteTaskQueueWhileTasksAreInFlight) {
-  auto task_queue = task_queue_factory_->CreateTaskQueue(
-      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
-
-  bool did_run_post_task = false;
-  task_queue->PostTask(webrtc::ToQueuedTask(
-      [&did_run_post_task]() { did_run_post_task = true; }));
-  bool did_run_low_precision_delay_task = false;
-  task_queue->PostDelayedTask(
-      webrtc::ToQueuedTask([&did_run_low_precision_delay_task]() {
-        did_run_low_precision_delay_task = true;
-      }),
-      /*milliseconds=*/1);
-  bool did_run_high_precision_delay_task = false;
-  task_queue->PostDelayedHighPrecisionTask(
-      webrtc::ToQueuedTask([&did_run_high_precision_delay_task]() {
-        did_run_high_precision_delay_task = true;
-      }),
-      /*milliseconds=*/1);
-
-  EXPECT_FALSE(did_run_post_task);
-  EXPECT_FALSE(did_run_low_precision_delay_task);
-  EXPECT_FALSE(did_run_high_precision_delay_task);
-  task_queue.reset();
-
-  // The PostTask is executed, but not the delayed tasks.
-  EXPECT_TRUE(did_run_post_task);
-  EXPECT_FALSE(did_run_low_precision_delay_task);
-  EXPECT_FALSE(did_run_high_precision_delay_task);
-
-  // The delayed tasks never run because they have been cancelled.
-  task_environment_.FastForwardBy(kMetronomeTick);
-  EXPECT_FALSE(did_run_low_precision_delay_task);
-  EXPECT_FALSE(did_run_high_precision_delay_task);
-}
-
-TEST_F(MetronomeTaskQueueFactoryTest, DelayedTasksRunInOrder) {
-  auto task_queue = task_queue_factory_->CreateTaskQueue(
-      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
-
-  constexpr uint32_t kTime0Ms = 0;
-  constexpr uint32_t kTime1Ms = 1;
-  std::vector<std::string> run_tasks;
-
-  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
-                                run_tasks.emplace_back("Time0_First");
-                              }),
-                              kTime0Ms);
-  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
-                                run_tasks.emplace_back("Time1_First");
-                              }),
-                              kTime1Ms);
-  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
-                                run_tasks.emplace_back("Time1_Second");
-                              }),
-                              kTime1Ms);
-  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
-                                run_tasks.emplace_back("Time0_Second");
-                              }),
-                              kTime0Ms);
-  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
-                                run_tasks.emplace_back("Time0_Third");
-                              }),
-                              kTime0Ms);
-  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
-                                run_tasks.emplace_back("Time1_Third");
-                              }),
-                              kTime1Ms);
-  task_environment_.FastForwardBy(kMetronomeTick);
-
-  EXPECT_THAT(run_tasks,
-              ElementsAre("Time0_First", "Time0_Second", "Time0_Third",
-                          "Time1_First", "Time1_Second", "Time1_Third"));
-}
-
-TEST_F(MetronomeTaskQueueFactoryTest, DelayedTaskCanPostDelayedTask) {
-  auto task_queue = task_queue_factory_->CreateTaskQueue(
-      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
-
-  bool task0_ran = false;
-  bool task1_ran = false;
-
-  task_queue->PostDelayedTask(
-      webrtc::ToQueuedTask([&task_queue, &task0_ran, &task1_ran]() {
-        task0_ran = true;
-        // Inception!
-        task_queue->PostDelayedTask(
-            webrtc::ToQueuedTask([&task1_ran]() { task1_ran = true; }),
-            kMetronomeTick.InMilliseconds());
-      }),
-      kMetronomeTick.InMilliseconds());
-
-  task_environment_.FastForwardBy(kMetronomeTick);
-  EXPECT_TRUE(task0_ran);
-  EXPECT_FALSE(task1_ran);
-  task_environment_.FastForwardBy(kMetronomeTick);
-  EXPECT_TRUE(task0_ran);
-  EXPECT_TRUE(task1_ran);
-}
+// Instantiate suite to run all tests defined in
+// third_party/webrtc_overrides/test/metronome_like_task_queue_test.h
+INSTANTIATE_TEST_SUITE_P(WebRtcMetronomeTaskQueue,
+                         MetronomeLikeTaskQueueTest,
+                         ::testing::Values(MetronomeLikeTaskQueueTestParams{
+                             .task_queue_factory =
+                                 []() {
+                                   return TestMetronomeTaskQueueFactory::
+                                       CreateWithoutTestEnvironment();
+                                 },
+                             .metronome_tick = kMetronomeTick}));
 
 }  // namespace
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index cc319f6d7..37b196e0 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1264,15 +1264,6 @@
       status: "stable",
     },
     {
-      name: "InterestCohortAPI",
-      origin_trial_feature_name: "InterestCohortAPI",
-      origin_trial_allows_third_party: true,
-    },
-    {
-      name: "InterestCohortFeaturePolicy",
-      status: "experimental",
-    },
-    {
       name: "KeyboardAccessibleTooltip",
       status: "experimental",
     },
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
index a103b21..1bf3d56 100644
--- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
@@ -123,7 +123,7 @@
     const {
   CheckOnValidThread();
   DCHECK(sequence_manager_);
-  return sequence_manager_->GetNextWakeUp();
+  return sequence_manager_->GetNextDelayedWakeUp();
 }
 
 void SchedulerHelper::SetTimeDomain(
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
index db42ee4..e59d6a1 100644
--- a/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
@@ -83,7 +83,8 @@
       // WakeUpResolution::kLow is always used for throttled tasks since those
       // tasks can tolerate having their execution being delayed.
       return base::sequence_manager::WakeUp{
-          allowed_run_time, base::sequence_manager::WakeUpResolution::kLow};
+          allowed_run_time, base::sequence_manager::WakeUp::kDefaultLeeway,
+          base::sequence_manager::WakeUpResolution::kLow};
     }
   }
   if (!next_wake_up.has_value())
@@ -96,7 +97,9 @@
     allowed_run_time = desired_run_time;
 
   return base::sequence_manager::WakeUp{
-      allowed_run_time, base::sequence_manager::WakeUpResolution::kLow};
+      allowed_run_time, next_wake_up->leeway,
+      base::sequence_manager::WakeUpResolution::kLow,
+      next_wake_up->delay_policy};
 }
 
 void TaskQueueThrottler::OnHasImmediateTask() {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc
index 7614dc8..ab7f58cb 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc
@@ -188,7 +188,8 @@
                                                        base::Milliseconds(100));
 
   // Task at t+10ms should be run immediately.
-  EXPECT_GE(base::TimeTicks::Now(), sequence_manager_->GetNextWakeUp()->time);
+  EXPECT_GE(base::TimeTicks::Now(),
+            sequence_manager_->GetNextDelayedWakeUp()->time);
 
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(task_run);
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index cddd9bb..c54e2bb 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3191,6 +3191,31 @@
 crbug.com/626703 [ Linux ] external/wpt/url/failure.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/css/filter-effects/filter-function/filter-function-001.html [ Failure ]
+crbug.com/626703 external/wpt/css/filter-effects/filter-function/filter-function-002.html [ Failure ]
+crbug.com/626703 external/wpt/css/filter-effects/filter-function/filter-function-003.html [ Failure ]
+crbug.com/626703 external/wpt/css/filter-effects/filter-function/filter-function-005.html [ Failure ]
+crbug.com/626703 external/wpt/css/filter-effects/filter-function/filter-function-006.html [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Mac10.12 ] external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Mac10.13 ] external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Mac10.14 ] external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Mac10.15 ] external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Win ] external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Mac11 ] external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Timeout Failure ]
+crbug.com/626703 virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-001.html [ Failure ]
+crbug.com/626703 virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-002.html [ Failure ]
+crbug.com/626703 virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-003.html [ Failure ]
+crbug.com/626703 virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-005.html [ Failure ]
+crbug.com/626703 virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-006.html [ Failure ]
+crbug.com/626703 [ Linux ] virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Mac10.12 ] virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Mac10.14 ] virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Mac10.15 ] virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Mac11 ] virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Mac11-arm64 ] virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
+crbug.com/626703 [ Win ] virtual/scalefactor200/external/wpt/css/filter-effects/filter-function/filter-function-007.html [ Failure ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/fetch/api/response/response-clone.any.worker.html [ Timeout ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html [ Timeout ]
 crbug.com/626703 [ Mac11 ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/hidpi/device-pixel-ratio.https.html [ Failure ]
@@ -7549,9 +7574,6 @@
 # Now flaky due to a timing issue.
 crbug.com/1292296 http/tests/inspector-protocol/accessibility/accessibility-getRootNode.js [ Failure Pass ]
 
-# Flaky due to timing issue.
-crbug.com/1293515 wpt_internal/resource-timing/initiator-type-early-hints-preload.h2.window.html [ Failure Pass ]
-
 # Sheriff 2022-02-01
 # Flaky test on Mac
 crbug.com/1292843 [ Mac ] external/wpt/css/css-transforms/animation/perspective-origin-interpolation.html [ Failure Pass ]
@@ -7579,6 +7601,11 @@
 crbug.com/1271296 virtual/no-forced-frame-updates/external/wpt/html/dom/render-blocking/render-blocked-apis-by-preload-link.tentative.html [ Skip ]
 crbug.com/1271296 virtual/no-forced-frame-updates/external/wpt/html/dom/render-blocking/script-inserted-preload-link.tentative.html [ Skip ]
 crbug.com/1271296 virtual/no-forced-frame-updates/external/wpt/html/dom/render-blocking/script-inserted-stylesheet-link.tentative.html [ Skip ]
+crbug.com/1271296 virtual/no-forced-frame-updates/external/wpt/html/dom/render-blocking/parser-inserted-async-script.tentative.html [ Skip ]
+crbug.com/1271296 virtual/no-forced-frame-updates/external/wpt/html/dom/render-blocking/parser-inserted-defer-script.tentative.html [ Skip ]
+crbug.com/1271296 virtual/no-forced-frame-updates/external/wpt/html/dom/render-blocking/parser-inserted-module-script.tentative.html [ Skip ]
+crbug.com/1271296 virtual/no-forced-frame-updates/external/wpt/html/dom/render-blocking/script-inserted-module-script.tentative.html [ Skip ]
+crbug.com/1271296 virtual/no-forced-frame-updates/external/wpt/html/dom/render-blocking/script-inserted-script.html [ Skip ]
 
 # Sheriff 2022-02-03
 crbug.com/1293878 [ Mac ] virtual/controls-refresh-hc/fast/forms/color-scheme/datetimelocal-picker/datetimelocal-picker-appearance.html [ Skip ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 86bf01c..54677d4 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -789,11 +789,6 @@
     "args": [ "--enable-features=BackForwardCache" ]
   },
   {
-    "prefix": "interest-cohort-api-origin-trial",
-    "bases": [ "http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces.html" ],
-    "args": [ "--enable-features=InterestCohortAPIOriginTrial" ]
-  },
-  {
     "prefix": "third-party-storage-partitioning",
     "bases": [
       "external/wpt/web-locks/partitioned-web-locks.tentative.https.html",
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version
index b4feb17..e1e2d6a 100644
--- a/third_party/blink/web_tests/external/Version
+++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@
-Version: 9ed88e9fa342a2320491d435bd5d91a5f546e00e
+Version: 7f8942c429a66fa5225d2b9cebcf72d09afd9b14
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 3aeb586f..c1d1a7b0 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -2567,6 +2567,13 @@
        {}
       ]
      ],
+     "selection-modify-around-input-in-contenteditable.html": [
+      "90b615da5cdd2ad51782577a3b90a4106be5e128",
+      [
+       null,
+       {}
+      ]
+     ],
      "unloading-editor-in-subdocument-containing-misspelled-word.html": [
       "1b90e1d56a6a03bf164ca053691c3117b513af57",
       [
@@ -3419,6 +3426,13 @@
        null,
        {}
       ]
+     ],
+     "firefox-bug-1753105.html": [
+      "3105c577beac345c25a432c4a5e0646125b4f78e",
+      [
+       null,
+       {}
+      ]
      ]
     },
     "extensibility": {
@@ -120526,6 +120540,19 @@
         {}
        ]
       ],
+      "custom-highlight-painting-018.html": [
+       "95bef09bbe441803e53304ca5e43480ca1093124",
+       [
+        null,
+        [
+         [
+          "/css/css-highlight-api/painting/custom-highlight-painting-001-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "custom-highlight-painting-below-grammar.html": [
        "93d2560040b791a0685151cc29587c771fad8c03",
        [
@@ -120813,7 +120840,7 @@
        ]
       ],
       "custom-highlight-painting-staticrange-001.html": [
-       "8b116c6904f6046012e70c2f4ee82f8cd4136fce",
+       "ee81bb89d713b6df203b00a0b92d67b2da7800b1",
        [
         null,
         [
@@ -120826,7 +120853,7 @@
        ]
       ],
       "custom-highlight-painting-staticrange-002.html": [
-       "be4280966e21e9ed63fe5749c78aa1009d65cc81",
+       "43a0b06c35e9cfda39f7be2c33c779c8f0422686",
        [
         null,
         [
@@ -120851,58 +120878,6 @@
         {}
        ]
       ],
-      "custom-highlight-painting-staticrange-004.html": [
-       "14e9766a981afe6ce2efa368eb2fbb5ec62a697e",
-       [
-        null,
-        [
-         [
-          "/css/css-highlight-api/painting/custom-highlight-painting-staticrange-001-ref.html",
-          "=="
-         ]
-        ],
-        {}
-       ]
-      ],
-      "custom-highlight-painting-staticrange-005.html": [
-       "b955b0fcee4342a24a6b59d6d91e0f2fbdd4126f",
-       [
-        null,
-        [
-         [
-          "/css/css-highlight-api/painting/custom-highlight-painting-001-ref.html",
-          "=="
-         ]
-        ],
-        {}
-       ]
-      ],
-      "custom-highlight-painting-staticrange-006.html": [
-       "8436102240d04b161bf55d711a64ad92c1309959",
-       [
-        null,
-        [
-         [
-          "/css/css-highlight-api/painting/custom-highlight-painting-staticrange-001-ref.html",
-          "=="
-         ]
-        ],
-        {}
-       ]
-      ],
-      "custom-highlight-painting-staticrange-007.html": [
-       "03a7ee6d54534a7545f26be083659c0c26c4e4fc",
-       [
-        null,
-        [
-         [
-          "/css/css-highlight-api/painting/custom-highlight-painting-001-ref.html",
-          "=="
-         ]
-        ],
-        {}
-       ]
-      ],
       "custom-highlight-painting-text-decoration-001.html": [
        "df6e5dd32cc9260743ab096acf3bb13cf8f9abfb",
        [
@@ -205824,6 +205799,112 @@
        {}
       ]
      ],
+     "filter-function": {
+      "filter-function-001.html": [
+       "4294218511751bea11f681b1987f33d07d1c641f",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "filter-function-002.html": [
+       "c1b0b0a78c8b3361af32d05229fde264546944f5",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "filter-function-003.html": [
+       "cb1bf35819275907dd9cb5a83ac20fcae701df40",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "filter-function-004.html": [
+       "07825d8d0d6ce142fe860e355b92738df2cad9fb",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "filter-function-005.html": [
+       "2d3ad5b9a95c2ec38e63464d8a6c8abe9d32f169",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "filter-function-006.html": [
+       "fe5c0c384957842e1399de0872cb45bb025ea6da",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "filter-function-007.html": [
+       "aad794e019e52f38e2a1fa28cb0798978d634caf",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "filter-function-008.html": [
+       "951a4ed7fd8594b5f153e6f73b3ebab0a9e09f37",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ]
+     },
      "filter-grayscale-001.html": [
       "c6fc1be727c3964368120a878166dbaaa41df0ed",
       [
@@ -228548,6 +228629,10 @@
      "3f5238e841d7f3af9a87fb8e8fe4e784dc662a67",
      []
     ],
+    "idb-partitioned-basic.tentative.sub-expected.txt": [
+     "f34c47c662d47df8d9de74ea270b98d243614c54",
+     []
+    ],
     "idbworker.js": [
      "359f6fb69119b5c6605047f0e0c38ef6fe847009",
      []
@@ -228571,6 +228656,10 @@
       "997c5a2b72bafcad3421ccb48e48e323de6ef6f0",
       []
      ],
+     "idb-partitioned-iframe.tentative.html": [
+      "ed6bbf272f0af4609e77afa7679ec5f0d677e100",
+      []
+     ],
      "idbfactory-origin-isolation-iframe.html": [
       "d405ea48e15e298241a2c400a6d04adbd054e1e5",
       []
@@ -271478,7 +271567,7 @@
       []
      ],
      "idlharness-expected.txt": [
-      "3470bea6fc0796ed7bc4343a82ff8ce2579689f7",
+      "59c039ac45fdf0888afc1e30cc00342829121403",
       []
      ],
      "resources": {
@@ -271504,11 +271593,11 @@
      "stylevalue-subclasses": {
       "numeric-objects": {
        "cssUnitValue-expected.txt": [
-        "36ed6fb351f75d2688fe3a3995a426a957cda2ec",
+        "79f57d4ca4fc09701717eb109411730c2cdf641c",
         []
        ],
        "numeric-factory.tentative-expected.txt": [
-        "c768f1244dd71b180d60b810c3dbe6dfdabce70c",
+        "6de3224ecda3d2b3c3a19d41b05d08c66b077337",
         []
        ],
        "resources": {
@@ -273604,10 +273693,6 @@
      "viewport-units-001-print-ref.html": [
       "bc914522c7fcf556c69ba56d2d0ba792d7e92b89",
       []
-     ],
-     "viewport-units-parsing-expected.txt": [
-      "3984c7c987664bb5f2c5a06ced4618d72f89c24d",
-      []
      ]
     },
     "css-variables": {
@@ -277059,6 +277144,26 @@
       "794674da48456eeaee84710ddff8c2197de7cf9e",
       []
      ],
+     "filter-function": {
+      "resources": {
+       "green-transparent-100x100.png": [
+        "fe89b0da37571c09e921a44c9efa05cbedc27620",
+        []
+       ],
+       "green-transparent-200x200.png": [
+        "deac37042f7871e7020155b78d446ba94f2a1c69",
+        []
+       ],
+       "green-transparent-20x10.png": [
+        "3570d532184be32a447860c9905334733ae14592",
+        []
+       ],
+       "green-transparent-80x80.png": [
+        "cf180535b9b94510fc0775826fdf6d612fd2a97e",
+        []
+       ]
+      }
+     },
      "filter-grayscale-ref.html": [
       "beaa72aaa3c3e9a6fdbf95ef3f50c7c515a77b44",
       []
@@ -284093,7 +284198,7 @@
        []
       ],
       "preflight.py": [
-       "bc2250456e04dbb35edb0496685d0af698fded6b",
+       "730a5532624e1b7f727244676e2f5f09f7576cbc",
        []
       ],
       "service-worker-bridge.html": [
@@ -284117,7 +284222,7 @@
        []
       ],
       "support.sub.js": [
-       "98ae1f3457cd5a1e5cf431b8150542b1eb4322a0",
+       "ecb8b8193d49323e03152233bea7bafd0b6b793a",
        []
       ],
       "worker-fetcher.html": [
@@ -291071,12 +291176,20 @@
      ],
      "render-blocking": {
       "support": {
+       "dummy-1.js": [
+        "597772cf641d83b41f0e4238a1fa74a050f29d3c",
+        []
+       ],
+       "dummy-1.mjs": [
+        "9b85a21033e92389cf43e11f5fb97d6d4139f9d2",
+        []
+       ],
        "target-red.css": [
         "a387acd4ecb17a0a0419fb5b3c90a1f0b2f1b0ea",
         []
        ],
        "test-render-blocking.js": [
-        "5d193a4ab211931fae656e8851845beff879e4a2",
+        "b3d09abaa508d614a280af55bb4675a05500b6dd",
         []
        ]
       }
@@ -305907,7 +306020,13 @@
     "permission-helper.js": [
      "769f3ee24247b4c5231e6cc3b63340bf4659104b",
      []
-    ]
+    ],
+    "support": {
+     "iframe-MediaStreamTrack-transfer.html": [
+      "e8d6aac647de880283dca1cd6993f05787acf289",
+      []
+     ]
+    }
    },
    "mediasession": {
     "DIR_METADATA": [
@@ -320071,6 +320190,10 @@
      []
     ],
     "broadcastchannel": {
+     "cross-partition.https.tentative-expected.txt": [
+      "208239edbd3886300b4b759afc96b4f26787557f",
+      []
+     ],
      "resources": {
       "cross-origin.html": [
        "5078b6fc8e46f556fe1b86c7e1aa5a141c132be1",
@@ -327212,6 +327335,13 @@
       }
      ]
     ],
+    "idb-partitioned-basic.tentative.sub.html": [
+     "326d1f4d3d5d38057c5a903526dca843eaf8ac9b",
+     [
+      null,
+      {}
+     ]
+    ],
     "idb_binary_key_conversion.htm": [
      "b55e6324b349987750816d49efb9eb908a845724",
      [
@@ -379697,7 +379827,7 @@
         ]
        ],
        "equals.tentative.html": [
-        "6e135cef2d8ef059576ac87105a184905a0295f2",
+        "dc1e7959f6e32175797c784b57cb5560841ea9f8",
         [
          null,
          {}
@@ -382781,6 +382911,13 @@
        {}
       ]
      ],
+     "viewport-units-compute.html": [
+      "7310946c0d730c7d1c9604ed9accc14df46957b7",
+      [
+       null,
+       {}
+      ]
+     ],
      "viewport-units-css2-001.html": [
       "c51237dd8a07546d31eef6f6f9b3c84b6ac2b65b",
       [
@@ -382788,12 +382925,40 @@
        {}
       ]
      ],
+     "viewport-units-invalidation.html": [
+      "93512ab9a53a1a4f88560c3ddb7abedf7ab5b132",
+      [
+       null,
+       {}
+      ]
+     ],
+     "viewport-units-keyframes.html": [
+      "6e50a84331e58273febd23e539d12311e92bf1e8",
+      [
+       null,
+       {}
+      ]
+     ],
+     "viewport-units-media-queries.html": [
+      "33561793319f1400cca787dcdaebedc28381db34",
+      [
+       null,
+       {}
+      ]
+     ],
      "viewport-units-parsing.html": [
       "4373b2a9f0844456c00904a3d90e159c78362c28",
       [
        null,
        {}
       ]
+     ],
+     "viewport-units-writing-mode.html": [
+      "ee851fd17c412790a704a9caa217fe481ab73a9f",
+      [
+       null,
+       {}
+      ]
      ]
     },
     "css-variables": {
@@ -418141,8 +418306,26 @@
        }
       ]
      ],
+     "redirect.https.window.js": [
+      "fe004d929dec6da4f0985528d9e97e7f2fdd05c6",
+      [
+       "fetch/private-network-access/redirect.https.window.html",
+       {
+        "script_metadata": [
+         [
+          "script",
+          "/common/utils.js"
+         ],
+         [
+          "script",
+          "resources/support.sub.js"
+         ]
+        ]
+       }
+      ]
+     ],
      "service-worker-fetch.https.window.js": [
-      "edb20c04940e3fa76a2dd99e71785f97285c31c6",
+      "5645d78456156d09afd5b074c24215de83b19c4a",
       [
        "fetch/private-network-access/service-worker-fetch.https.window.html",
        {
@@ -418160,7 +418343,7 @@
       ]
      ],
      "service-worker-update.https.window.js": [
-      "703c7650b0dbeeb4559a74e3557a91bf6b484e19",
+      "aa0a770ba0ed8e80e27339262dc89f82466b51fd",
       [
        "fetch/private-network-access/service-worker-update.https.window.html",
        {
@@ -418178,7 +418361,7 @@
       ]
      ],
      "service-worker.https.window.js": [
-      "3d3845b4d7cb832dcc4ad7238c54d655c84656fc",
+      "91338462fa378f3fd253f67a5de514a5a6d4e0fb",
       [
        "fetch/private-network-access/service-worker.https.window.html",
        {
@@ -447730,6 +447913,34 @@
       ]
      ],
      "render-blocking": {
+      "parser-blocking-script.tentative.html": [
+       "8d391144b26b04a2c74ba1fdaf1f6ce675a79a76",
+       [
+        null,
+        {}
+       ]
+      ],
+      "parser-inserted-async-script.tentative.html": [
+       "4b2216dfcb16594f026500f0402677945a641d9a",
+       [
+        null,
+        {}
+       ]
+      ],
+      "parser-inserted-defer-script.tentative.html": [
+       "1ae8caf2ec9b43741fdf2a81b9b2590480c05f3b",
+       [
+        null,
+        {}
+       ]
+      ],
+      "parser-inserted-module-script.tentative.html": [
+       "2bca88e73c4c597c3cb5a301f7adae3ff7599db4",
+       [
+        null,
+        {}
+       ]
+      ],
       "parser-inserted-preload-link.tentative.html": [
        "827985d71a8a92e64a3bded1463e6d247d3d0f79",
        [
@@ -447752,12 +447963,24 @@
        ]
       ],
       "render-blocked-apis-by-preload-link.tentative.html": [
-       "cbc7a9a5104db4f6289694f2f3208599b269a868",
+       "8219fc8af9022eadb7c73333abbf20898272eb1d",
        [
         null,
-        {
-         "testdriver": true
-        }
+        {}
+       ]
+      ],
+      "render-blocked-apis-by-stylesheet-link.tentative.html": [
+       "30b60fc1103cf457ca3f1ae4f139a38ebde75a19",
+       [
+        null,
+        {}
+       ]
+      ],
+      "script-inserted-module-script.tentative.html": [
+       "73f0d3cdf4f2223530dcaf4e48fbf0f5034410cd",
+       [
+        null,
+        {}
        ]
       ],
       "script-inserted-preload-link.tentative.html": [
@@ -447767,6 +447990,13 @@
         {}
        ]
       ],
+      "script-inserted-script.html": [
+       "faf346b4ddaa37a090b97225ef89ef2e96a9233b",
+       [
+        null,
+        {}
+       ]
+      ],
       "script-inserted-style-element.tentative.html": [
        "683706af50d97cd4163845adf954f214b636d9b3",
        [
@@ -473548,6 +473778,13 @@
       }
      ]
     ],
+    "MediaStreamTrack-iframe-transfer.https.html": [
+     "28ff506b9e7c0d222bd7e7097191a70f344e0a28",
+     [
+      null,
+      {}
+     ]
+    ],
     "MediaStreamTrack-init.https.html": [
      "54ebf049e874222bb93260337b1b2468f6e59495",
      [
@@ -529983,6 +530220,13 @@
        {}
       ]
      ],
+     "cross-partition.https.tentative.html": [
+      "163e6c00a93a95364a044aa7c8f01e5d4b5a4fd5",
+      [
+       null,
+       {}
+      ]
+     ],
      "detached-iframe.html": [
       "b9b06c3a46463bf50a88ebc545f1ad9ed6ac496a",
       [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/stylevalue-subclasses/numeric-objects/equals.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-typed-om/stylevalue-subclasses/numeric-objects/equals.tentative.html
index 6e135ce..dc1e7959 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-typed-om/stylevalue-subclasses/numeric-objects/equals.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/stylevalue-subclasses/numeric-objects/equals.tentative.html
@@ -62,11 +62,13 @@
 test(() => {
   const a = new CSSMathClamp(1, 2, 3);
   const b = new CSSMathClamp(CSS.number(1), CSS.number(2), CSS.number(3));
+  assert_true(a.equals(b));
 }, 'Two CSSMathClamp with same value and unit are equal');
 
 test(() => {
   const a = new CSSMathClamp(1, 2, 3);
   const b = new CSSMathClamp(CSS.px(1), CSS.px(2), CSS.px(3));
+  assert_false(a.equals(b));
 }, 'Two CSSMathClamp with different units are not equal');
 
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-001.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-001.html
new file mode 100644
index 0000000..4294218
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-001.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>filter function can be applied to an image included as content</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter"/>
+<link rel="help" href="https://drafts.csswg.org/css-content/#content-property"/>
+<link rel="author" title="Mike Bremford" href="http://bfo.com/" />
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"/>
+<style>
+div {
+    width: 100px;
+    height: 100px;
+    background: red;
+    image-rendering: crisp-edges;
+    content: filter(url(resources/green-transparent-100x100.png), drop-shadow(50px 0 0 green));
+}
+</style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div></div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-002.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-002.html
new file mode 100644
index 0000000..c1b0b0a7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-002.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>filter function can be applied to border-image</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter"/>
+<link rel="author" title="Mike Bremford" href="http://bfo.com/" />
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"/>
+<style>
+.test {
+    position: relative;
+    width: 50px;
+    height: 100px;
+    box-sizing: border-box;
+    border: 25px solid black;
+    border-image: filter(url(resources/green-transparent-200x200.png), drop-shadow(50px 0 0 green)) 75 / 75px / 50px;
+}
+.red {
+    position: absolute;
+    left: -25px;
+    top: -25px;
+    width: 100px;
+    height: 100px;
+    background: red;
+    z-index: -1;
+}
+</style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="test">
+ <div class="red"></div>
+ </div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-003.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-003.html
new file mode 100644
index 0000000..cb1bf35
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-003.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>filter function can be applied to a background-image</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter"/>
+<link rel="author" title="Mike Bremford" href="http://bfo.com/" />
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"/>
+<style>
+.test {
+    width: 100px;
+    height: 100px;
+    background: filter(url(resources/green-transparent-100x100.png), drop-shadow(50px 0 0 green)) top left no-repeat, red;
+}
+</style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="test"></div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-004.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-004.html
new file mode 100644
index 0000000..07825d8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-004.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>filter function can be applied to a mask-image</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter"/>
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#the-mask-mode"/>
+<link rel="author" title="Mike Bremford" href="http://bfo.com/" />
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"/>
+<style>
+.test {
+    position: relative;
+    width: 100px;
+    height: 100px;
+    mask: filter(url(resources/green-transparent-100x100.png), drop-shadow(50px 0 0 black)) top left no-repeat alpha;
+    -webkit-mask: filter(url(resources/green-transparent-100x100.png), drop-shadow(50px 0 0 black)) top left no-repeat alpha;
+}
+.content {
+    width: 100px;
+    height: 100px;
+    background: green;
+}
+</style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="test"><div class="content"></div></div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-005.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-005.html
new file mode 100644
index 0000000..2d3ad5b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-005.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>filter function units are not scaled when applied to a scaled image included as content</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter"/>
+<link rel="help" href="https://drafts.csswg.org/css-content/#content-property"/>
+<link rel="author" title="Mike Bremford" href="http://bfo.com/" />
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"/>
+<meta name="assert" content="The dimensions in the filter functions are absolute dimensions, and if the image they are applied to is scaled (as it is here due to being part of an image included as generated content), the units in the filters should not be scaled. The filter must be applied after scaling." />
+<style>
+div {
+    width: 100px;
+    height: 100px;
+    background: red;
+    image-rendering: crisp-edges;
+    content: filter(url(resources/green-transparent-20x10.png), drop-shadow(50px 0 0 green));
+}
+</style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div></div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-006.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-006.html
new file mode 100644
index 0000000..fe5c0c3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-006.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>filter function unis are not scaled when applied to a scaled border-image</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter"/>
+<link rel="author" title="Mike Bremford" href="http://bfo.com/" />
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"/>
+<meta name="assert" content="The dimensions in the filter functions are absolute dimensions, and if the image they are applied to is scaled (as it is here due to being part of a border-image), the units in the filters should not be scaled. The filter must be applied after scaling."/>
+<style>
+.test {
+    position: relative;
+    width: 50px;
+    height: 100px;
+    box-sizing: border-box;
+    border: 25px solid black;
+    image-rendering: crisp-edges;
+    border-image: filter(url(resources/green-transparent-80x80.png), drop-shadow(50px 0 0 green)) 30 / 75px / 50px;
+}
+.red {
+    position: absolute;
+    left: -25px;
+    top: -25px;
+    width: 100px;
+    height: 100px;
+    background: red;
+    z-index: -1;
+}
+</style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="test">
+ <div class="red"></div>
+ </div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-007.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-007.html
new file mode 100644
index 0000000..aad794e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-007.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>filter function units are not scaled when applied to a scaled background-image</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter"/>
+<link rel="author" title="Mike Bremford" href="http://bfo.com/" />
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"/>
+<meta name="assert" content="The dimensions in the filter functions are absolute dimensions, and if the image they are applied to is scaled (as it is here due to being part of a background-image), the units in the filters should not be scaled. The filter must be applied after scaling."/>
+<style>
+.test {
+    position: relative;
+    width: 100px;
+    height: 100px;
+    image-rendering: crisp-edges;
+    background: filter(url(resources/green-transparent-20x10.png), drop-shadow(50px 0 0 green)) top left / 100px 100px no-repeat, red;
+}
+.red {
+    position: absolute;
+    width: 100px;
+    height: 100px;
+    background: red;
+    z-index: -1;
+}
+</style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="test">
+ </div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-008.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-008.html
new file mode 100644
index 0000000..951a4ed
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/filter-function-008.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>filter function units are not scaled when applied to a scaled mask-image</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter"/>
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#the-mask-mode"/>
+<link rel="author" title="Mike Bremford" href="http://bfo.com/" />
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"/>
+<meta name="assert" content="The dimensions in the filter functions are absolute dimensions, and if the image they are applied to is scaled (as it is here due to being part of a mask-image), the units in the filters should not be scaled. The filter must be applied after scaling."/>
+<style>
+.test {
+    position: relative;
+    width: 100px;
+    height: 100px;
+    mask: filter(url(resources/green-transparent-20x10.png), drop-shadow(50px 0 0 black)) top left / 100px 100px no-repeat alpha;
+    -webkit-mask: filter(url(resources/green-transparent-20x10.png), drop-shadow(50px 0 0 black)) top left / 100px 100px no-repeat alpha;
+}
+.content {
+    width: 100px;
+    height: 100px;
+    background: green;
+}
+</style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="test"><div class="content"></div></div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-100x100.png b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-100x100.png
new file mode 100644
index 0000000..fe89b0d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-100x100.png
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-200x200.png b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-200x200.png
new file mode 100644
index 0000000..deac370
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-200x200.png
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-20x10.png b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-20x10.png
new file mode 100644
index 0000000..3570d532
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-20x10.png
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-80x80.png b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-80x80.png
new file mode 100644
index 0000000..cf18053
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-function/resources/green-transparent-80x80.png
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/editing/crashtests/selection-modify-around-input-in-contenteditable.html b/third_party/blink/web_tests/external/wpt/editing/crashtests/selection-modify-around-input-in-contenteditable.html
new file mode 100644
index 0000000..90b615da
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/editing/crashtests/selection-modify-around-input-in-contenteditable.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script>
+addEventListener("load", () => {
+  const selection = window.getSelection();
+  const range = selection.getRangeAt(0);
+  selection.modify("move", "backward", "character");
+  selection.addRange(range);
+});
+</script>
+</head>
+<body>
+<fieldset contenteditable spellcheck="true">
+  <input value="x">
+  <table>
+    <caption></caption>
+  </table>
+</fieldset>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-blocking-script.tentative.html b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-blocking-script.tentative.html
new file mode 100644
index 0000000..8d39114
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-blocking-script.tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Parser-blocking script elements are implicitly render-blocking</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/test-render-blocking.js"></script>
+
+<script>
+// Add some renderable content before parser inserts body
+document.documentElement.appendChild(document.createTextNode('text'));
+
+// Test must be setup before the parser-blocking script
+test_render_blocking(
+    () => assert_equals(window.dummy, 1),
+    'Parser-blocking script is evaluated');
+</script>
+
+<script src="support/dummy-1.js?pipe=trickle(d1)"></script>
+
+<div>Some more text</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-async-script.tentative.html b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-async-script.tentative.html
new file mode 100644
index 0000000..4b2216d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-async-script.tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Parser-inserted async script elements with "blocking=render" are render-blocking</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/test-render-blocking.js"></script>
+
+<script id="async-script" async blocking="render"
+        src="support/dummy-1.js?pipe=trickle(d1)">
+</script>
+
+<div>Some text</div>
+
+<script>
+const asyncScript = document.getElementById('async-script');
+test_render_blocking(
+    asyncScript,
+    () => assert_equals(window.dummy, 1),
+    'Parser-inserted render-blocking async script is evaluated');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-defer-script.tentative.html b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-defer-script.tentative.html
new file mode 100644
index 0000000..1ae8caf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-defer-script.tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Parser-inserted defer script elements with "blocking=render" are render-blocking</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/test-render-blocking.js"></script>
+
+<script id="defer-script" defer blocking="render"
+        src="support/dummy-1.js?pipe=trickle(d1)">
+</script>
+
+<div>Some text</div>
+
+<script>
+const deferScript = document.getElementById('defer-script');
+test_render_blocking(
+    deferScript,
+    () => assert_equals(window.dummy, 1),
+    'Parser-inserted render-blocking defer script is evaluated');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-module-script.tentative.html b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-module-script.tentative.html
new file mode 100644
index 0000000..2bca88e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-module-script.tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Parser-inserted module script elements with "blocking=render" are render-blocking</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/test-render-blocking.js"></script>
+
+<script id="module-script" type="module" blocking="render"
+        src="support/dummy-1.mjs?pipe=trickle(d1)">
+</script>
+
+<div id="dummy">some text</div>
+
+<script>
+const moduleScript = document.getElementById('module-script');
+test_render_blocking(
+    moduleScript,
+    () => assert_equals(document.getElementById('dummy').textContent, '1'),
+    'Parser-inserted render-blocking module script is evaluated');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-module-script.tentative.html b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-module-script.tentative.html
new file mode 100644
index 0000000..73f0d3c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-module-script.tentative.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Script-inserted module script elements with "blocking=render" are render-blocking</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/test-render-blocking.js"></script>
+
+<script>
+const moduleScript = document.createElement('script');
+moduleScript.type = 'module';
+moduleScript.blocking = 'render';
+moduleScript.src = 'support/dummy-1.mjs?pipe=trickle(d1)';
+document.head.appendChild(moduleScript);
+</script>
+
+<div id="dummy">some text</div>
+
+<script>
+test_render_blocking(
+    moduleScript,
+    () => assert_equals(document.getElementById('dummy').textContent, '1'),
+    'Script-inserted render-blocking module script is evaluated');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-script.html b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-script.html
new file mode 100644
index 0000000..faf346b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-script.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>Script-inserted script elements with "blocking=render" are render-blocking</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/test-render-blocking.js"></script>
+
+<script>
+const script = document.createElement('script');
+script.src = 'support/dummy-1.js?pipe=trickle(d1)';
+script.blocking = 'render';
+document.head.appendChild(script);
+</script>
+
+<div>Some text</div>
+
+<script>
+test_render_blocking(
+    script,
+    () => assert_equals(window.dummy, 1),
+    'Script-inserted render-blocking script is evaluated');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/support/dummy-1.js b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/support/dummy-1.js
new file mode 100644
index 0000000..597772c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/support/dummy-1.js
@@ -0,0 +1 @@
+window.dummy = 1;
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/support/dummy-1.mjs b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/support/dummy-1.mjs
new file mode 100644
index 0000000..9b85a210
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/support/dummy-1.mjs
@@ -0,0 +1 @@
+document.getElementById('dummy').textContent = 1;
diff --git a/third_party/blink/web_tests/external/wpt/svg/crashtests/firefox-bug-1753105.html b/third_party/blink/web_tests/external/wpt/svg/crashtests/firefox-bug-1753105.html
new file mode 100644
index 0000000..3105c577
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/crashtests/firefox-bug-1753105.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<script>
+  document.addEventListener("DOMContentLoaded", () => {
+    const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg")
+    const text = document.createElementNS("http://www.w3.org/2000/svg", "text")
+    text.setAttribute("letter-spacing", "-37vw")
+    const node = document.createTextNode("\n\n\r7%٠\0ó …§ð†ªã€€&**=ðŸ¯šð¯‚ï¸¡ó ”©Û¹â€Ùªv*/𯄝𖹧垝纶*;{0ð–£”9̆뢻\r\n^掶𩹺*|\r\n🩂٫𐇽뫻e犮㇆᭲𡇂\u2028ᨲ⁤\rv+🧌8שּׁ\nð¯Žè›¥ó „ˆêº¡\n⒝𝱒٠۹𖯸0ó ¤™/ᾂ𫞾99 a&=𝉂۹𯩒゙2ó ¥µ^0ꒋ𝗻𝅻\0X%+0*/镳 ٪ȺXá©¿L2⼤𛪈­𪸏𛝉")
+    text.appendChild(node)
+    svg.appendChild(text)
+    document.documentElement.appendChild(svg)
+    const rect = document.documentElement.getBoundingClientRect()
+    node.convertRectFromNode(rect, svg, {})
+  })
+</script>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt
deleted file mode 100644
index e14ba67..0000000
--- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Test that the API exists with origin trial token
-
-FAILURE
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces.html b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces.html
deleted file mode 100644
index 96afbc7..0000000
--- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<!-- Generate token with the command:
-generate_token.py http://127.0.0.1:8000 InterestCohortAPI --expire-timestamp=2000000000 --version 3
--->
-<meta http-equiv="origin-trial" content="A1q7Ss8yaDaFBy5/0JLZCpLDbCD0o4uPIJkE9YEkUUuOBdvmdJiBcoNSy9OvLuRh+XsWnW3zP+0UcWI2T1vP1AwAAABZeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiSW50ZXJlc3RDb2hvcnRBUEkiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=" />
-<title>Interest Cohort API - interfaces exposed by origin trial</title>
-<body>
-<p>Test that the API exists with origin trial token</p>
-<div id="result"></div>
-<script>
-'use strict'
-
-if (window.testRunner) {
-  testRunner.dumpAsText();
-}
-
-if (document.interestCohort instanceof Function) {
-  document.getElementById("result").innerHTML += "SUCCESS";
-} else {
-  document.getElementById("result").innerHTML += "FAILURE";
-}
-</script>
-</body>
diff --git a/third_party/blink/web_tests/platform/win7/virtual/prerender/external/wpt/speculation-rules/prerender/restriction-window-move-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/prerender/external/wpt/speculation-rules/prerender/restriction-window-move-expected.txt
new file mode 100644
index 0000000..8d85af6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/prerender/external/wpt/speculation-rules/prerender/restriction-window-move-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL a prerendering page cannot move its window by executing moveTo. assert_equals: expected "PASS" but got "FAIL: Error: assert_equals: y position for primary expected 1 but got 0"
+PASS a prerendering page cannot move its window by executing moveBy.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/README.md b/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/README.md
deleted file mode 100644
index d260d11..0000000
--- a/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-*This suite runs the tests with**
-`--enable-features=InterestCohortAPIOriginTrial`
diff --git a/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt b/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt
deleted file mode 100644
index 710fa8f..0000000
--- a/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Test that the API exists with origin trial token
-
-SUCCESS
diff --git a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt
index 669d2d9..35afa391 100644
--- a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt
+++ b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt
@@ -42,7 +42,6 @@
 gyroscope
 hid
 idle-detection
-interest-cohort
 keyboard-map
 magnetometer
 microphone
diff --git a/third_party/closure_compiler/externs/autofill_private.js b/third_party/closure_compiler/externs/autofill_private.js
index 11f3deb..1e180eb 100644
--- a/third_party/closure_compiler/externs/autofill_private.js
+++ b/third_party/closure_compiler/externs/autofill_private.js
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2022 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.
 
@@ -36,7 +36,9 @@
  *   summarySublabel: (string|undefined),
  *   isLocal: (boolean|undefined),
  *   isCached: (boolean|undefined),
- *   isMigratable: (boolean|undefined)
+ *   isMigratable: (boolean|undefined),
+ *   isVirtualCardEnrollmentEligible: (boolean|undefined),
+ *   isVirtualCardEnrolled: (boolean|undefined)
  * }}
  */
 chrome.autofillPrivate.AutofillMetadata;
diff --git a/third_party/inspector_protocol/lib/base_string_adapter_cc.template b/third_party/inspector_protocol/lib/base_string_adapter_cc.template
index 4bb10dc..6c314d1 100644
--- a/third_party/inspector_protocol/lib/base_string_adapter_cc.template
+++ b/third_party/inspector_protocol/lib/base_string_adapter_cc.template
@@ -52,7 +52,7 @@
     return protocol::StringValue::create(value.GetString());
   if (value.is_list()) {
     auto result = protocol::ListValue::create();
-    for (const base::Value& item : value.GetList()) {
+    for (const base::Value& item : value.GetListDeprecated()) {
       if (auto converted = toProtocolValue(item, depth - 1)) {
         result->pushValue(std::move(converted));
       }
diff --git a/third_party/webrtc_overrides/BUILD.gn b/third_party/webrtc_overrides/BUILD.gn
index 61039e44..e0b4440 100644
--- a/third_party/webrtc_overrides/BUILD.gn
+++ b/third_party/webrtc_overrides/BUILD.gn
@@ -49,6 +49,7 @@
   "//third_party/webrtc/api/audio_codecs/opus:audio_encoder_multiopus",
   "//third_party/webrtc/api/audio_codecs/opus:audio_encoder_opus",
   "//third_party/webrtc/api/rtc_event_log:rtc_event_log_factory",
+  "//third_party/webrtc/api/task_queue:task_queue",
   "//third_party/webrtc/api/transport:enums",
   "//third_party/webrtc/api/transport/rtp:rtp_source",
   "//third_party/webrtc/api/video:recordable_encoded_frame",
@@ -96,6 +97,8 @@
   "//third_party/webrtc/rtc_base:socket_address",
   "//third_party/webrtc/rtc_base:threading",
   "//third_party/webrtc/rtc_base:timeutils",
+  "//third_party/webrtc/rtc_base/system:rtc_export",
+  "//third_party/webrtc/rtc_base/task_utils:to_queued_task",
   "//third_party/webrtc/rtc_base/third_party/base64",
   "//third_party/webrtc/rtc_base/third_party/sigslot",
   "//third_party/webrtc/rtc_base/third_party/sigslot:sigslot",
@@ -216,11 +219,24 @@
     "//third_party/webrtc/api/task_queue",
     "//third_party/webrtc/rtc_base/system:rtc_export",
   ]
+}
 
-  # If you want to use a WebRTC task queue you may want to have access to
-  # webrtc::ToQueuedTask, but it has limited visibility within WebRTC so we
-  # depend on it publically here.
-  public_deps = [ "//third_party/webrtc/rtc_base/task_utils:to_queued_task" ]
+source_set("metronome_like_task_queue_test") {
+  configs += webrtc_configs
+  public_configs = webrtc_public_configs
+
+  testonly = true
+
+  sources = [
+    "test/metronome_like_task_queue_test.cc",
+    "test/metronome_like_task_queue_test.h",
+  ]
+  deps = [
+    ":webrtc_component",
+    "//base",
+    "//base/test:test_support",
+    "//testing/gtest:gtest",
+  ]
 }
 
 source_set("system_time") {
diff --git a/third_party/webrtc_overrides/test/DEPS b/third_party/webrtc_overrides/test/DEPS
new file mode 100644
index 0000000..d2f34d2d
--- /dev/null
+++ b/third_party/webrtc_overrides/test/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  '+testing',
+]
diff --git a/third_party/webrtc_overrides/test/metronome_like_task_queue_test.cc b/third_party/webrtc_overrides/test/metronome_like_task_queue_test.cc
new file mode 100644
index 0000000..ddbec8e
--- /dev/null
+++ b/third_party/webrtc_overrides/test/metronome_like_task_queue_test.cc
@@ -0,0 +1,180 @@
+// Copyright 2022 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/webrtc_overrides/test/metronome_like_task_queue_test.h"
+
+#include <functional>
+#include <memory>
+
+#include "base/time/time.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/api/task_queue/task_queue_factory.h"
+
+namespace blink {
+
+using ::testing::ElementsAre;
+
+TEST_P(MetronomeLikeTaskQueueTest, PostTaskRunsPriorToTick) {
+  auto task_queue = task_queue_factory_->CreateTaskQueue(
+      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
+
+  bool did_run = false;
+  task_queue->PostTask(webrtc::ToQueuedTask([&did_run]() { did_run = true; }));
+
+  EXPECT_FALSE(did_run);
+  task_environment_.FastForwardBy(base::Nanoseconds(1));
+  EXPECT_TRUE(did_run);
+}
+
+TEST_P(MetronomeLikeTaskQueueTest, NormalPriorityDelayedTasksRunOnTicks) {
+  auto task_queue = task_queue_factory_->CreateTaskQueue(
+      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
+
+  int task_run_counter = 0;
+
+  // Delay task until next tick.
+  task_queue->PostDelayedTask(
+      webrtc::ToQueuedTask([&task_run_counter]() { ++task_run_counter; }),
+      metronome_tick_.InMilliseconds());
+  EXPECT_EQ(task_run_counter, 0);
+  task_environment_.FastForwardBy(metronome_tick_);
+  EXPECT_EQ(task_run_counter, 1);
+
+  // Delay half a tick. A full tick must pass before it runs.
+  task_queue->PostDelayedTask(
+      webrtc::ToQueuedTask([&task_run_counter]() { ++task_run_counter; }),
+      (metronome_tick_ / 2).InMilliseconds());
+  task_environment_.FastForwardBy(metronome_tick_ - base::Milliseconds(1));
+  EXPECT_EQ(task_run_counter, 1);
+  task_environment_.FastForwardBy(base::Milliseconds(1));
+  EXPECT_EQ(task_run_counter, 2);
+
+  // Delay several ticks.
+  task_queue->PostDelayedTask(
+      webrtc::ToQueuedTask([&task_run_counter]() { ++task_run_counter; }),
+      (metronome_tick_ * 3).InMilliseconds());
+  task_environment_.FastForwardBy(metronome_tick_ * 2);
+  EXPECT_EQ(task_run_counter, 2);
+  task_environment_.FastForwardBy(metronome_tick_);
+  EXPECT_EQ(task_run_counter, 3);
+}
+
+TEST_P(MetronomeLikeTaskQueueTest,
+       NormalPriorityHighPrecisionDelayedTasksRunOutsideTicks) {
+  auto task_queue = task_queue_factory_->CreateTaskQueue(
+      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
+
+  bool did_run = false;
+  task_queue->PostDelayedHighPrecisionTask(
+      webrtc::ToQueuedTask([&did_run]() { did_run = true; }),
+      /*milliseconds=*/1);
+
+  EXPECT_FALSE(did_run);
+  task_environment_.FastForwardBy(base::Milliseconds(1));
+  EXPECT_TRUE(did_run);
+}
+
+TEST_P(MetronomeLikeTaskQueueTest, CanDeleteTaskQueueWhileTasksAreInFlight) {
+  auto task_queue = task_queue_factory_->CreateTaskQueue(
+      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
+
+  bool did_run_post_task = false;
+  task_queue->PostTask(webrtc::ToQueuedTask(
+      [&did_run_post_task]() { did_run_post_task = true; }));
+  bool did_run_low_precision_delay_task = false;
+  task_queue->PostDelayedTask(
+      webrtc::ToQueuedTask([&did_run_low_precision_delay_task]() {
+        did_run_low_precision_delay_task = true;
+      }),
+      /*milliseconds=*/1);
+  bool did_run_high_precision_delay_task = false;
+  task_queue->PostDelayedHighPrecisionTask(
+      webrtc::ToQueuedTask([&did_run_high_precision_delay_task]() {
+        did_run_high_precision_delay_task = true;
+      }),
+      /*milliseconds=*/1);
+
+  EXPECT_FALSE(did_run_post_task);
+  EXPECT_FALSE(did_run_low_precision_delay_task);
+  EXPECT_FALSE(did_run_high_precision_delay_task);
+  task_queue.reset();
+
+  // The PostTask is executed, but not the delayed tasks.
+  EXPECT_TRUE(did_run_post_task);
+  EXPECT_FALSE(did_run_low_precision_delay_task);
+  EXPECT_FALSE(did_run_high_precision_delay_task);
+
+  // The delayed tasks never run because they have been cancelled.
+  task_environment_.FastForwardBy(metronome_tick_);
+  EXPECT_FALSE(did_run_low_precision_delay_task);
+  EXPECT_FALSE(did_run_high_precision_delay_task);
+}
+
+TEST_P(MetronomeLikeTaskQueueTest, DelayedTasksRunInOrder) {
+  auto task_queue = task_queue_factory_->CreateTaskQueue(
+      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
+
+  constexpr uint32_t kTime0Ms = 0;
+  constexpr uint32_t kTime1Ms = 1;
+  std::vector<std::string> run_tasks;
+
+  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
+                                run_tasks.emplace_back("Time0_First");
+                              }),
+                              kTime0Ms);
+  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
+                                run_tasks.emplace_back("Time1_First");
+                              }),
+                              kTime1Ms);
+  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
+                                run_tasks.emplace_back("Time1_Second");
+                              }),
+                              kTime1Ms);
+  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
+                                run_tasks.emplace_back("Time0_Second");
+                              }),
+                              kTime0Ms);
+  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
+                                run_tasks.emplace_back("Time0_Third");
+                              }),
+                              kTime0Ms);
+  task_queue->PostDelayedTask(webrtc::ToQueuedTask([&run_tasks]() {
+                                run_tasks.emplace_back("Time1_Third");
+                              }),
+                              kTime1Ms);
+  task_environment_.FastForwardBy(metronome_tick_);
+
+  EXPECT_THAT(run_tasks,
+              ElementsAre("Time0_First", "Time0_Second", "Time0_Third",
+                          "Time1_First", "Time1_Second", "Time1_Third"));
+}
+
+TEST_P(MetronomeLikeTaskQueueTest, DelayedTaskCanPostDelayedTask) {
+  auto task_queue = task_queue_factory_->CreateTaskQueue(
+      "MetronomeTestQueue", webrtc::TaskQueueFactory::Priority::NORMAL);
+
+  bool task0_ran = false;
+  bool task1_ran = false;
+
+  task_queue->PostDelayedTask(
+      webrtc::ToQueuedTask(
+          [tick = metronome_tick_, &task_queue, &task0_ran, &task1_ran]() {
+            task0_ran = true;
+            // Inception!
+            task_queue->PostDelayedTask(
+                webrtc::ToQueuedTask([&task1_ran]() { task1_ran = true; }),
+                tick.InMilliseconds());
+          }),
+      metronome_tick_.InMilliseconds());
+
+  task_environment_.FastForwardBy(metronome_tick_);
+  EXPECT_TRUE(task0_ran);
+  EXPECT_FALSE(task1_ran);
+  task_environment_.FastForwardBy(metronome_tick_);
+  EXPECT_TRUE(task0_ran);
+  EXPECT_TRUE(task1_ran);
+}
+
+}  // namespace blink
diff --git a/third_party/webrtc_overrides/test/metronome_like_task_queue_test.h b/third_party/webrtc_overrides/test/metronome_like_task_queue_test.h
new file mode 100644
index 0000000..f844cb8
--- /dev/null
+++ b/third_party/webrtc_overrides/test/metronome_like_task_queue_test.h
@@ -0,0 +1,43 @@
+// Copyright 2022 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_WEBRTC_OVERRIDES_TEST_METRONOME_LIKE_TASK_QUEUE_TEST_H_
+#define THIRD_PARTY_WEBRTC_OVERRIDES_TEST_METRONOME_LIKE_TASK_QUEUE_TEST_H_
+
+#include <functional>
+#include <memory>
+
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/api/task_queue/task_queue_factory.h"
+#include "third_party/webrtc/rtc_base/system/rtc_export.h"
+#include "third_party/webrtc/rtc_base/task_utils/to_queued_task.h"
+
+namespace blink {
+
+struct RTC_EXPORT MetronomeLikeTaskQueueTestParams {
+  std::function<std::unique_ptr<webrtc::TaskQueueFactory>()> task_queue_factory;
+  base::TimeDelta metronome_tick;
+};
+
+class RTC_EXPORT MetronomeLikeTaskQueueTest
+    : public ::testing::TestWithParam<MetronomeLikeTaskQueueTestParams> {
+ public:
+  MetronomeLikeTaskQueueTest()
+      : task_environment_(
+            base::test::TaskEnvironment::ThreadingMode::MULTIPLE_THREADS,
+            base::test::TaskEnvironment::TimeSource::MOCK_TIME),
+        task_queue_factory_(GetParam().task_queue_factory()),
+        metronome_tick_(GetParam().metronome_tick) {}
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
+  std::unique_ptr<webrtc::TaskQueueFactory> task_queue_factory_;
+  const base::TimeDelta metronome_tick_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_WEBRTC_OVERRIDES_TEST_METRONOME_LIKE_TASK_QUEUE_TEST_H_
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 3be1140..9eb4d5e 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -856,7 +856,7 @@
       'gpu-fyi-try-android-l-nexus-5-32': 'gpu_tests_android_release_trybot',
       'gpu-fyi-try-android-m-nexus-5x-64': 'gpu_tests_android_release_trybot_arm64',
       'gpu-fyi-try-android-m-nexus-9-64': 'gpu_tests_android_release_trybot_arm64',
-      'gpu-fyi-try-android-n-nvidia-shield-tv-64': 'gpu_tests_android_release_trybot_arm64',
+      'gpu-fyi-try-android-nvidia-shield-tv': 'gpu_tests_android_release_trybot',
       'gpu-fyi-try-android-p-pixel-2-32': 'gpu_tests_android_release_trybot',
       'gpu-fyi-try-android-r-pixel-4-32': 'gpu_tests_android_release_trybot',
       'gpu-fyi-try-android-pixel-6-64': 'gpu_tests_android_release_trybot_arm64',
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.android.json b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
index 1b511d80..cc2c207 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.android.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
@@ -1235,7 +1235,7 @@
       "use_static_angle": true
     }
   },
-  "gpu-fyi-try-android-n-nvidia-shield-tv-64": {
+  "gpu-fyi-try-android-nvidia-shield-tv": {
     "gn_args": {
       "blink_enable_generated_code_formatting": false,
       "dcheck_always_on": true,
@@ -1244,7 +1244,6 @@
       "is_debug": false,
       "proprietary_codecs": true,
       "symbol_level": 1,
-      "target_cpu": "arm64",
       "target_os": "android",
       "use_goma": true,
       "use_static_angle": true
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 31f87d5..6333489 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -11273,6 +11273,7 @@
   <int value="12" label="kTrustTokens"/>
   <int value="13" label="kConversions"/>
   <int value="14" label="kDeferredCookies"/>
+  <int value="15" label="kSharedStorage"/>
 </enum>
 
 <enum name="BrowsingInstancePluralityVisibilityState">
@@ -15326,6 +15327,8 @@
   <int value="37" label="HTTP/3 (draft-28)"/>
   <int value="38" label="HTTP/3 (draft-29)"/>
   <int value="39" label="HTTP/3 (T051)"/>
+  <int value="40" label="QUIC (RFC)"/>
+  <int value="41" label="QUICv2 (draft-01)"/>
 </enum>
 
 <enum name="ConnectionResult">
@@ -36516,7 +36519,7 @@
   <int value="3684" label="XRFrameGetDepthInformation"/>
   <int value="3685" label="XRCPUDepthInformationGetDepth"/>
   <int value="3686" label="XRCPUDepthInformationDataAttribute"/>
-  <int value="3687" label="InterestCohortAPI_interestCohort_Method"/>
+  <int value="3687" label="OBSOLETE_InterestCohortAPI_interestCohort_Method"/>
   <int value="3688"
       label="OBSOLETE_AddressSpaceLocalEmbeddedInPrivateSecureContext"/>
   <int value="3689"
@@ -37119,7 +37122,7 @@
   <int value="79" label="Gamepad"/>
   <int value="80" label="OTPCredentials"/>
   <int value="81" label="DisplayCapture"/>
-  <int value="82" label="InterestCohort"/>
+  <int value="82" label="Deprecated: InterestCohort"/>
   <int value="83" label="SharedAutofill"/>
   <int value="84" label="DirectSockets"/>
   <int value="85" label="ClientHintPrefersColorScheme"/>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml
index c88937e..1b8122a 100644
--- a/tools/metrics/histograms/metadata/media/histograms.xml
+++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -2883,7 +2883,7 @@
 </histogram>
 
 <histogram name="Media.MediaFoundation.VideoColorSpace.PrimaryID"
-    enum="VideoColorSpace.PrimaryID" expires_after="M98">
+    enum="VideoColorSpace.PrimaryID" expires_after="2022-08-30">
   <owner>dalecurtis@chromium.org</owner>
   <owner>macrabil@microsoft.com</owner>
   <owner>media-dev@chromium.org</owner>
@@ -2894,7 +2894,7 @@
 </histogram>
 
 <histogram name="Media.MediaFoundation.VideoColorSpace.TransferID"
-    enum="VideoColorSpace.TransferID" expires_after="M98">
+    enum="VideoColorSpace.TransferID" expires_after="2022-08-30">
   <owner>dalecurtis@chromium.org</owner>
   <owner>macrabil@microsoft.com</owner>
   <owner>media-dev@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
index c0e53a0b..d4896e9 100644
--- a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
@@ -451,6 +451,17 @@
   <token key="SignalType" variants="SignalType"/>
 </histogram>
 
+<histogram name="SegmentationPlatform.StructuredMetrics.TooManyTensors.Count"
+    units="tensors" expires_after="2022-10-01">
+  <owner>qinmin@chromium.org</owner>
+  <owner>chrome-segmentation-platform@google.com</owner>
+  <summary>
+    Records the number of input tensors that are causing structured metrics to
+    fail to upload due to input size. Recorded immediately after the failure
+    when an ML model is reporting structured metrics.
+  </summary>
+</histogram>
+
 <histogram name="SegmentationPlatform.{BooleanModel}.SegmentSwitched"
     enum="SegmentationBooleanSegmentSwitch" expires_after="2022-08-01">
   <owner>shaktisahu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/storage/histograms.xml b/tools/metrics/histograms/metadata/storage/histograms.xml
index db3aa4a..cb7c6f6 100644
--- a/tools/metrics/histograms/metadata/storage/histograms.xml
+++ b/tools/metrics/histograms/metadata/storage/histograms.xml
@@ -484,6 +484,33 @@
   </summary>
 </histogram>
 
+<histogram name="Storage.SharedStorage.Database.Destruction"
+    units="BooleanDestroyed" expires_after="2023-01-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Whether destruction was successful after a catastrophic error that occurred
+    in Shared Storage. Recorded by
+    SharedStorageDatabase::DatabaseErrorCallback() just after the SQLite
+    database called RazeAndClose() and then, if it was file-backed,
+    SharedStorageDatabase attempted to delete the file.
+  </summary>
+</histogram>
+
+<histogram name="Storage.SharedStorage.Database.Error" enum="SqliteErrorCode"
+    expires_after="2023-01-31">
+  <owner>cammie@chromium.org</owner>
+  <owner>yaoxia@chromium.org</owner>
+  <owner>chrome-ads-histograms@google.com</owner>
+  <summary>
+    Errors that occur in Shared Storage. Recorded by
+    SharedStorageDatabase::DatabaseErrorCallback() just before the SQLite
+    database determines whether the error is catastrophic and handles it
+    accordingly.
+  </summary>
+</histogram>
+
 <histogram name="Storage.StoragePressure.Bubble"
     enum="StoragePressureBubbleUserAction" expires_after="2022-03-12">
   <owner>jarrydg@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 9377db4..55e36db 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -16796,6 +16796,203 @@
   </metric>
 </event>
 
+<event name="Segmentation.ModelExecution">
+  <owner>nyquist@chromium.org</owner>
+  <owner>qinmin@chromium.org</owner>
+  <owner>ssid@chromium.org</owner>
+  <summary>
+    Input and output tensors for executing the ML model identified by
+    optimization targets and version. The input tensors can come from UMA or
+    UKM, with or without aggregation. Check model metadata for more information
+    about each tensor. Since all the ML tensors are floats, they are encoded
+    into int64 and will be decoded later during model training. This metric is
+    recorded after an ML model is executed, and the actual result is collected.
+  </summary>
+  <metric name="ActualResult">
+    <summary>
+      UMA or UKM metrics related to the features affected by the ML model, with
+      or without aggregation, after running the features as instructed by the ML
+      model. For example, this can be the 7 day total button clicks after an ML
+      model decides to show it. No encoding is used as this is normally a count
+      or sum of a UMA/UKM metric.
+    </summary>
+  </metric>
+  <metric name="Input0">
+    <summary>
+      The input tensor at index 0 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input1">
+    <summary>
+      The input tensor at index 1 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input10">
+    <summary>
+      The input tensor at index 10 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input11">
+    <summary>
+      The input tensor at index 11 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input12">
+    <summary>
+      The input tensor at index 12 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input13">
+    <summary>
+      The input tensor at index 13 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input14">
+    <summary>
+      The input tensor at index 14 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input15">
+    <summary>
+      The input tensor at index 15 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input16">
+    <summary>
+      The input tensor at index 16 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input17">
+    <summary>
+      The input tensor at index 17 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input18">
+    <summary>
+      The input tensor at index 18 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input19">
+    <summary>
+      The input tensor at index 19 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input2">
+    <summary>
+      The input tensor at index 2 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input20">
+    <summary>
+      The input tensor at index 20 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input21">
+    <summary>
+      The input tensor at index 21 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input22">
+    <summary>
+      The input tensor at index 22 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input23">
+    <summary>
+      The input tensor at index 23 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input24">
+    <summary>
+      The input tensor at index 24 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input25">
+    <summary>
+      The input tensor at index 25 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input26">
+    <summary>
+      The input tensor at index 26 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input27">
+    <summary>
+      The input tensor at index 27 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input28">
+    <summary>
+      The input tensor at index 28 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input29">
+    <summary>
+      The input tensor at index 29 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input3">
+    <summary>
+      The input tensor at index 3 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input4">
+    <summary>
+      The input tensor at index 4 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input5">
+    <summary>
+      The input tensor at index 5 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input6">
+    <summary>
+      The input tensor at index 6 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input7">
+    <summary>
+      The input tensor at index 7 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input8">
+    <summary>
+      The input tensor at index 8 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="Input9">
+    <summary>
+      The input tensor at index 9 represented in IEEE 754 double precision.
+    </summary>
+  </metric>
+  <metric name="ModelVersion">
+    <summary>
+      The version of the ML model used for execution. May not be a counter int.
+    </summary>
+  </metric>
+  <metric name="OptimizationTarget">
+    <summary>
+      The OptimizationTarget associated with the ML model. This is an enum for
+      classifying different ML models. It represents what an model is trying to
+      optimize.
+    </summary>
+  </metric>
+  <metric name="OutputDelaySec">
+    <summary>
+      The time from executing the model to when the UKM is recorded, in seconds.
+    </summary>
+  </metric>
+  <metric name="PredictionResult">
+    <summary>
+      Predicted result from executing the ML model. This is normally a score for
+      determining whether to show a particular feature. The value is a floating
+      number between 0 to 1 and encoded into IEEE 754 double precision here.
+    </summary>
+  </metric>
+</event>
+
 <event name="SharedHighlights.LinkGenerated">
   <owner>seblalancette@chromium.org</owner>
   <owner>chrome-creation@google.com</owner>
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 6c024e3..a25f76f 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -87,8 +87,6 @@
  <item id="external_policy_fetcher" added_in_milestone="62" content_hash_code="03d48984" os_list="linux,windows,chromeos" file_path="components/policy/core/common/cloud/external_policy_data_fetcher.cc" />
  <item id="favicon_loader" added_in_milestone="63" content_hash_code="0437e97c" os_list="linux,windows,chromeos,android" file_path="third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc" />
  <item id="file_system_connector_to_box" added_in_milestone="89" type="partial" second_id="oauth2_api_call_flow" content_hash_code="02587cd7" os_list="linux,windows,chromeos" semantics_fields="1,2,3,4,5" policy_fields="-1,3,4" file_path="chrome/browser/enterprise/connectors/file_system/box_api_call_flow.cc" />
- <item id="floc_event_logger" added_in_milestone="89" type="partial" second_id="floc_remote_permission_service" content_hash_code="040df9ca" os_list="linux,windows,chromeos,android" semantics_fields="2,3,4" policy_fields="3" file_path="chrome/browser/federated_learning/floc_event_logger.cc" />
- <item id="floc_remote_permission_service" added_in_milestone="85" type="completing" content_hash_code="0524bc76" os_list="linux,windows,chromeos,android" semantics_fields="1,5" policy_fields="1,2,4" file_path="chrome/browser/federated_learning/floc_remote_permission_service.cc" />
  <item id="ftl_messaging_client_ack_messages" added_in_milestone="86" content_hash_code="013f1ddb" os_list="linux,windows,chromeos,android" file_path="remoting/signaling/ftl_messaging_client.cc" />
  <item id="ftl_messaging_client_receive_messages" added_in_milestone="86" content_hash_code="022e9c77" os_list="linux,windows,chromeos,android" file_path="remoting/signaling/ftl_messaging_client.cc" />
  <item id="ftl_messaging_client_send_messages" added_in_milestone="86" content_hash_code="006864f3" os_list="linux,windows,chromeos,android" file_path="remoting/signaling/ftl_messaging_client.cc" />
@@ -227,7 +225,7 @@
  <item id="safe_browsing_v4_update" added_in_milestone="70" content_hash_code="00501369" os_list="linux,windows,chromeos,android" file_path="components/safe_browsing/core/browser/db/v4_update_protocol_manager.cc" />
  <item id="safe_search_service" added_in_milestone="70" content_hash_code="07995c17" os_list="linux,windows,chromeos,android" file_path="components/policy/content/safe_search_service.cc" />
  <item id="safety_check_update_connectivity" added_in_milestone="84" content_hash_code="01d8ad59" os_list="linux,windows,chromeos,android" file_path="components/safety_check/update_check_helper.cc" />
- <item id="sanitized_image_source" added_in_milestone="86" content_hash_code="025ed93b" os_list="linux,windows,chromeos" file_path="chrome/browser/ui/webui/sanitized_image_source.cc" />
+ <item id="sanitized_image_source" added_in_milestone="86" content_hash_code="039309ce" os_list="linux,windows,chromeos" file_path="chrome/browser/ui/webui/sanitized_image_source.cc" />
  <item id="save_file_manager" added_in_milestone="62" content_hash_code="03610e73" os_list="linux,windows,chromeos,android" file_path="content/browser/download/save_file_manager.cc" />
  <item id="sct_auditing" added_in_milestone="87" content_hash_code="0298c98f" os_list="linux,windows,chromeos,android" file_path="chrome/browser/ssl/sct_reporting_service.cc" />
  <item id="search_prefetch_service" added_in_milestone="88" content_hash_code="077746c6" os_list="windows,linux,chromeos,android" file_path="chrome/browser/prefetch/search_prefetch/base_search_prefetch_request.cc" />
diff --git a/tools/traffic_annotation/summary/grouping.xml b/tools/traffic_annotation/summary/grouping.xml
index 858e79d6..a1f74b83b 100644
--- a/tools/traffic_annotation/summary/grouping.xml
+++ b/tools/traffic_annotation/summary/grouping.xml
@@ -291,9 +291,6 @@
     <sender name="Conversion Measurements">
       <traffic_annotation unique_id="conversion_measurement_report"/>
     </sender>
-    <sender name="Federated Learning of Cohorts (FLoC)">
-      <traffic_annotation unique_id="floc_event_logger"/>
-    </sender>
     <sender name="Aggregation Service">
       <traffic_annotation unique_id="aggregation_service_helper_keys"/>
       <traffic_annotation unique_id="aggregation_service_report"/>
diff --git a/tools/typescript/definitions/autofill_private.d.ts b/tools/typescript/definitions/autofill_private.d.ts
index 42403f28..a3fe0e9 100644
--- a/tools/typescript/definitions/autofill_private.d.ts
+++ b/tools/typescript/definitions/autofill_private.d.ts
@@ -30,6 +30,8 @@
         isLocal?: boolean;
         isCached?: boolean;
         isMigratable?: boolean;
+        isVirtualCardEnrollmentEligible?: boolean;
+        isVirtualCardEnrolled?: boolean;
       }
 
       export interface AddressEntry {
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc
index 5cbda14..b0f06a0 100644
--- a/ui/accessibility/ax_node_position_unittest.cc
+++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -9106,6 +9106,48 @@
 }
 
 TEST_F(AXPositionTest,
+       AsLeafTextPositionBeforeAndAfterCharacterWithInvalidPosition) {
+  AXNodeData root_data;
+  root_data.id = 1;
+  root_data.role = ax::mojom::Role::kRootWebArea;
+
+  AXNodeData text_data;
+  text_data.id = 2;
+  text_data.role = ax::mojom::Role::kStaticText;
+  text_data.SetName("some text");
+
+  root_data.child_ids = {text_data.id};
+  SetTree(CreateAXTree({root_data, text_data}));
+
+  // Create a text position at MaxTextOffset.
+  TestPositionType text_position = AXNodePosition::CreateTextPosition(
+      GetTreeID(), text_data.id, 9 /* text_offset */,
+      ax::mojom::TextAffinity::kDownstream);
+  ASSERT_NE(nullptr, text_position);
+  EXPECT_TRUE(text_position->IsTextPosition());
+  EXPECT_TRUE(text_position->IsValid());
+  EXPECT_EQ(9, text_position->text_offset());
+
+  // Now make a change to shorten MaxTextOffset. Ensure that this position is
+  // invalid.
+  text_data.SetName("some tex");
+  AXTreeUpdate shorten_text_update;
+  shorten_text_update.nodes = {text_data};
+  ASSERT_TRUE(GetTree()->Unserialize(shorten_text_update));
+  EXPECT_FALSE(text_position->IsValid());
+
+  // Ensure that |AsLeafTextPositionBeforeCharacter| returns a null position.
+  TestPositionType text_position_before =
+      text_position->AsLeafTextPositionBeforeCharacter();
+  EXPECT_TRUE(text_position_before->IsNullPosition());
+
+  // Likewise for |AsLeafTextPositionAfterCharacter|.
+  TestPositionType text_position_after =
+      text_position->AsLeafTextPositionAfterCharacter();
+  EXPECT_TRUE(text_position_after->IsNullPosition());
+}
+
+TEST_F(AXPositionTest,
        AsLeafTextPositionBeforeAndAfterCharacterAtInvalidGraphemeBoundary) {
   std::vector<int> text_offsets;
   SetTree(CreateMultilingualDocument(&text_offsets));
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h
index 9aec585..07fd92a 100644
--- a/ui/accessibility/ax_position.h
+++ b/ui/accessibility/ax_position.h
@@ -2568,6 +2568,14 @@
       return Clone();
 
     AXPositionInstance text_position = AsTextPosition();
+    // The following situation should not be possible but there are existing
+    // crashes in the field.
+    //
+    // TODO(nektar): Remove this workaround as soon as the source of the bug
+    // is identified.
+    if (text_position->text_offset_ > text_position->MaxTextOffset())
+      return CreateNullPosition();
+
     // In case the input affinity is upstream, reset it to downstream.
     //
     // This is to ensure that when we find the equivalent leaf text position, it
diff --git a/ui/accessibility/extensions/caretbrowsing/caretbrowsing.js b/ui/accessibility/extensions/caretbrowsing/caretbrowsing.js
index 38f293a..6796fd2 100644
--- a/ui/accessibility/extensions/caretbrowsing/caretbrowsing.js
+++ b/ui/accessibility/extensions/caretbrowsing/caretbrowsing.js
@@ -122,28 +122,29 @@
 class CaretBrowsing {
   constructor() {
     /**
-     * Keep it enabled even when flipped off (for the options page)?
+     * Tracks whether to keep caret browsing enabled on this page even when it's
+     * flipped off. This is used on the options page.
      * @type {boolean}
      */
     this.forceEnabled = false;
 
     /**
-     * Is this window / iframe focused? We won't show the caret if not,
-     * especially so that carets aren't shown in two iframes of the same
-     * tab.
+     * Tracks whether this window / iframe is focused. The caret isn't shown on
+     * pages that are not focused, which is especially important so that carets
+     * aren't shown in two iframes of the same tab.
      * @type {boolean}
      */
     this.isWindowFocused = false;
 
     /**
-     * Is the caret actually visible? This is true only if Storage.enabled and
-     * isWindowFocused are both true.
+     * Tracks whether the caret is actually visible. This is true only if
+     * Storage.enabled and this.isWindowFocused are both true.
      * @type {boolean}
      */
     this.isCaretVisible = false;
 
     /**
-     * The actual caret element, an absolute-positioned flashing line.
+     * The actual caret HTML element, an absolute-positioned flashing line.
      * @type {Element}
      */
     this.caretElement;
@@ -173,20 +174,20 @@
     this.caretHeight = 0;
 
     /**
-     * The foreground color.
+     * The caret's foreground color.
      * @type {string}
      */
     this.caretForeground = '#000';
 
     /**
-     * The background color.
+     * The caret's background color.
      * @type {string}
      */
     this.caretBackground = '#fff';
 
     /**
-     * Is the selection collapsed, i.e. are the start and end locations
-     * the same? If so, our blinking caret image is shown; otherwise
+     * Tracks whether the selection is collapsed, i.e. are the start and end
+     * locations the same? If so, our blinking caret image is shown; otherwise
      * the Chrome selection is shown.
      * @type {boolean}
      */
@@ -195,7 +196,7 @@
     /**
      * The id returned by window.setInterval for our blink function, so
      * we can cancel it when caret browsing is disabled.
-     * @type {number?}
+     * @type {?number}
      */
     this.blinkFunctionId = null;
 
@@ -207,7 +208,7 @@
      * so that the x position doesn't drift as you move throughout lines, but
      * stays as close as possible to the initial position. This is reset when
      * moving left or right or clicking.
-     * @type {number?}
+     * @type {?number}
      */
     this.targetX = null;
 
@@ -218,7 +219,7 @@
     this.blinkFlag = true;
 
     /**
-     * Whether or not we're on a Mac - affects modifier keys.
+     * Whether or not we're on a Mac - which affects modifier keys.
      * @type {boolean}
      */
     this.isMac = (navigator.appVersion.indexOf("Mac") != -1);
diff --git a/ui/accessibility/platform/ax_platform_node_cocoa.mm b/ui/accessibility/platform/ax_platform_node_cocoa.mm
index 3fcfc92..db54f8e7 100644
--- a/ui/accessibility/platform/ax_platform_node_cocoa.mm
+++ b/ui/accessibility/platform/ax_platform_node_cocoa.mm
@@ -1539,12 +1539,42 @@
   if (selector == @selector(setAccessibilityFocused:))
     return _node->HasState(ax::mojom::State::kFocusable);
 
-  if (selector == @selector(setAccessibilityValue:) &&
-      _node->GetRole() == ax::mojom::Role::kTab) {
-    // Tabs use the radio button role on Mac, so they are selected by calling
-    // setSelected on an individual tab, rather than by setting the selected
-    // element on the tabstrip as a whole.
-    return !_node->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected);
+  if (selector == @selector(setAccessibilityValue:)) {
+    switch (_node->GetRole()) {
+      case ax::mojom::Role::kSlider:
+        // When VoiceOver performs an increment/decrement action, it immediately
+        // calls upon success of the action the selector setAccessibilityValue
+        // on the slider that was just updated. The value passed to this
+        // function is always equals to 5% of the slider's value range, so
+        // actually setting that value to our slider would:
+        //   1. render the increment/decrement action performed a moment before
+        //      useless as it would override the modified value;
+        //   2. make the slider value stuck in place, at 5% of its range.
+        //
+        // I haven't found much on the topic online, so the following is at best
+        // a conjecture: I believe that VoiceOver "suggests" us to
+        // increment/decrement the value by 5%. There might be a setting I'm not
+        // aware of that allows the VO users to modify this value by a different
+        // one, which would allow them to always increment/decrement sliders by
+        // the same amount on all apps.
+        //
+        // However, in Chromium, we handle the increment and decrement actions
+        // on the blink side and the step value is computed over there. That
+        // way, the experience for changing the value of a slider by increments
+        // is the same for all different inputs: whether it's the keyboard arrow
+        // keys, an AT, etc.
+        //
+        // TL;DR: setAccessibilityValue, when called on sliders, is breaking our
+        // increment and decrement AX actions, so don't allow it.
+        return NO;
+      case ax::mojom::Role::kTab:
+        // Tabs use the radio button role on Mac, so they are selected by
+        // calling setSelected on an individual tab, rather than by setting the
+        // selected element on the tabstrip as a whole.
+        return !_node->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected);
+      default:
+        break;
+    }
   }
 
   // Don't allow calling AX setters on disabled elements.
diff --git a/ui/accessibility/platform/inspect/ax_call_statement_invoker_mac.mm b/ui/accessibility/platform/inspect/ax_call_statement_invoker_mac.mm
index 7c56dd54..7bcca03 100644
--- a/ui/accessibility/platform/inspect/ax_call_statement_invoker_mac.mm
+++ b/ui/accessibility/platform/inspect/ax_call_statement_invoker_mac.mm
@@ -221,10 +221,45 @@
   // protocols if the object responds to a corresponding selector. Ignore all
   // other selectors the object may respond to because it exposes unwanted
   // NSAccessibility attributes listed in default filters as a side effect.
-  if (base::StartsWith(property_node.name_or_value, "accessibility") ||
-      base::StartsWith(property_node.name_or_value, "isAccessibility")) {
+  //
+  // Methods whose names start with "isAccessibility" returns a BOOL, so we
+  // need to handle the returned value differently than methods whose return
+  // types are id.
+  if (base::StartsWith(property_node.name_or_value, "isAccessibility")) {
+    absl::optional<SEL> optional_arg_selector;
+    std::string selector_string = property_node.name_or_value;
+    // In some cases, we might want to pass a SEL as argument instead of an id.
+    // When an argument is prefixed with "@SEL:", transform the string into a
+    // valid SEL to pass to the main selector.
+    if (property_node.arguments.size() == 1 &&
+        base::StartsWith(property_node.arguments[0].name_or_value, "@SEL:")) {
+      optional_arg_selector = NSSelectorFromString(base::SysUTF8ToNSString(
+          property_node.arguments[0].name_or_value.substr(5)));
+      selector_string += ":";
+    }
+
+    SEL selector =
+        NSSelectorFromString(base::SysUTF8ToNSString(selector_string));
+    if (![target respondsToSelector:selector])
+      return AXOptionalNSObject::Error();
+
+    NSInvocation* invocation = [NSInvocation
+        invocationWithMethodSignature:
+            [[target class] instanceMethodSignatureForSelector:selector]];
+    [invocation setSelector:selector];
+    [invocation setTarget:target];
+    if (optional_arg_selector) {
+      // The target is at index 0 and the selector at index 1, so arguments
+      // start at index 2.
+      [invocation setArgument:&*optional_arg_selector atIndex:2];
+    }
+    [invocation invoke];
+    BOOL return_value;
+    [invocation getReturnValue:&return_value];
+    return AXOptionalNSObject([NSNumber numberWithBool:return_value]);
+  } else if (base::StartsWith(property_node.name_or_value, "accessibility")) {
     if (property_node.arguments.size() == 1) {
-      auto optional_id =
+      absl::optional<id> optional_id =
           PerformAXSelector(target, property_node.name_or_value,
                             property_node.arguments[0].name_or_value);
       if (optional_id) {
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html
index fb612a6..4308ebc 100644
--- a/ui/file_manager/file_manager/main.html
+++ b/ui/file_manager/file_manager/main.html
@@ -39,21 +39,6 @@
           --cr-input-min-height: 32px;
           width: 100%;
         }
-
-        paper-progress {
-          --paper-progress-active-color: rgb(26, 194, 34);
-        }
-
-        body.check-select .dialog-header files-toggle-ripple {
-          --files-toggle-ripple-bg-color: black;
-          --files-toggle-ripple-activated-bg-color: black;
-          --files-toggle-ripple-activated-opacity: 0.08;
-        }
-
-        body.check-select .dialog-header files-ripple {
-          --files-ripple-bg-color: black;
-        }
-
       </style>
     </custom-style>
 
@@ -523,7 +508,6 @@
                 <div class="detail-table" id="detail-table" tabindex="0">
                 </div>
                 <grid class="thumbnail-grid" tabindex="0" hidden></grid>
-                <paper-progress class="loading-indicator" indeterminate hidden></paper-progress>
                 <files-spinner class="loading-indicator" hidden></files-spinner>
                 <div class="drive-welcome page"></div>
               </div>
diff --git a/ui/webui/resources/images/200-logo_googleg.png b/ui/webui/resources/images/200-logo_googleg.png
deleted file mode 100644
index 9ace71c..0000000
--- a/ui/webui/resources/images/200-logo_googleg.png
+++ /dev/null
Binary files differ
diff --git a/ui/webui/resources/images/BUILD.gn b/ui/webui/resources/images/BUILD.gn
index 8d44ce3..f01ceb2 100644
--- a/ui/webui/resources/images/BUILD.gn
+++ b/ui/webui/resources/images/BUILD.gn
@@ -44,7 +44,6 @@
 
   if (!is_android && !is_ios) {
     input_files += [
-      "200-logo_googleg.png",
       "arrow_down.svg",
       "arrow_right.svg",
       "business.svg",