diff --git a/DEPS b/DEPS
index c88905a..c0f7738 100644
--- a/DEPS
+++ b/DEPS
@@ -313,11 +313,11 @@
   # 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': '6f7f7fc9a15d3d026dfb83127d7696384a260453',
+  'v8_revision': 'd8629e1b3fd3f577927bc834b67b7b67daddd471',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '6b89950496d124a45f026569183fa7083874fb15',
+  'angle_revision': '9a7e8b7bb17fdd3c88c3b1f26f0c605135654ee0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -380,11 +380,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '96c026ec93f9db606de6421c6ec970666f583581',
+  'catapult_revision': '84fb1a2dd0db549933ae487a763ce77d6bcb171a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling chromium_variations
   # and whatever else without interference from each other.
-  'chromium_variations_revision': '769b143ec5dfc2af98d14e3fed7bd0f1df01927f',
+  'chromium_variations_revision': '09c35745a7a4fd1be89f5f2988d8333925a97cb1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # and whatever else without interference from each other.
@@ -400,7 +400,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': '921aae6ff160beed8abea8959036b4f0ba1eed6a',
+  'devtools_frontend_revision': 'fd66b840a076b7c161543dc94828ee2ce0bcc4c1',
   # 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.
@@ -824,7 +824,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '9198f75e85bd3e2feed339e5ed10d04e3fb76446',
+    '20d5912ad65aa985382a75f6883945a2bb40c79a',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -833,7 +833,7 @@
   },
 
   'src/ios/third_party/earl_grey2/src': {
-      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'b089cf61fdc4829854190ab753167a8f4179380a',
+      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '2afe6d25f15c122be700d7e693cd095f46495a69',
       'condition': 'checkout_ios',
   },
 
@@ -1224,7 +1224,7 @@
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'b8b21fe11c921d47a352bad33425a50ea3c7df64',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '108ae7ce925d5b6a4691eee6f6e5bafe9e41b8bc',
     'condition': 'checkout_src_internal',
   },
 
@@ -1689,7 +1689,7 @@
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '86ba297f4358f76eced618085b9aa669446a6c51',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'ed90e2735442263d54f02f2aa7410762f653d9c8',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1779,7 +1779,7 @@
     Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + 'c9f9edf6d75bb065fa47468bf035e051a57bec7c',
 
   'src/third_party/sqlite/src':
-    Var('chromium_git') + '/chromium/deps/sqlite.git' + '@' + 'ca75d938c18c99dc33b769fbdac8fc4c71befa33',
+    Var('chromium_git') + '/chromium/deps/sqlite.git' + '@' + 'a7a54e1dd9b6124c725a35552d48d6ce0e3c1ef9',
 
   'src/third_party/sqlite4java': {
       'packages': [
@@ -1874,7 +1874,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'f413d3474963ae2e63a7ba9580709b3c7180f9e8',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '80056062f5066192fc602eb06bd47e4570ee766b',
+    Var('webrtc_git') + '/src.git' + '@' + 'bd396fdffae452216e1984dec3cea73937192479',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
diff --git a/WATCHLISTS b/WATCHLISTS
index a2d7696b..9b2b9eb 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1073,7 +1073,7 @@
       'filepath': 'chrome/renderer/media/.*key_system|' \
                   'chrome/browser/media/.*(cdm|encrypted)|' \
                   'components/cdm/|' \
-                  'content/browser/media/cdm/|' \
+                  'content/browser/media/.*(cdm|key_system|media_license|encrypted)|' \
                   'media/base/android/.*drm|' \
                   'media/cdm/|' \
                   'third_party/widevine/cdm/'
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 4b8d06a6..57e5775 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -3797,6 +3797,7 @@
     "wm/window_positioner_unittest.cc",
     "wm/window_positioning_utils_unittest.cc",
     "wm/window_preview_view_unittest.cc",
+    "wm/window_restore/informed_restore_dialog_unittest.cc",
     "wm/window_restore/window_restore_controller_unittest.cc",
     "wm/window_state_unittest.cc",
     "wm/window_transient_descendant_iterator_unittest.cc",
diff --git a/ash/accessibility/sticky_keys/sticky_keys_overlay.cc b/ash/accessibility/sticky_keys/sticky_keys_overlay.cc
index 591cd6a2..9907e8f 100644
--- a/ash/accessibility/sticky_keys/sticky_keys_overlay.cc
+++ b/ash/accessibility/sticky_keys/sticky_keys_overlay.cc
@@ -14,6 +14,8 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
@@ -47,6 +49,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 //  StickyKeyOverlayLabel
 class StickyKeyOverlayLabel : public views::Label {
+  METADATA_HEADER(StickyKeyOverlayLabel, views::Label)
+
  public:
   explicit StickyKeyOverlayLabel(const std::string& key_name);
 
@@ -99,11 +103,16 @@
   SetFontList(font_list().DeriveWithStyle(style));
 }
 
+BEGIN_METADATA(StickyKeyOverlayLabel)
+END_METADATA
+
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
 //  StickyKeysOverlayView
 class StickyKeysOverlayView : public views::View {
+  METADATA_HEADER(StickyKeysOverlayView, views::View)
+
  public:
   StickyKeysOverlayView();
 
@@ -200,6 +209,9 @@
   modifier_label_map_[modifier] = label;
 }
 
+BEGIN_METADATA(StickyKeysOverlayView)
+END_METADATA
+
 ///////////////////////////////////////////////////////////////////////////////
 //  StickyKeysOverlay
 StickyKeysOverlay::StickyKeysOverlay() {
diff --git a/ash/app_menu/notification_item_view.cc b/ash/app_menu/notification_item_view.cc
index ba7a76a..c2c63494 100644
--- a/ash/app_menu/notification_item_view.cc
+++ b/ash/app_menu/notification_item_view.cc
@@ -5,6 +5,7 @@
 #include "ash/app_menu/notification_item_view.h"
 
 #include "ash/public/cpp/app_menu_constants.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image.h"
@@ -167,4 +168,7 @@
   }
 }
 
+BEGIN_METADATA(NotificationItemView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/app_menu/notification_item_view.h b/ash/app_menu/notification_item_view.h
index e5c26fe1..562e79de 100644
--- a/ash/app_menu/notification_item_view.h
+++ b/ash/app_menu/notification_item_view.h
@@ -11,6 +11,7 @@
 #include "ash/app_menu/app_menu_export.h"
 #include "ash/app_menu/notification_menu_view.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/animation/slide_out_controller_delegate.h"
 #include "ui/views/view.h"
 
@@ -35,6 +36,8 @@
 
 // The view which contains the details of a notification.
 class APP_MENU_EXPORT NotificationItemView : public views::View {
+  METADATA_HEADER(NotificationItemView, views::View)
+
  public:
   NotificationItemView(
       NotificationMenuView::Delegate* delegate,
diff --git a/ash/app_menu/notification_menu_header_view.cc b/ash/app_menu/notification_menu_header_view.cc
index 1492e46..fad09444 100644
--- a/ash/app_menu/notification_menu_header_view.cc
+++ b/ash/app_menu/notification_menu_header_view.cc
@@ -7,6 +7,7 @@
 #include "ash/public/cpp/app_menu_constants.h"
 #include "base/strings/string_number_conversions.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/label.h"
@@ -77,4 +78,7 @@
                       counter_preferred_size.height());
 }
 
+BEGIN_METADATA(NotificationMenuHeaderView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/app_menu/notification_menu_header_view.h b/ash/app_menu/notification_menu_header_view.h
index 3c3197d..04eeda3 100644
--- a/ash/app_menu/notification_menu_header_view.h
+++ b/ash/app_menu/notification_menu_header_view.h
@@ -6,6 +6,7 @@
 #define ASH_APP_MENU_NOTIFICATION_MENU_HEADER_VIEW_H_
 
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/view.h"
 
 namespace views {
@@ -17,6 +18,8 @@
 // The header view which shows the "Notifications" text and a counter to show
 // the number of notifications for this app.
 class NotificationMenuHeaderView : public views::View {
+  METADATA_HEADER(NotificationMenuHeaderView, views::View)
+
  public:
   NotificationMenuHeaderView();
 
diff --git a/ash/app_menu/notification_menu_view.cc b/ash/app_menu/notification_menu_view.cc
index bfd5e37..57e847ad 100644
--- a/ash/app_menu/notification_menu_view.cc
+++ b/ash/app_menu/notification_menu_view.cc
@@ -9,6 +9,7 @@
 #include "ash/app_menu/notification_overflow_view.h"
 #include "ash/public/cpp/app_menu_constants.h"
 #include "base/ranges/algorithm.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/menu_separator_types.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
@@ -179,4 +180,7 @@
                             &NotificationItemView::notification_id);
 }
 
+BEGIN_METADATA(NotificationMenuView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/app_menu/notification_menu_view.h b/ash/app_menu/notification_menu_view.h
index 8dfaebb..1425e06 100644
--- a/ash/app_menu/notification_menu_view.h
+++ b/ash/app_menu/notification_menu_view.h
@@ -10,6 +10,7 @@
 
 #include "ash/app_menu/app_menu_export.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/view.h"
 
 namespace message_center {
@@ -30,6 +31,8 @@
 // A view inserted into a container MenuItemView which shows a
 // NotificationItemView and a NotificationMenuHeaderView.
 class APP_MENU_EXPORT NotificationMenuView : public views::View {
+  METADATA_HEADER(NotificationMenuView, views::View)
+
  public:
   // API for child views to interact with the NotificationMenuController.
   class Delegate {
diff --git a/ash/app_menu/notification_overflow_view.cc b/ash/app_menu/notification_overflow_view.cc
index 96480d7d..74850eb 100644
--- a/ash/app_menu/notification_overflow_view.cc
+++ b/ash/app_menu/notification_overflow_view.cc
@@ -6,6 +6,8 @@
 
 #include "ash/public/cpp/app_menu_constants.h"
 #include "base/ranges/algorithm.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/menu_separator_types.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
@@ -42,6 +44,9 @@
 // The icon which represents a notification.
 class NotificationOverflowImageView
     : public message_center::ProportionalImageView {
+  METADATA_HEADER(NotificationOverflowImageView,
+                  message_center::ProportionalImageView)
+
  public:
   NotificationOverflowImageView(const ui::ImageModel& image,
                                 const std::string& notification_id)
@@ -63,6 +68,9 @@
   std::string const notification_id_;
 };
 
+BEGIN_METADATA(NotificationOverflowImageView)
+END_METADATA
+
 NotificationOverflowView::NotificationOverflowView()
     : separator_(AddChildView(std::make_unique<views::MenuSeparator>(
           ui::MenuSeparatorType::NORMAL_SEPARATOR))) {
@@ -148,4 +156,7 @@
   overflow_icon_->SetVisible(false);
 }
 
+BEGIN_METADATA(NotificationOverflowView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/app_menu/notification_overflow_view.h b/ash/app_menu/notification_overflow_view.h
index f059cb4..eb5b6a4 100644
--- a/ash/app_menu/notification_overflow_view.h
+++ b/ash/app_menu/notification_overflow_view.h
@@ -11,6 +11,8 @@
 #include "ash/app_menu/app_menu_export.h"
 #include "ash/app_menu/notification_item_view.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/views/view.h"
 
 namespace message_center {
 class ProportionalImageView;
@@ -24,6 +26,8 @@
 class NotificationOverflowImageView;
 
 class APP_MENU_EXPORT NotificationOverflowView : public views::View {
+  METADATA_HEADER(NotificationOverflowView, views::View)
+
  public:
   NotificationOverflowView();
 
diff --git a/ash/assistant/ui/main_stage/launcher_search_iph_view.cc b/ash/assistant/ui/main_stage/launcher_search_iph_view.cc
index 6d02f8a..916ee7a 100644
--- a/ash/assistant/ui/main_stage/launcher_search_iph_view.cc
+++ b/ash/assistant/ui/main_stage/launcher_search_iph_view.cc
@@ -176,7 +176,7 @@
         PillButton::Type::kDefaultLargeWithoutIcon);
   }
 
-  if (is_in_tablet_mode) {
+  if (is_in_tablet_mode || !show_assistant_chip_) {
     box_layout_view->SetBackground(views::CreateThemedRoundedRectBackground(
         kColorAshControlBackgroundColorInactive, kBackgroundRadiusTablet));
   } else {
diff --git a/ash/components/arc/arc_features.cc b/ash/components/arc/arc_features.cc
index 15fa8d7..59a40c0 100644
--- a/ash/components/arc/arc_features.cc
+++ b/ash/components/arc/arc_features.cc
@@ -409,5 +409,5 @@
 // top Android apps from being killed that result in bad user experience.
 BASE_FEATURE(kLmkPerceptibleMinStateUpdate,
              "ArcLmkPerceptibleMinStateUpdate",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 }  // namespace arc
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index b80d1ba..8bd8b2c 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -1324,7 +1324,7 @@
 // Enables a Files banner about Google One offer.
 BASE_FEATURE(kGoogleOneOfferFilesBanner,
              "GoogleOneOfferFilesBanner",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Enables editing with handwriting gestures within the virtual keyboard.
 BASE_FEATURE(kHandwritingGestureEditing,
diff --git a/ash/display/touch_calibrator_view.cc b/ash/display/touch_calibrator_view.cc
index fdac665..c2c7443 100644
--- a/ash/display/touch_calibrator_view.cc
+++ b/ash/display/touch_calibrator_view.cc
@@ -11,6 +11,8 @@
 #include "ash/shell.h"
 #include "base/memory/ptr_util.h"
 #include "ui/aura/window.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
@@ -125,6 +127,8 @@
 // element.
 class CircularThrobberView : public views::View,
                              public views::AnimationDelegateViews {
+  METADATA_HEADER(CircularThrobberView, views::View)
+
  public:
   CircularThrobberView(int width,
                        const SkColor& inner_circle_color,
@@ -205,7 +209,12 @@
   SchedulePaint();
 }
 
+BEGIN_METADATA(CircularThrobberView)
+END_METADATA
+
 class TouchTargetThrobberView : public CircularThrobberView {
+  METADATA_HEADER(TouchTargetThrobberView, CircularThrobberView)
+
  public:
   TouchTargetThrobberView(const gfx::Rect& bounds,
                           const SkColor& inner_circle_color,
@@ -251,6 +260,9 @@
   canvas->DrawImageInt(hand_icon_, horizontal_offset_, icon_width_);
 }
 
+BEGIN_METADATA(TouchTargetThrobberView)
+END_METADATA
+
 //   Circular      _________________________________
 //   Throbber     |                                 |
 //     View       |                                 |
@@ -268,6 +280,8 @@
 // align. The hint box has a label text and a sublabel text to assist the
 // user by informing them about the next step in the calibration process.
 class HintBox : public views::View {
+  METADATA_HEADER(HintBox, views::View)
+
  public:
   HintBox(const gfx::Rect& bounds, int border_radius);
   HintBox(const HintBox&) = delete;
@@ -405,7 +419,12 @@
                                   gfx::Canvas::NO_ELLIPSIS);
 }
 
+BEGIN_METADATA(HintBox)
+END_METADATA
+
 class CompletionMessageView : public views::View {
+  METADATA_HEADER(CompletionMessageView, views::View)
+
  public:
   CompletionMessageView(const gfx::Rect& bounds, const std::u16string& message);
   CompletionMessageView(const CompletionMessageView&) = delete;
@@ -458,6 +477,9 @@
       gfx::Canvas::TEXT_ALIGN_LEFT | gfx::Canvas::NO_SUBPIXEL_RENDERING);
 }
 
+BEGIN_METADATA(CompletionMessageView)
+END_METADATA
+
 // static
 views::UniqueWidgetPtr TouchCalibratorView::Create(
     const display::Display& target_display,
@@ -812,4 +834,7 @@
   }
 }
 
+BEGIN_METADATA(TouchCalibratorView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/display/touch_calibrator_view.h b/ash/display/touch_calibrator_view.h
index d8d43db1b..636ad92d 100644
--- a/ash/display/touch_calibrator_view.h
+++ b/ash/display/touch_calibrator_view.h
@@ -10,6 +10,7 @@
 #include "ash/ash_export.h"
 #include "base/memory/raw_ptr.h"
 #include "cc/paint/paint_flags.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/display/display.h"
 #include "ui/gfx/animation/linear_animation.h"
@@ -43,6 +44,8 @@
 class ASH_EXPORT TouchCalibratorView : public views::View,
                                        public views::AnimationDelegateViews,
                                        public ui::LayerAnimationObserver {
+  METADATA_HEADER(TouchCalibratorView, views::View)
+
  public:
   // Different states of |TouchCalibratorView| in order.
   enum State {
diff --git a/ash/game_dashboard/game_dashboard_controller.cc b/ash/game_dashboard/game_dashboard_controller.cc
index 0ead9dac..e2bae76 100644
--- a/ash/game_dashboard/game_dashboard_controller.cc
+++ b/ash/game_dashboard/game_dashboard_controller.cc
@@ -235,6 +235,7 @@
       if (!context) {
         context = std::make_unique<GameDashboardContext>(window);
         RefreshForGameControlsFlags(window);
+        delegate_->RecordGameWindowOpenedEvent(window);
       }
     } else if (prev_is_game_property) {
       // The window was a game, but NOT anymore. This can happen if the user
diff --git a/ash/game_dashboard/game_dashboard_delegate.h b/ash/game_dashboard/game_dashboard_delegate.h
index ef4dff3..fb5b479 100644
--- a/ash/game_dashboard/game_dashboard_delegate.h
+++ b/ash/game_dashboard/game_dashboard_delegate.h
@@ -9,6 +9,7 @@
 
 #include "ash/ash_export.h"
 #include "base/functional/callback.h"
+#include "ui/aura/window.h"
 
 namespace ash {
 
@@ -27,6 +28,9 @@
 
   // Gets the app name by `app_id`.
   virtual std::string GetArcAppName(const std::string& app_id) const = 0;
+
+  // Records `ScalableIph::kGameWindowOpened` event.
+  virtual void RecordGameWindowOpenedEvent(aura::Window* window) = 0;
 };
 
 }  // namespace ash
diff --git a/ash/game_dashboard/test_game_dashboard_delegate.cc b/ash/game_dashboard/test_game_dashboard_delegate.cc
index afe35ae..3293ba0 100644
--- a/ash/game_dashboard/test_game_dashboard_delegate.cc
+++ b/ash/game_dashboard/test_game_dashboard_delegate.cc
@@ -16,4 +16,7 @@
   return std::string();
 }
 
+void TestGameDashboardDelegate::RecordGameWindowOpenedEvent(
+    aura::Window* window) {}
+
 }  // namespace ash
diff --git a/ash/game_dashboard/test_game_dashboard_delegate.h b/ash/game_dashboard/test_game_dashboard_delegate.h
index 803d27a..cda9b73 100644
--- a/ash/game_dashboard/test_game_dashboard_delegate.h
+++ b/ash/game_dashboard/test_game_dashboard_delegate.h
@@ -23,6 +23,7 @@
   // ash::GameDashboardDelegate:
   void GetIsGame(const std::string& app_id, IsGameCallback callback) override;
   std::string GetArcAppName(const std::string& app_id) const override;
+  void RecordGameWindowOpenedEvent(aura::Window* window) override;
 };
 
 }  // namespace ash
diff --git a/ash/glanceables/common/glanceables_error_message_view.cc b/ash/glanceables/common/glanceables_error_message_view.cc
index 1fee4d8..a92bd58 100644
--- a/ash/glanceables/common/glanceables_error_message_view.cc
+++ b/ash/glanceables/common/glanceables_error_message_view.cc
@@ -13,6 +13,7 @@
 #include "ash/style/typography.h"
 #include "base/types/cxx23_to_underlying.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/gfx/text_constants.h"
@@ -39,6 +40,8 @@
 namespace ash {
 
 class DismissErrorLabelButton : public views::LabelButton {
+  METADATA_HEADER(DismissErrorLabelButton, views::LabelButton)
+
  public:
   explicit DismissErrorLabelButton(PressedCallback callback)
       : views::LabelButton(std::move(callback)) {
@@ -55,6 +58,9 @@
   ~DismissErrorLabelButton() override = default;
 };
 
+BEGIN_METADATA(DismissErrorLabelButton, views::LabelButton)
+END_METADATA
+
 GlanceablesErrorMessageView::GlanceablesErrorMessageView(
     views::Button::PressedCallback callback,
     const std::u16string& error_message) {
diff --git a/ash/glanceables/common/glanceables_list_footer_view.cc b/ash/glanceables/common/glanceables_list_footer_view.cc
index 8ff8bac..6694f8e 100644
--- a/ash/glanceables/common/glanceables_list_footer_view.cc
+++ b/ash/glanceables/common/glanceables_list_footer_view.cc
@@ -18,6 +18,7 @@
 #include "components/vector_icons/vector_icons.h"
 #include "ui/accessibility/ax_enums.mojom-shared.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/image_model.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
@@ -40,6 +41,8 @@
 constexpr int kSeeAllIconLabelSpacing = 6;
 
 class SeeAllButton : public views::LabelButton {
+  METADATA_HEADER(SeeAllButton, views::LabelButton)
+
  public:
   SeeAllButton(const std::u16string& see_all_accessible_name,
                base::RepeatingClosure on_see_all_pressed) {
@@ -65,6 +68,9 @@
   ~SeeAllButton() override = default;
 };
 
+BEGIN_METADATA(SeeAllButton)
+END_METADATA
+
 }  // namespace
 
 GlanceablesListFooterView::GlanceablesListFooterView(
@@ -107,7 +113,7 @@
                                  base::NumberToString16(total_items_count)));
 }
 
-BEGIN_METADATA(GlanceablesListFooterView, views::View)
+BEGIN_METADATA(GlanceablesListFooterView)
 END_METADATA
 
 }  // namespace ash
diff --git a/ash/glanceables/common/glanceables_list_footer_view.h b/ash/glanceables/common/glanceables_list_footer_view.h
index 170e5eb..a6f3462 100644
--- a/ash/glanceables/common/glanceables_list_footer_view.h
+++ b/ash/glanceables/common/glanceables_list_footer_view.h
@@ -23,9 +23,9 @@
 // Renders "Showing X out of Y" label and "See all" button. Used in classroom
 // and tasks bubbles.
 class ASH_EXPORT GlanceablesListFooterView : public views::FlexLayoutView {
- public:
-  METADATA_HEADER(GlanceablesListFooterView);
+  METADATA_HEADER(GlanceablesListFooterView, views::FlexLayoutView)
 
+ public:
   GlanceablesListFooterView(const std::u16string& see_all_accessible_name,
                             base::RepeatingClosure on_see_all_pressed);
   GlanceablesListFooterView(const GlanceablesListFooterView&) = delete;
diff --git a/ash/glanceables/common/glanceables_progress_bar_view.cc b/ash/glanceables/common/glanceables_progress_bar_view.cc
index 9cd6dd7..f5d0386 100644
--- a/ash/glanceables/common/glanceables_progress_bar_view.cc
+++ b/ash/glanceables/common/glanceables_progress_bar_view.cc
@@ -8,6 +8,7 @@
 
 #include "ash/glanceables/common/glanceables_view_id.h"
 #include "base/types/cxx23_to_underlying.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/size.h"
@@ -49,4 +50,7 @@
   progress_bar_->SetVisible(visible);
 }
 
+BEGIN_METADATA(GlanceablesProgressBarView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/glanceables/common/glanceables_progress_bar_view.h b/ash/glanceables/common/glanceables_progress_bar_view.h
index db708da8b8..a77def6d 100644
--- a/ash/glanceables/common/glanceables_progress_bar_view.h
+++ b/ash/glanceables/common/glanceables_progress_bar_view.h
@@ -7,6 +7,7 @@
 
 #include "ash/ash_export.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/layout/flex_layout_view.h"
 
 namespace views {
@@ -17,6 +18,8 @@
 
 // Container for infinite `views::ProgressBar` used in glanceables bubbles.
 class ASH_EXPORT GlanceablesProgressBarView : public views::FlexLayoutView {
+  METADATA_HEADER(GlanceablesProgressBarView, views::FlexLayoutView)
+
  public:
   GlanceablesProgressBarView();
   GlanceablesProgressBarView(const GlanceablesProgressBarView&) = delete;
diff --git a/ash/glanceables/tasks/glanceables_task_view.cc b/ash/glanceables/tasks/glanceables_task_view.cc
index 5782408..39d7283 100644
--- a/ash/glanceables/tasks/glanceables_task_view.cc
+++ b/ash/glanceables/tasks/glanceables_task_view.cc
@@ -25,6 +25,7 @@
 #include "base/types/cxx23_to_underlying.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/events/keycodes/keyboard_codes_posix.h"
@@ -103,6 +104,8 @@
 
 class TaskViewTextField : public views::Textfield,
                           public views::TextfieldController {
+  METADATA_HEADER(TaskViewTextField, views::Textfield)
+
  public:
   using OnFinishedEditingCallback =
       base::OnceCallback<void(const std::u16string& title)>;
@@ -147,9 +150,14 @@
   OnFinishedEditingCallback on_finished_editing_;
 };
 
+BEGIN_METADATA(TaskViewTextField)
+END_METADATA
+
 }  // namespace
 
 class GlanceablesTaskView::CheckButton : public views::ImageButton {
+  METADATA_HEADER(CheckButton, views::ImageButton)
+
  public:
   explicit CheckButton(PressedCallback pressed_callback)
       : views::ImageButton(std::move(pressed_callback)) {
@@ -196,7 +204,12 @@
   bool checked_ = false;
 };
 
+BEGIN_METADATA(GlanceablesTaskView, CheckButton, views::ImageButton)
+END_METADATA
+
 class GlanceablesTaskView::TaskTitleButton : public views::LabelButton {
+  METADATA_HEADER(TaskTitleButton, views::LabelButton)
+
  public:
   TaskTitleButton(const std::u16string& title, PressedCallback pressed_callback)
       : views::LabelButton(std::move(pressed_callback), title) {
@@ -231,6 +244,9 @@
   }
 };
 
+BEGIN_METADATA(GlanceablesTaskView, TaskTitleButton, views::LabelButton)
+END_METADATA
+
 GlanceablesTaskView::GlanceablesTaskView(
     const api::Task* task,
     MarkAsCompletedCallback mark_as_completed_callback,
diff --git a/ash/in_session_auth/auth_dialog_contents_view.cc b/ash/in_session_auth/auth_dialog_contents_view.cc
index ce24598..d0fc5bb 100644
--- a/ash/in_session_auth/auth_dialog_contents_view.cc
+++ b/ash/in_session_auth/auth_dialog_contents_view.cc
@@ -26,6 +26,8 @@
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/image_model.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/compositor/layer.h"
@@ -104,10 +106,14 @@
 
 // Consists of fingerprint icon view and a label.
 class AuthDialogContentsView::FingerprintView : public views::View {
+  METADATA_HEADER(FingerprintView, views::View)
+
  public:
   // Use a subclass that inherit views::Label so that GetAccessibleNodeData
   // override is respected.
   class FingerprintLabel : public views::Label {
+    METADATA_HEADER(FingerprintLabel, views::Label)
+
    public:
     // views::View
     void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
@@ -292,7 +298,17 @@
   base::OneShotTimer reset_state_;
 };
 
+BEGIN_METADATA(AuthDialogContentsView, FingerprintView, views::View)
+END_METADATA
+
+BEGIN_METADATA(AuthDialogContentsView::FingerprintView,
+               FingerprintLabel,
+               views::Label)
+END_METADATA
+
 class AuthDialogContentsView::TitleLabel : public views::Label {
+  METADATA_HEADER(TitleLabel, views::Label)
+
  public:
   TitleLabel() {
     SetSubpixelRenderingEnabled(false);
@@ -342,6 +358,9 @@
   bool is_showing_error_ = false;
 };
 
+BEGIN_METADATA(AuthDialogContentsView, TitleLabel, views::Label)
+END_METADATA
+
 AuthDialogContentsView::AuthDialogContentsView(
     uint32_t auth_methods,
     const std::string& origin_name,
@@ -711,4 +730,7 @@
   WebAuthNDialogController::Get()->OpenInSessionAuthHelpPage();
 }
 
+BEGIN_METADATA(AuthDialogContentsView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/in_session_auth/auth_dialog_contents_view.h b/ash/in_session_auth/auth_dialog_contents_view.h
index eb1b68b..5b26eea 100644
--- a/ash/in_session_auth/auth_dialog_contents_view.h
+++ b/ash/in_session_auth/auth_dialog_contents_view.h
@@ -10,6 +10,7 @@
 #include "ash/ash_export.h"
 #include "ash/public/cpp/login_types.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/view.h"
 
 namespace views {
@@ -29,6 +30,8 @@
 // Contains the debug views that allows the developer to interact with the
 // AuthDialogController.
 class AuthDialogContentsView : public views::View {
+  METADATA_HEADER(AuthDialogContentsView, views::View)
+
  public:
   // Flags which describe the set of currently visible auth methods.
   enum AuthMethods {
diff --git a/ash/lock_screen_action/lock_screen_action_background_view.cc b/ash/lock_screen_action/lock_screen_action_background_view.cc
index d284562..0fb57b2f 100644
--- a/ash/lock_screen_action/lock_screen_action_background_view.cc
+++ b/ash/lock_screen_action/lock_screen_action_background_view.cc
@@ -11,6 +11,8 @@
 #include "base/functional/callback.h"
 #include "base/i18n/rtl.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
@@ -26,6 +28,8 @@
 namespace ash {
 
 class LockScreenActionBackgroundView::NoteBackground : public views::View {
+  METADATA_HEADER(NoteBackground, views::View)
+
  public:
   explicit NoteBackground(views::InkDropObserver* observer)
       : observer_(observer) {
@@ -69,6 +73,9 @@
   raw_ptr<views::InkDropObserver, ExperimentalAsh> observer_;
 };
 
+BEGIN_METADATA(LockScreenActionBackgroundView, NoteBackground, views::View)
+END_METADATA
+
 LockScreenActionBackgroundView::LockScreenActionBackgroundView() {
   SetCanMaximize(true);
   SetCanFullscreen(true);
@@ -126,4 +133,7 @@
   return background_;
 }
 
+BEGIN_METADATA(LockScreenActionBackgroundView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/lock_screen_action/lock_screen_action_background_view.h b/ash/lock_screen_action/lock_screen_action_background_view.h
index 6b78433..0c7b8e9 100644
--- a/ash/lock_screen_action/lock_screen_action_background_view.h
+++ b/ash/lock_screen_action/lock_screen_action_background_view.h
@@ -8,6 +8,7 @@
 #include "ash/ash_export.h"
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/animation/ink_drop_observer.h"
 #include "ui/views/animation/ink_drop_state.h"
 #include "ui/views/widget/widget_delegate.h"
@@ -22,6 +23,8 @@
 class ASH_EXPORT LockScreenActionBackgroundView
     : public views::WidgetDelegateView,
       public views::InkDropObserver {
+  METADATA_HEADER(LockScreenActionBackgroundView, views::WidgetDelegateView)
+
  public:
   LockScreenActionBackgroundView();
 
diff --git a/ash/login/ui/access_code_input.cc b/ash/login/ui/access_code_input.cc
index 64bd7e66..618cdb88 100644
--- a/ash/login/ui/access_code_input.cc
+++ b/ash/login/ui/access_code_input.cc
@@ -15,6 +15,7 @@
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/color/color_id.h"
 #include "ui/compositor/layer.h"
@@ -42,6 +43,9 @@
 constexpr int kAccessCodeBetweenInputFieldsGapDp = 8;
 }  // namespace
 
+BEGIN_METADATA(AccessCodeInput)
+END_METADATA
+
 FlexCodeInput::FlexCodeInput(OnInputChange on_input_change,
                              OnEnter on_enter,
                              OnEscape on_escape,
@@ -187,6 +191,9 @@
   return false;
 }
 
+BEGIN_METADATA(FlexCodeInput)
+END_METADATA
+
 AccessibleInputField::AccessibleInputField()
     : SystemTextfield(SystemTextfield::Type::kMedium) {}
 
@@ -219,6 +226,9 @@
   node_data->SetNameFrom(ax::mojom::NameFrom::kAttributeExplicitlyEmpty);
 }
 
+BEGIN_METADATA(AccessibleInputField)
+END_METADATA
+
 FixedLengthCodeInput::FixedLengthCodeInput(int length,
                                            OnInputChange on_input_change,
                                            OnEnter on_enter,
@@ -605,4 +615,7 @@
   return ActiveField()->GetText();
 }
 
+BEGIN_METADATA(FixedLengthCodeInput)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/login/ui/access_code_input.h b/ash/login/ui/access_code_input.h
index bc1a7c1..364bb7b03 100644
--- a/ash/login/ui/access_code_input.h
+++ b/ash/login/ui/access_code_input.h
@@ -10,6 +10,7 @@
 #include "ash/style/system_textfield.h"
 #include "base/memory/raw_ptr.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/color/color_id.h"
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/controls/textfield/textfield_controller.h"
@@ -21,6 +22,8 @@
 namespace ash {
 
 class AccessCodeInput : public views::View, public views::TextfieldController {
+  METADATA_HEADER(AccessCodeInput, views::View)
+
  public:
   static constexpr int kAccessCodeInputFieldUnderlineThicknessDp = 2;
   static constexpr int kAccessCodeInputFieldHeightDp =
@@ -54,6 +57,8 @@
 };
 
 class FlexCodeInput : public AccessCodeInput {
+  METADATA_HEADER(FlexCodeInput, AccessCodeInput)
+
  public:
   using OnInputChange = base::RepeatingCallback<void(bool enable_submit)>;
   using OnEnter = base::RepeatingClosure;
@@ -123,6 +128,8 @@
 // Accessible input field for a single digit in fixed length codes.
 // Customizes field description and focus behavior.
 class AccessibleInputField : public SystemTextfield {
+  METADATA_HEADER(AccessibleInputField, SystemTextfield)
+
  public:
   AccessibleInputField();
 
@@ -141,6 +148,8 @@
 // Digital access code input view for variable length of input codes.
 // Displays a separate underscored field for every input code digit.
 class FixedLengthCodeInput : public AccessCodeInput {
+  METADATA_HEADER(FixedLengthCodeInput, AccessCodeInput)
+
  public:
   using OnInputChange =
       base::RepeatingCallback<void(bool last_field_active, bool complete)>;
diff --git a/ash/login/ui/animated_auth_factors_label_wrapper.cc b/ash/login/ui/animated_auth_factors_label_wrapper.cc
index bb674cd..975cd43 100644
--- a/ash/login/ui/animated_auth_factors_label_wrapper.cc
+++ b/ash/login/ui/animated_auth_factors_label_wrapper.cc
@@ -10,6 +10,8 @@
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animation_sequence.h"
 #include "ui/compositor/layer_animator.h"
@@ -39,6 +41,8 @@
 constexpr int kLabelWrapperHeightDp = kLabelMaxLines * kLabelLineHeightDp;
 
 class AuthFactorsLabel : public views::Label {
+  METADATA_HEADER(AuthFactorsLabel, views::Label)
+
  public:
   AuthFactorsLabel(bool visible_to_screen_reader)
       : visible_to_screen_reader_(visible_to_screen_reader) {
@@ -77,6 +81,9 @@
   bool visible_to_screen_reader_ = true;
 };
 
+BEGIN_METADATA(AuthFactorsLabel)
+END_METADATA
+
 }  // namespace
 
 AnimatedAuthFactorsLabelWrapper::AnimatedAuthFactorsLabelWrapper() {
@@ -198,4 +205,7 @@
   return gfx::Size(kAuthFactorsViewWidthDp, kLabelWrapperHeightDp);
 }
 
+BEGIN_METADATA(AnimatedAuthFactorsLabelWrapper)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/login/ui/animated_auth_factors_label_wrapper.h b/ash/login/ui/animated_auth_factors_label_wrapper.h
index 8457cfd..2dc6593 100644
--- a/ash/login/ui/animated_auth_factors_label_wrapper.h
+++ b/ash/login/ui/animated_auth_factors_label_wrapper.h
@@ -10,6 +10,7 @@
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/timer/timer.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/view.h"
 
 namespace views {
@@ -20,6 +21,8 @@
 
 // TODO(b/216696664): Add unit tests for this class.
 class ASH_EXPORT AnimatedAuthFactorsLabelWrapper : public views::View {
+  METADATA_HEADER(AnimatedAuthFactorsLabelWrapper, views::View)
+
  public:
   AnimatedAuthFactorsLabelWrapper();
   AnimatedAuthFactorsLabelWrapper(const AnimatedAuthFactorsLabelWrapper&) =
diff --git a/ash/login/ui/animated_rounded_image_view.cc b/ash/login/ui/animated_rounded_image_view.cc
index dea96b50..e5d2daf 100644
--- a/ash/login/ui/animated_rounded_image_view.cc
+++ b/ash/login/ui/animated_rounded_image_view.cc
@@ -10,6 +10,7 @@
 #include "base/numerics/ranges.h"
 #include "skia/ext/image_operations.h"
 #include "third_party/skia/include/core/SkPath.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/skia_conversions.h"
 #include "ui/gfx/image/image_skia_operations.h"
@@ -150,4 +151,7 @@
   }
 }
 
+BEGIN_METADATA(AnimatedRoundedImageView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/login/ui/animated_rounded_image_view.h b/ash/login/ui/animated_rounded_image_view.h
index 8f87fdd..630d05ad 100644
--- a/ash/login/ui/animated_rounded_image_view.h
+++ b/ash/login/ui/animated_rounded_image_view.h
@@ -11,6 +11,7 @@
 #include "ash/ash_export.h"
 #include "ash/login/ui/animation_frame.h"
 #include "base/timer/timer.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/views/view.h"
@@ -19,6 +20,8 @@
 
 // A custom image view with rounded edges.
 class ASH_EXPORT AnimatedRoundedImageView : public views::View {
+  METADATA_HEADER(AnimatedRoundedImageView, views::View)
+
  public:
   enum class Playback {
     kFirstFrameOnly,  // Only the first frame in the animation will be shown.
diff --git a/ash/login/ui/login_base_bubble_view.cc b/ash/login/ui/login_base_bubble_view.cc
index f86d5ff..e4315c7 100644
--- a/ash/login/ui/login_base_bubble_view.cc
+++ b/ash/login/ui/login_base_bubble_view.cc
@@ -19,6 +19,7 @@
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/aura/client/focus_change_observer.h"
 #include "ui/aura/client/focus_client.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animator.h"
@@ -392,4 +393,7 @@
   }
 }
 
+BEGIN_METADATA(LoginBaseBubbleView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/login/ui/login_base_bubble_view.h b/ash/login/ui/login_base_bubble_view.h
index abee7d8d..b3a2dd30 100644
--- a/ash/login/ui/login_base_bubble_view.h
+++ b/ash/login/ui/login_base_bubble_view.h
@@ -9,6 +9,7 @@
 #include "ash/login/ui/login_button.h"
 #include "ash/style/system_shadow.h"
 #include "base/memory/weak_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 #include "ui/views/view.h"
@@ -21,6 +22,8 @@
 // Base bubble view for login screen bubbles.
 class ASH_EXPORT LoginBaseBubbleView : public views::View,
                                        public ui::LayerAnimationObserver {
+  METADATA_HEADER(LoginBaseBubbleView, views::View)
+
  public:
   enum class PositioningStrategy {
     // Try to show the bubble after the anchor (on the right side in LTR), if
diff --git a/ash/login/ui/login_password_view.cc b/ash/login/ui/login_password_view.cc
index 871f1a3..72db0cb 100644
--- a/ash/login/ui/login_password_view.cc
+++ b/ash/login/ui/login_password_view.cc
@@ -29,6 +29,7 @@
 #include "chromeos/constants/chromeos_features.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/image_model.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
@@ -144,6 +145,8 @@
 // The login password row contains the password textfield and different buttons
 // and indicators (display password, caps lock enabled).
 class LoginPasswordView::LoginPasswordRow : public views::View {
+  METADATA_HEADER(LoginPasswordRow, views::View)
+
  public:
   explicit LoginPasswordRow() {
     const bool is_jelly = chromeos::features::IsJellyEnabled();
@@ -163,9 +166,14 @@
   LoginPasswordRow& operator=(const LoginPasswordRow&) = delete;
 };
 
+BEGIN_METADATA(LoginPasswordView, LoginPasswordRow, views::View)
+END_METADATA
+
 // A textfield that selects all text on focus and allows to switch between
 // show/hide password modes.
 class LoginPasswordView::LoginTextfield : public views::Textfield {
+  METADATA_HEADER(LoginTextfield, views::Textfield)
+
  public:
   LoginTextfield(base::RepeatingClosure on_focus_closure,
                  base::RepeatingClosure on_blur_closure)
@@ -246,8 +254,13 @@
   base::RepeatingClosure on_tab_focus_closure_;
 };
 
+BEGIN_METADATA(LoginPasswordView, LoginTextfield, views::Textfield)
+END_METADATA
+
 class LoginPasswordView::DisplayPasswordButton
     : public views::ToggleImageButton {
+  METADATA_HEADER(DisplayPasswordButton, views::ToggleImageButton)
+
  public:
   explicit DisplayPasswordButton(views::Button::PressedCallback callback)
       : ToggleImageButton(std::move(callback)) {
@@ -285,6 +298,11 @@
   ~DisplayPasswordButton() override = default;
 };
 
+BEGIN_METADATA(LoginPasswordView,
+               DisplayPasswordButton,
+               views::ToggleImageButton)
+END_METADATA
+
 LoginPasswordView::TestApi::TestApi(LoginPasswordView* view) : view_(view) {}
 
 LoginPasswordView::TestApi::~TestApi() = default;
diff --git a/ash/login/ui/login_pin_input_view.cc b/ash/login/ui/login_pin_input_view.cc
index bff3e06..4601d0e 100644
--- a/ash/login/ui/login_pin_input_view.cc
+++ b/ash/login/ui/login_pin_input_view.cc
@@ -19,6 +19,8 @@
 #include "ui/accessibility/ax_enums.mojom-shared.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/compositor/layer_type.h"
 #include "ui/gfx/geometry/size.h"
@@ -42,6 +44,8 @@
 // A FixedLengthCodeInput that is always obscured and
 // has some special focus handling.
 class LoginPinInput : public FixedLengthCodeInput {
+  METADATA_HEADER(LoginPinInput, FixedLengthCodeInput)
+
  public:
   LoginPinInput(int length,
                 LoginPinInputView::OnPinSubmit on_submit,
@@ -146,6 +150,9 @@
       IDS_ASH_LOGIN_POD_PASSWORD_PIN_INPUT_ACCESSIBLE_NAME));
 }
 
+BEGIN_METADATA(LoginPinInput)
+END_METADATA
+
 const int LoginPinInputView::kDefaultLength = 6;
 
 LoginPinInputView::TestApi::TestApi(LoginPinInputView* view) : view_(view) {
@@ -305,4 +312,7 @@
   }
 }
 
+BEGIN_METADATA(LoginPinInputView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/login/ui/login_pin_input_view.h b/ash/login/ui/login_pin_input_view.h
index 2927b2e3..0973df0 100644
--- a/ash/login/ui/login_pin_input_view.h
+++ b/ash/login/ui/login_pin_input_view.h
@@ -10,6 +10,7 @@
 #include "ash/login/ui/non_accessible_view.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/views/view.h"
 
@@ -34,6 +35,8 @@
 //
 class ASH_EXPORT LoginPinInputView : public views::View,
                                      public ui::ImplicitAnimationObserver {
+  METADATA_HEADER(LoginPinInputView, views::View)
+
  public:
   using OnPinSubmit = base::RepeatingCallback<void(const std::u16string& pin)>;
   using OnPinChanged = base::RepeatingCallback<void(bool is_empty)>;
diff --git a/ash/login/ui/login_pin_view.cc b/ash/login/ui/login_pin_view.cc
index 09d2180d..3343952f 100644
--- a/ash/login/ui/login_pin_view.cc
+++ b/ash/login/ui/login_pin_view.cc
@@ -22,6 +22,8 @@
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/image_model.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/keycodes/dom/dom_code.h"
@@ -88,6 +90,8 @@
 
 // A base class for pin button in the pin keyboard.
 class BasePinButton : public views::View {
+  METADATA_HEADER(BasePinButton, views::View)
+
  public:
   BasePinButton(const gfx::Size& size,
                 const std::u16string& accessible_name,
@@ -205,10 +209,15 @@
   base::RepeatingClosure on_press_;
 };
 
+BEGIN_METADATA(BasePinButton)
+END_METADATA
+
 }  // namespace
 
 // A PIN button that displays a digit number and corresponding letter mapping.
 class LoginPinView::DigitPinButton : public BasePinButton {
+  METADATA_HEADER(DigitPinButton, BasePinButton)
+
  public:
   DigitPinButton(int value,
                  bool show_sub_label,
@@ -252,8 +261,13 @@
   raw_ptr<views::Label, ExperimentalAsh> sub_label_ = nullptr;
 };
 
+BEGIN_METADATA(LoginPinView, DigitPinButton, BasePinButton)
+END_METADATA
+
 // A PIN button that displays backspace icon.
 class LoginPinView::BackspacePinButton : public BasePinButton {
+  METADATA_HEADER(BackspacePinButton, BasePinButton)
+
  public:
   BackspacePinButton(const gfx::Size& size,
                      const base::RepeatingClosure& on_press)
@@ -393,8 +407,13 @@
           base::Unretained(this)));
 };
 
+BEGIN_METADATA(LoginPinView, BackspacePinButton, BasePinButton)
+END_METADATA
+
 // A PIN button to press to submit the PIN / password.
 class LoginPinView::SubmitPinButton : public BasePinButton {
+  METADATA_HEADER(SubmitPinButton, BasePinButton)
+
  public:
   SubmitPinButton(const gfx::Size& size, const base::RepeatingClosure& on_press)
       : BasePinButton(size,
@@ -424,6 +443,9 @@
                               base::Unretained(this)));
 };
 
+BEGIN_METADATA(LoginPinView, SubmitPinButton, BasePinButton)
+END_METADATA
+
 // static
 gfx::Size LoginPinView::TestApi::GetButtonSize(Style style) {
   return gfx::Size(kButtonWidthDp, kButtonHeightDp);
@@ -537,4 +559,7 @@
   return row;
 }
 
+BEGIN_METADATA(LoginPinView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/login/ui/login_pin_view.h b/ash/login/ui/login_pin_view.h
index b1299b6..528a278a 100644
--- a/ash/login/ui/login_pin_view.h
+++ b/ash/login/ui/login_pin_view.h
@@ -13,6 +13,7 @@
 #include "base/functional/callback.h"
 #include "base/functional/callback_helpers.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/view.h"
 
 namespace base {
@@ -50,6 +51,8 @@
 // The submit button is optional.
 //
 class ASH_EXPORT LoginPinView : public NonAccessibleView {
+  METADATA_HEADER(LoginPinView, NonAccessibleView)
+
  public:
   // Visual style of PIN keyboard.
   enum class Style {
diff --git a/ash/login/ui/login_remove_account_dialog.cc b/ash/login/ui/login_remove_account_dialog.cc
index b919ff3..b3ecf4c 100644
--- a/ash/login/ui/login_remove_account_dialog.cc
+++ b/ash/login/ui/login_remove_account_dialog.cc
@@ -18,6 +18,8 @@
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
@@ -75,6 +77,8 @@
 
 // A system label button that dismisses its bubble dialog parent on key event.
 class RemoveUserButton : public PillButton {
+  METADATA_HEADER(RemoveUserButton, PillButton)
+
  public:
   RemoveUserButton(PressedCallback callback, LoginRemoveAccountDialog* bubble)
       : PillButton(std::move(callback),
@@ -113,6 +117,9 @@
   raw_ptr<LoginRemoveAccountDialog, ExperimentalAsh> bubble_;
 };
 
+BEGIN_METADATA(RemoveUserButton)
+END_METADATA
+
 LoginRemoveAccountDialog::TestApi::TestApi(LoginRemoveAccountDialog* bubble)
     : bubble_(bubble) {}
 
@@ -328,4 +335,7 @@
   }
 }
 
+BEGIN_METADATA(LoginRemoveAccountDialog)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/login/ui/login_remove_account_dialog.h b/ash/login/ui/login_remove_account_dialog.h
index 6951553..fb1749b 100644
--- a/ash/login/ui/login_remove_account_dialog.h
+++ b/ash/login/ui/login_remove_account_dialog.h
@@ -12,6 +12,7 @@
 #include "ash/login/ui/login_button.h"
 #include "base/memory/raw_ptr.h"
 #include "components/user_manager/user_type.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/focus/focus_search.h"
 #include "ui/views/view.h"
@@ -23,6 +24,8 @@
 
 class ASH_EXPORT LoginRemoveAccountDialog : public LoginBaseBubbleView,
                                             public views::FocusTraversable {
+  METADATA_HEADER(LoginRemoveAccountDialog, LoginBaseBubbleView)
+
  public:
   class TestApi {
    public:
diff --git a/ash/login/ui/non_accessible_view.cc b/ash/login/ui/non_accessible_view.cc
index 7b6ecea..b18eb488 100644
--- a/ash/login/ui/non_accessible_view.cc
+++ b/ash/login/ui/non_accessible_view.cc
@@ -6,6 +6,7 @@
 
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 
 namespace ash {
 
@@ -19,12 +20,15 @@
 
 NonAccessibleView::~NonAccessibleView() = default;
 
-const char* NonAccessibleView::GetClassName() const {
-  return name_.c_str();
+std::string NonAccessibleView::GetObjectName() const {
+  return name_;
 }
 
 void NonAccessibleView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   node_data->AddState(ax::mojom::State::kInvisible);
 }
 
+BEGIN_METADATA(NonAccessibleView)
+END_METADATA
+
 }  // namespace ash
\ No newline at end of file
diff --git a/ash/login/ui/non_accessible_view.h b/ash/login/ui/non_accessible_view.h
index e6bfa18..3e688b4 100644
--- a/ash/login/ui/non_accessible_view.h
+++ b/ash/login/ui/non_accessible_view.h
@@ -8,12 +8,15 @@
 #include <string>
 
 #include "ash/ash_export.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/view.h"
 
 namespace ash {
 
 // A views::View instance that is not shown in the accessibility hierarchy.
 class ASH_EXPORT NonAccessibleView : public views::View {
+  METADATA_HEADER(NonAccessibleView, views::View)
+
  public:
   NonAccessibleView();
   explicit NonAccessibleView(const std::string& name);
@@ -24,7 +27,7 @@
   ~NonAccessibleView() override;
 
   // views::View:
-  const char* GetClassName() const override;
+  std::string GetObjectName() const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
 
  private:
diff --git a/ash/login/ui/note_action_launch_button.cc b/ash/login/ui/note_action_launch_button.cc
index 0c88ecc1..ef27a89 100644
--- a/ash/login/ui/note_action_launch_button.cc
+++ b/ash/login/ui/note_action_launch_button.cc
@@ -16,6 +16,8 @@
 #include "base/i18n/rtl.h"
 #include "base/memory/raw_ptr.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/image_model.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animator.h"
@@ -101,6 +103,8 @@
 
 // The (background) view that paints and animates the note action bubble.
 class NoteActionLaunchButton::BackgroundView : public NonAccessibleView {
+  METADATA_HEADER(BackgroundView, NonAccessibleView)
+
  public:
   // NOTE: the background layer is set to the large bubble bounds and scaled
   // down when needed.
@@ -161,6 +165,9 @@
   BubbleLayerDelegate background_layer_delegate_;
 };
 
+BEGIN_METADATA(NoteActionLaunchButton, BackgroundView, NonAccessibleView)
+END_METADATA
+
 // The event target delegate used for the note action view. It matches the
 // shape of the bubble with the provided radius.
 class BubbleTargeterDelegate : public views::MaskedTargeterDelegate {
@@ -189,6 +196,8 @@
 // the (small) bubble shape centered in the top right corner of the action
 // button bounds.
 class NoteActionLaunchButton::ActionButton : public views::ImageButton {
+  METADATA_HEADER(ActionButton, views::ImageButton)
+
  public:
   explicit ActionButton(NoteActionLaunchButton::BackgroundView* background)
       : views::ImageButton(base::BindRepeating(&ActionButton::ButtonPressed,
@@ -343,6 +352,9 @@
   bool tracking_activation_gesture_ = false;
 };
 
+BEGIN_METADATA(NoteActionLaunchButton, ActionButton, views::ImageButton)
+END_METADATA
+
 NoteActionLaunchButton::TestApi::TestApi(NoteActionLaunchButton* launch_button)
     : launch_button_(launch_button) {}
 
@@ -376,4 +388,7 @@
   SetVisible(action_state == mojom::TrayActionState::kAvailable);
 }
 
+BEGIN_METADATA(NoteActionLaunchButton)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/login/ui/note_action_launch_button.h b/ash/login/ui/note_action_launch_button.h
index c8f92497..fc6e7c92 100644
--- a/ash/login/ui/note_action_launch_button.h
+++ b/ash/login/ui/note_action_launch_button.h
@@ -11,6 +11,7 @@
 #include "ash/tray_action/tray_action.h"
 #include "ash/tray_action/tray_action_observer.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 
 namespace ash {
 
@@ -27,6 +28,8 @@
 // (the view observes the action availability using login data dispatcher, and
 // updates itself accordingly).
 class ASH_EXPORT NoteActionLaunchButton : public NonAccessibleView {
+  METADATA_HEADER(NoteActionLaunchButton, NonAccessibleView)
+
  public:
   // Used by tests to get internal implementation details.
   class ASH_EXPORT TestApi {
diff --git a/ash/login/ui/public_account_monitoring_info_dialog.cc b/ash/login/ui/public_account_monitoring_info_dialog.cc
index 1ed96466..9ff511ee 100644
--- a/ash/login/ui/public_account_monitoring_info_dialog.cc
+++ b/ash/login/ui/public_account_monitoring_info_dialog.cc
@@ -7,6 +7,8 @@
 #include "ash/login/ui/login_expanded_public_account_view.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/canvas.h"
 #include "ui/views/border.h"
 #include "ui/views/bubble/bubble_frame_view.h"
@@ -28,6 +30,8 @@
     kDialogWidthDp - kBulletContainerSizeDp - 2 * kDialogContentMarginDp;
 
 class BulletView : public views::View {
+  METADATA_HEADER(BulletView, views::View)
+
  public:
   explicit BulletView(SkColor color, int radius)
       : color_(color), radius_(radius) {}
@@ -55,6 +59,9 @@
   int radius_;
 };
 
+BEGIN_METADATA(BulletView)
+END_METADATA
+
 }  // namespace
 
 PublicAccountMonitoringInfoDialog::PublicAccountMonitoringInfoDialog(
@@ -136,4 +143,7 @@
   return {kDialogWidthDp, GetHeightForWidth(kDialogWidthDp)};
 }
 
+BEGIN_METADATA(PublicAccountMonitoringInfoDialog)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/login/ui/public_account_monitoring_info_dialog.h b/ash/login/ui/public_account_monitoring_info_dialog.h
index 4a29869..3c79cae9 100644
--- a/ash/login/ui/public_account_monitoring_info_dialog.h
+++ b/ash/login/ui/public_account_monitoring_info_dialog.h
@@ -7,6 +7,7 @@
 
 #include "ash/ash_export.h"
 #include "base/memory/weak_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/window/dialog_delegate.h"
 
 namespace ash {
@@ -17,6 +18,8 @@
 // present on the public account expanded view.
 class ASH_EXPORT PublicAccountMonitoringInfoDialog
     : public views::DialogDelegateView {
+  METADATA_HEADER(PublicAccountMonitoringInfoDialog, views::DialogDelegateView)
+
  public:
   explicit PublicAccountMonitoringInfoDialog(
       base::WeakPtr<LoginExpandedPublicAccountView> controller);
diff --git a/ash/login/ui/views_utils.cc b/ash/login/ui/views_utils.cc
index dcbc736..03fdc186 100644
--- a/ash/login/ui/views_utils.cc
+++ b/ash/login/ui/views_utils.cc
@@ -10,6 +10,8 @@
 #include "ash/public/cpp/shelf_config.h"
 #include "ash/style/ash_color_provider.h"
 #include "base/ranges/algorithm.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/color/color_id.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
@@ -28,6 +30,8 @@
 
 class ContainerView : public NonAccessibleView,
                       public views::ViewTargeterDelegate {
+  METADATA_HEADER(ContainerView, NonAccessibleView)
+
  public:
   ContainerView() {
     SetEventTargeter(std::make_unique<views::ViewTargeter>(this));
@@ -52,6 +56,9 @@
   }
 };
 
+BEGIN_METADATA(ContainerView)
+END_METADATA
+
 }  // namespace
 
 namespace login_views_utils {
diff --git a/ash/public/cpp/accelerators_util.cc b/ash/public/cpp/accelerators_util.cc
index 7473cbe9..fd85713 100644
--- a/ash/public/cpp/accelerators_util.cc
+++ b/ash/public/cpp/accelerators_util.cc
@@ -99,6 +99,12 @@
   return *key_display_map;
 }
 
+bool IsValidDomCode(ui::DomCode dom_code) {
+  return ui::KeycodeConverter::InvalidNativeKeycode() !=
+         ui::KeycodeConverter::UsbKeycodeToNativeKeycode(
+             static_cast<int32_t>(dom_code));
+}
+
 }  // namespace
 
 namespace ash {
@@ -124,7 +130,8 @@
     ui::DomCode dom_code =
         ui::KeycodeConverter::MapUSPositionalShortcutKeyToDomCode(key_code);
     if (dom_code != ui::DomCode::NONE) {
-      if (layout_engine->Lookup(dom_code, /*event_flags=*/ui::EF_NONE, &dom_key,
+      if (IsValidDomCode(dom_code) &&
+          layout_engine->Lookup(dom_code, /*event_flags=*/ui::EF_NONE, &dom_key,
                                 &key_code_to_compare)) {
         if (dom_key.IsDeadKey()) {
           return GetStringForDeadKey(dom_key);
@@ -148,7 +155,8 @@
 
   // Cache miss, get the key string and store it.
   for (const auto& dom_code : ui::kDomCodesArray) {
-    if (!layout_engine->Lookup(dom_code, /*event_flags=*/ui::EF_NONE, &dom_key,
+    if (IsValidDomCode(dom_code) &&
+        !layout_engine->Lookup(dom_code, /*event_flags=*/ui::EF_NONE, &dom_key,
                                &key_code_to_compare)) {
       continue;
     }
diff --git a/ash/public/cpp/ash_web_view.cc b/ash/public/cpp/ash_web_view.cc
index 7617a47c..3c3ba5d 100644
--- a/ash/public/cpp/ash_web_view.cc
+++ b/ash/public/cpp/ash_web_view.cc
@@ -4,6 +4,8 @@
 
 #include "ash/public/cpp/ash_web_view.h"
 
+#include "ui/base/metadata/metadata_impl_macros.h"
+
 namespace ash {
 
 // AshWebView ------------------------------------------------------------
@@ -11,4 +13,7 @@
 AshWebView::AshWebView() = default;
 AshWebView::~AshWebView() = default;
 
+BEGIN_METADATA(AshWebView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/public/cpp/ash_web_view.h b/ash/public/cpp/ash_web_view.h
index 0ca3c1d3..5ae7864 100644
--- a/ash/public/cpp/ash_web_view.h
+++ b/ash/public/cpp/ash_web_view.h
@@ -8,6 +8,7 @@
 #include "ash/public/cpp/ash_public_export.h"
 #include "base/observer_list_types.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/gfx/geometry/rounded_corners_f.h"
 #include "ui/views/view.h"
 
@@ -22,6 +23,8 @@
 // A view which wraps a views::WebView (and associated WebContents) to work
 // around dependency restrictions in Ash.
 class ASH_PUBLIC_EXPORT AshWebView : public views::View {
+  METADATA_HEADER(AshWebView, views::View)
+
  public:
   // Initialization parameters which dictate how an instance of AshWebView
   // should behave.
diff --git a/ash/public/cpp/rounded_image_view.cc b/ash/public/cpp/rounded_image_view.cc
index 5356eda..deb7985 100644
--- a/ash/public/cpp/rounded_image_view.cc
+++ b/ash/public/cpp/rounded_image_view.cc
@@ -6,6 +6,7 @@
 
 #include "skia/ext/image_operations.h"
 #include "third_party/skia/include/core/SkPath.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/skia_conversions.h"
 #include "ui/gfx/image/image_skia_operations.h"
@@ -119,4 +120,7 @@
   return resized_image_.size();
 }
 
+BEGIN_METADATA(RoundedImageView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/public/cpp/rounded_image_view.h b/ash/public/cpp/rounded_image_view.h
index bc86cc5..3f961ad 100644
--- a/ash/public/cpp/rounded_image_view.h
+++ b/ash/public/cpp/rounded_image_view.h
@@ -6,6 +6,7 @@
 #define ASH_PUBLIC_CPP_ROUNDED_IMAGE_VIEW_H_
 
 #include "ash/public/cpp/ash_public_export.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/views/metadata/view_factory.h"
@@ -15,6 +16,8 @@
 
 // A custom image view with rounded edges.
 class ASH_PUBLIC_EXPORT RoundedImageView : public views::View {
+  METADATA_HEADER(RoundedImageView, views::View)
+
  public:
   enum class Alignment {
     // The image's drawn portion always contains the image's origin.
diff --git a/ash/shelf/shelf_app_button.cc b/ash/shelf/shelf_app_button.cc
index 86a2ac79..5f41176 100644
--- a/ash/shelf/shelf_app_button.cc
+++ b/ash/shelf/shelf_app_button.cc
@@ -10,7 +10,6 @@
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/shelf_config.h"
 #include "ash/public/cpp/shelf_model.h"
-#include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shelf/scrollable_shelf_view.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_button_delegate.h"
@@ -527,13 +526,33 @@
       image, icon_shadows_));
 }
 
-void ShelfAppButton::UpdateIconImage() {
+void ShelfAppButton::SetImage(const gfx::ImageSkia& image) {
+  if (image.isNull()) {
+    // TODO: need an empty image.
+    icon_view_->SetImage(image);
+    icon_image_ = gfx::ImageSkia();
+    return;
+  }
+  icon_image_ = image;
+
+  gfx::Size preferred_size = GetPreferredIconSize();
+
   if (has_host_badge_) {
-    icon_view_->SetImage(GetIconImage());
+    if (image.size() == preferred_size) {
+      icon_view_->SetImage(image);
+      return;
+    }
+    icon_view_->SetImage(gfx::ImageSkiaOperations::CreateResizedImage(
+        image, skia::ImageOperations::RESIZE_BEST, preferred_size));
     return;
   }
 
-  SetShadowedImage(GetIconImage());
+  if (image.size() == preferred_size) {
+    SetShadowedImage(image);
+    return;
+  }
+  SetShadowedImage(gfx::ImageSkiaOperations::CreateResizedImage(
+      image, skia::ImageOperations::RESIZE_BEST, preferred_size));
 }
 
 gfx::ImageSkia ShelfAppButton::GetImage() const {
@@ -541,24 +560,12 @@
 }
 
 gfx::ImageSkia ShelfAppButton::GetIconImage() const {
-  gfx::ImageSkia icon_image;
-  if (icon_image_model_.IsImage()) {
-    icon_image = icon_image_model_.GetImage().AsImageSkia();
-  } else if (icon_image_model_.IsVectorIcon()) {
-    auto* color_provider = GetColorProvider();
-    if (!color_provider) {
-      color_provider = shelf_view_->GetColorProvider();
-    }
-    icon_image = ui::ThemedVectorIcon(icon_image_model_.GetVectorIcon())
-                     .GetImageSkia(color_provider);
-  }
-  const gfx::Size preferred_size = GetPreferredIconSize();
-  if (icon_image.size() == preferred_size) {
-    return icon_image;
-  }
+  const gfx::Size preferred_size = GetPreferredSize();
+  if (icon_image_.size() == preferred_size)
+    return icon_image_;
 
   return gfx::ImageSkiaOperations::CreateResizedImage(
-      icon_image, skia::ImageOperations::RESIZE_BEST, preferred_size);
+      icon_image_, skia::ImageOperations::RESIZE_BEST, GetPreferredIconSize());
 }
 
 void ShelfAppButton::SetHostBadgeImage(const gfx::ImageSkia& host_badge_image) {
@@ -577,21 +584,13 @@
 }
 
 void ShelfAppButton::SetMainAndMaybeHostBadgeImage(
-    const gfx::ImageSkia& main_image,
-    bool has_placeholder_icon,
+    const gfx::ImageSkia& image,
     const gfx::ImageSkia& host_badge_image) {
   // `has_host_badge_` needs to be set before SetImage(), since image size is
   // set depending on the boolean logic.
   has_host_badge_ = !host_badge_image.isNull();
-  if (is_promise_app_ && has_placeholder_icon) {
-    icon_image_model_ = ui::ImageModel(ui::ImageModel::FromVectorIcon(
-        ash::kPlaceholderAppIcon, cros_tokens::kCrosSysPrimary));
-  } else {
-    icon_image_model_ =
-        ui::ImageModel(ui::ImageModel::FromImageSkia(main_image));
-  }
+  SetImage(image);
   SetHostBadgeImage(host_badge_image);
-  UpdateIconImage();
 }
 
 void ShelfAppButton::AddState(State state) {
@@ -722,15 +721,16 @@
   else
     ClearState(ShelfAppButton::STATE_NOTIFICATION);
 
+  app_status_ = item.app_status;
+
   is_promise_app_ = item.is_promise_app;
 
   package_id_ = item.package_id;
 
   // Progress is incremental always by server side implementation. Do not use
   // equal for comparing progress as float point errors may surface.
-  if (progress_ < item.progress || app_status_ != item.app_status) {
+  if (progress_ < item.progress) {
     progress_ = item.progress;
-    app_status_ = item.app_status;
     UpdateProgressRingBounds();
   }
 
@@ -1222,11 +1222,9 @@
                             : shelf_view_->GetButtonIconSize() *
                                   GetAdjustedIconScaleForProgressRing();
 
-  const gfx::Size current_icon_size = icon_image_model_.Size();
-
   // Resize the image maintaining our aspect ratio.
-  float aspect_ratio = static_cast<float>(current_icon_size.width()) /
-                       static_cast<float>(current_icon_size.height());
+  float aspect_ratio = static_cast<float>(icon_image_.width()) /
+                       static_cast<float>(icon_image_.height());
   int height = icon_size;
   int width = static_cast<int>(aspect_ratio * height);
   if (width > icon_size) {
@@ -1242,7 +1240,7 @@
 
   if (scale_up) {
     icon_scale_ = kAppIconScale;
-    UpdateIconImage();
+    SetImage(icon_image_);
     icon_view_->layer()->SetTransform(GetScaleTransform(kAppIconScale));
   }
   ui::ScopedLayerAnimationSettings settings(icon_view_->layer()->GetAnimator());
@@ -1278,7 +1276,7 @@
 
 void ShelfAppButton::OnImplicitAnimationsCompleted() {
   icon_scale_ = 1.0f;
-  UpdateIconImage();
+  SetImage(icon_image_);
   icon_view_->layer()->SetTransform(gfx::Transform());
   if (notification_indicator_)
     notification_indicator_->layer()->SetTransform(gfx::Transform());
diff --git a/ash/shelf/shelf_app_button.h b/ash/shelf/shelf_app_button.h
index 449f4db..28d2876 100644
--- a/ash/shelf/shelf_app_button.h
+++ b/ash/shelf/shelf_app_button.h
@@ -12,12 +12,14 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/timer/timer.h"
-#include "ui/base/models/image_model.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/gfx/shadow_value.h"
 #include "ui/views/animation/ink_drop_observer.h"
 #include "ui/views/animation/ink_drop_state.h"
-#include "ui/views/controls/image_view.h"
+
+namespace views {
+class ImageView;
+}  // namespace views
 
 namespace ash {
 struct ShelfItem;
@@ -68,22 +70,17 @@
 
   ~ShelfAppButton() override;
 
-  // Updates the icon image to display for this entry.
-  void UpdateIconImage();
+  // Sets the image to display for this entry.
+  void SetImage(const gfx::ImageSkia& image);
 
   // Retrieve the image to show proxy operations.
   gfx::ImageSkia GetImage() const;
 
-  // Gets the resized icon image represented by `icon_image_model_` without the
-  // shadow.
+  // Gets the resized `icon_image_` without the shadow.
   gfx::ImageSkia GetIconImage() const;
 
-  // Sets the `icon_image_model_` for this entry. If |is_placeholder_icon| is
-  // true, the |main_image| will be ignored and this entry will be assigned a
-  // placeholder vector icon. This method also SetHostBadgeImage() depending on
-  // `has_host_badge` and then calls into UpdateIconImage().
-  void SetMainAndMaybeHostBadgeImage(const gfx::ImageSkia& main_image,
-                                     bool is_placeholder_icon,
+  // Calls SetImage(), and SetHostBadgeImage() depending on `has_host_badge`.
+  void SetMainAndMaybeHostBadgeImage(const gfx::ImageSkia& image,
                                      const gfx::ImageSkia& host_badge_image);
 
   // |state| is or'd into the current state.
@@ -259,8 +256,8 @@
 
   gfx::ShadowValues icon_shadows_;
 
-  // The model image for this app button.
-  ui::ImageModel icon_image_model_;
+  // The bitmap image for this app button.
+  gfx::ImageSkia icon_image_;
 
   // The bitmap image for the host badge icon if this is an App Shortcut.
   gfx::ImageSkia host_badge_image_;
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index e939ce03..4136112 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -1062,8 +1062,7 @@
 
 void ShelfView::UpdateButton(ShelfAppButton* button, const ShelfItem& item) {
   button->ReflectItemStatus(item);
-  button->SetMainAndMaybeHostBadgeImage(item.image, item.has_placeholder_icon,
-                                        item.badge_image);
+  button->SetMainAndMaybeHostBadgeImage(item.image, item.badge_image);
   button->SetNotificationBadgeColor(item.notification_badge_color);
   button->SetAccessibleName(item.accessible_name);
   button->SchedulePaint();
diff --git a/ash/style/combobox.cc b/ash/style/combobox.cc
index b03a2d48..a126a90 100644
--- a/ash/style/combobox.cc
+++ b/ash/style/combobox.cc
@@ -18,6 +18,7 @@
 #include "base/functional/bind.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/combobox_model.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
@@ -77,6 +78,8 @@
 constexpr int kMenuShadowElevation = 12;
 
 class ComboboxMenuOption : public RadioButton {
+  METADATA_HEADER(ComboboxMenuOption, RadioButton)
+
  public:
   ComboboxMenuOption(int button_width,
                      PressedCallback callback,
@@ -110,7 +113,12 @@
   }
 };
 
+BEGIN_METADATA(ComboboxMenuOption)
+END_METADATA
+
 class ComboboxMenuOptionGroup : public RadioButtonGroup {
+  METADATA_HEADER(ComboboxMenuOptionGroup, RadioButtonGroup)
+
  public:
   ComboboxMenuOptionGroup()
       : RadioButtonGroup(kMaxMenuWidth,
@@ -139,6 +147,9 @@
   }
 };
 
+BEGIN_METADATA(ComboboxMenuOptionGroup)
+END_METADATA
+
 }  // namespace
 
 //------------------------------------------------------------------------------
diff --git a/ash/style/dot_indicator.cc b/ash/style/dot_indicator.cc
index 403f2dc..8d07b69 100644
--- a/ash/style/dot_indicator.cc
+++ b/ash/style/dot_indicator.cc
@@ -4,6 +4,7 @@
 
 #include "ash/style/dot_indicator.h"
 
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/scoped_canvas.h"
@@ -68,4 +69,7 @@
   canvas->DrawCircle(center, dsf * radius, flags);
 }
 
+BEGIN_METADATA(DotIndicator)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/style/dot_indicator.h b/ash/style/dot_indicator.h
index f6b7d842..8ae90b7 100644
--- a/ash/style/dot_indicator.h
+++ b/ash/style/dot_indicator.h
@@ -6,6 +6,7 @@
 #define ASH_STYLE_DOT_INDICATOR_H_
 
 #include "ash/ash_export.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/view.h"
 
 namespace ash {
@@ -15,6 +16,8 @@
 // set to visible by the owner view. The owner of this component is also
 // responsible for setting the correct bounds on the app icon.
 class ASH_EXPORT DotIndicator : public views::View {
+  METADATA_HEADER(DotIndicator, views::View)
+
  public:
   explicit DotIndicator(SkColor indicator_color);
   DotIndicator(const DotIndicator& other) = delete;
diff --git a/ash/style/drop_down_checkbox.cc b/ash/style/drop_down_checkbox.cc
index 6e318e00..bbf4cc6 100644
--- a/ash/style/drop_down_checkbox.cc
+++ b/ash/style/drop_down_checkbox.cc
@@ -17,6 +17,7 @@
 #include "base/functional/bind.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/list_model_observer.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
@@ -69,6 +70,8 @@
 constexpr int kMenuShadowElevation = 12;
 
 class CheckboxMenuOptionGroup : public CheckboxGroup {
+  METADATA_HEADER(CheckboxMenuOptionGroup, CheckboxGroup)
+
  public:
   CheckboxMenuOptionGroup()
       : CheckboxGroup(kMaxMenuWidth,
@@ -96,6 +99,9 @@
   }
 };
 
+BEGIN_METADATA(CheckboxMenuOptionGroup)
+END_METADATA
+
 }  // namespace
 
 //------------------------------------------------------------------------------
@@ -132,8 +138,9 @@
 //------------------------------------------------------------------------------
 // DropDownCheckbox::MenuView:
 class DropDownCheckbox::MenuView : public views::View {
+  METADATA_HEADER(MenuView, views::View)
+
  public:
-  METADATA_HEADER(MenuView);
   explicit MenuView(DropDownCheckbox* drop_down_check_box)
       : drop_down_checkbox_(drop_down_check_box) {
     SetLayoutManager(std::make_unique<views::FillLayout>());
diff --git a/ash/style/style_viewer/system_ui_components_style_viewer_view.cc b/ash/style/style_viewer/system_ui_components_style_viewer_view.cc
index 80fc498..863a917 100644
--- a/ash/style/style_viewer/system_ui_components_style_viewer_view.cc
+++ b/ash/style/style_viewer/system_ui_components_style_viewer_view.cc
@@ -14,6 +14,8 @@
 #include "base/containers/contains.h"
 #include "base/functional/bind.h"
 #include "chromeos/constants/chromeos_features.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_provider.h"
@@ -59,6 +61,8 @@
 // SystemUIComponentsStyleViewerView::ComponentButton:
 class SystemUIComponentsStyleViewerView::ComponentButton
     : public views::LabelButton {
+  METADATA_HEADER(ComponentButton, views::LabelButton)
+
  public:
   ComponentButton(views::LabelButton::PressedCallback pressed_callback,
                   const std::u16string& name)
@@ -114,6 +118,11 @@
   ui::ColorId text_color_id_ = kInactiveButtonTextColorId;
 };
 
+BEGIN_METADATA(SystemUIComponentsStyleViewerView,
+               ComponentButton,
+               views::LabelButton)
+END_METADATA
+
 // -----------------------------------------------------------------------------
 // SystemUIComponentsStyleViewerView:
 SystemUIComponentsStyleViewerView::SystemUIComponentsStyleViewerView()
@@ -242,4 +251,7 @@
   g_instance = nullptr;
 }
 
+BEGIN_METADATA(SystemUIComponentsStyleViewerView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/style/style_viewer/system_ui_components_style_viewer_view.h b/ash/style/style_viewer/system_ui_components_style_viewer_view.h
index 60a9174..e1de617 100644
--- a/ash/style/style_viewer/system_ui_components_style_viewer_view.h
+++ b/ash/style/style_viewer/system_ui_components_style_viewer_view.h
@@ -9,6 +9,7 @@
 
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/views/widget/widget_observer.h"
 
@@ -36,6 +37,8 @@
 // +----------------------+---------------------------------------+
 class SystemUIComponentsStyleViewerView : public views::WidgetDelegateView,
                                           public views::WidgetObserver {
+  METADATA_HEADER(SystemUIComponentsStyleViewerView, views::WidgetDelegateView)
+
  public:
   // A view factory of `SystemUIComponentsGridView` that shows the UI component
   // instances in a m x n grids.
diff --git a/ash/style/tab_slider.cc b/ash/style/tab_slider.cc
index c31301a..8f19b72 100644
--- a/ash/style/tab_slider.cc
+++ b/ash/style/tab_slider.cc
@@ -11,6 +11,7 @@
 #include "base/functional/callback_helpers.h"
 #include "base/memory/raw_ptr.h"
 #include "base/time/time.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/compositor/layer.h"
@@ -39,6 +40,8 @@
 // selected, it moves from the previously selected button to the currently
 // selected button.
 class TabSlider::SelectorView : public views::View {
+  METADATA_HEADER(SelectorView, views::View)
+
  public:
   explicit SelectorView(bool has_animation) : has_animation_(has_animation) {
     SetPaintToLayer();
@@ -91,6 +94,9 @@
   raw_ptr<TabSliderButton, ExperimentalAsh> button_ = nullptr;
 };
 
+BEGIN_METADATA(TabSlider, SelectorView, views::View)
+END_METADATA
+
 //------------------------------------------------------------------------------
 // TabSlider:
 
diff --git a/ash/test/test_ash_web_view.cc b/ash/test/test_ash_web_view.cc
index 5f4aea3b..ee75467 100644
--- a/ash/test/test_ash_web_view.cc
+++ b/ash/test/test_ash_web_view.cc
@@ -6,6 +6,7 @@
 
 #include "base/functional/bind.h"
 #include "base/task/sequenced_task_runner.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/views/view.h"
 
 namespace ash {
@@ -69,4 +70,7 @@
   return is_error_document_;
 }
 
+BEGIN_METADATA(TestAshWebView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/test/test_ash_web_view.h b/ash/test/test_ash_web_view.h
index 5568ceac..fb4468df 100644
--- a/ash/test/test_ash_web_view.h
+++ b/ash/test/test_ash_web_view.h
@@ -7,6 +7,7 @@
 
 #include "ash/public/cpp/ash_web_view.h"
 #include "base/observer_list.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "url/gurl.h"
 
 namespace views {
@@ -16,6 +17,8 @@
 
 // An implementation of AshWebView for use in unittests.
 class TestAshWebView : public AshWebView {
+  METADATA_HEADER(TestAshWebView, AshWebView)
+
  public:
   explicit TestAshWebView(const AshWebView::InitParams& init_params);
   ~TestAshWebView() override;
diff --git a/ash/touch/touch_hud_renderer.cc b/ash/touch/touch_hud_renderer.cc
index c5a8dbf..3d5fea3 100644
--- a/ash/touch/touch_hud_renderer.cc
+++ b/ash/touch/touch_hud_renderer.cc
@@ -9,6 +9,8 @@
 #include "base/scoped_observation.h"
 #include "base/time/time.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_owner.h"
 #include "ui/events/event.h"
@@ -34,6 +36,8 @@
 class TouchPointView : public views::View,
                        public views::AnimationDelegateViews,
                        public views::WidgetObserver {
+  METADATA_HEADER(TouchPointView, views::View)
+
  public:
   explicit TouchPointView(views::Widget* parent_widget)
       : views::AnimationDelegateViews(this) {
@@ -127,6 +131,9 @@
       widget_observation_{this};
 };
 
+BEGIN_METADATA(TouchPointView)
+END_METADATA
+
 TouchHudRenderer::TouchHudRenderer(views::Widget* parent_widget)
     : parent_widget_(parent_widget) {
   parent_widget_->AddObserver(this);
diff --git a/ash/wallpaper/views/wallpaper_view.cc b/ash/wallpaper/views/wallpaper_view.cc
index 74239c1f..3fc69d7 100644
--- a/ash/wallpaper/views/wallpaper_view.cc
+++ b/ash/wallpaper/views/wallpaper_view.cc
@@ -17,6 +17,7 @@
 #include "ui/aura/window.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer.h"
 #include "ui/display/display.h"
 #include "ui/display/manager/display_manager.h"
@@ -325,4 +326,7 @@
   return wallpaper_widget;
 }
 
+BEGIN_METADATA(WallpaperView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/wallpaper/views/wallpaper_view.h b/ash/wallpaper/views/wallpaper_view.h
index d5af0dd..665bfe65 100644
--- a/ash/wallpaper/views/wallpaper_view.h
+++ b/ash/wallpaper/views/wallpaper_view.h
@@ -10,6 +10,7 @@
 #include "ash/wallpaper/views/wallpaper_base_view.h"
 #include "ash/wallpaper/wallpaper_constants.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/context_menu_controller.h"
 
 namespace aura {
@@ -22,6 +23,8 @@
 // also add blur and dimming effects, as well as handle context menu requests.
 class WallpaperView : public WallpaperBaseView,
                       public views::ContextMenuController {
+  METADATA_HEADER(WallpaperView, WallpaperBaseView)
+
  public:
   explicit WallpaperView(float blur_sigma);
 
diff --git a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc
index 36460624..9ed9ec74 100644
--- a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc
+++ b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc
@@ -15,6 +15,8 @@
 #include "base/i18n/rtl.h"
 #include "base/timer/timer.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
@@ -107,6 +109,8 @@
 class BackGestureContextualNudge::ContextualNudgeView
     : public views::View,
       public ui::ImplicitAnimationObserver {
+  METADATA_HEADER(ContextualNudgeView, views::View)
+
  public:
   explicit ContextualNudgeView(base::OnceCallback<void(bool)> callback)
       : callback_(std::move(callback)) {
@@ -167,6 +171,8 @@
   // affordance and a label.
   class SuggestionView : public views::View,
                          public ui::ImplicitAnimationObserver {
+    METADATA_HEADER(SuggestionView, views::View)
+
    public:
     explicit SuggestionView(ContextualNudgeView* nudge_view)
         : nudge_view_(nudge_view) {
@@ -372,6 +378,14 @@
   base::OnceCallback<void(bool)> callback_;
 };
 
+BEGIN_METADATA(BackGestureContextualNudge, ContextualNudgeView, views::View)
+END_METADATA
+
+BEGIN_METADATA(BackGestureContextualNudge::ContextualNudgeView,
+               SuggestionView,
+               views::View)
+END_METADATA
+
 BackGestureContextualNudge::BackGestureContextualNudge(
     base::OnceCallback<void(bool)> callback) {
   widget_ = CreateWidget();
diff --git a/ash/wm/overview/glanceables/glanceables_bar_view.cc b/ash/wm/overview/glanceables/glanceables_bar_view.cc
index 4ef888b4..76f8428c 100644
--- a/ash/wm/overview/glanceables/glanceables_bar_view.cc
+++ b/ash/wm/overview/glanceables/glanceables_bar_view.cc
@@ -12,6 +12,8 @@
 #include "ash/wm/work_area_insets.h"
 #include "base/functional/bind.h"
 #include "base/time/time.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer.h"
 #include "ui/gfx/geometry/transform_util.h"
 #include "ui/views/animation/animation_builder.h"
@@ -41,6 +43,8 @@
 // The chips container with glanceables chips and hiding chips button.
 class GlanceablesBarView::GlanceablesChipsContainer
     : public views::BoxLayoutView {
+  METADATA_HEADER(GlanceablesChipsContainer, views::BoxLayoutView)
+
  public:
   explicit GlanceablesChipsContainer(GlanceablesBarView* glanceable_bar)
       : glanceable_bar_(glanceable_bar) {
@@ -79,6 +83,11 @@
   raw_ptr<IconButton> hide_glanceables_button_;
 };
 
+BEGIN_METADATA(GlanceablesBarView,
+               GlanceablesChipsContainer,
+               views::BoxLayoutView)
+END_METADATA
+
 //------------------------------------------------------------------------------
 // GlanceablesBarView
 GlanceablesBarView::GlanceablesBarView() {
@@ -218,4 +227,7 @@
                     show ? gfx::Transform() : vertical_shift);
 }
 
+BEGIN_METADATA(GlanceablesBarView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/wm/overview/glanceables/glanceables_bar_view.h b/ash/wm/overview/glanceables/glanceables_bar_view.h
index 43434ad..6518235 100644
--- a/ash/wm/overview/glanceables/glanceables_bar_view.h
+++ b/ash/wm/overview/glanceables/glanceables_bar_view.h
@@ -5,6 +5,7 @@
 #ifndef ASH_WM_OVERVIEW_GLANCEABLES_GLANCEABLES_BAR_VIEW_H_
 #define ASH_WM_OVERVIEW_GLANCEABLES_GLANCEABLES_BAR_VIEW_H_
 
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/models/image_model.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/view.h"
@@ -18,6 +19,8 @@
 // hiding button, the glanceables chips will fade out and the showing chips
 // button will appear in the center.
 class GlanceablesBarView : public views::View {
+  METADATA_HEADER(GlanceablesBarView, views::View)
+
  public:
   // TODO(zxdan): When the data model is implemented, pass in the model to
   // generate glanceable chips.
diff --git a/ash/wm/splitview/split_view_divider_handler_view.cc b/ash/wm/splitview/split_view_divider_handler_view.cc
index 69898d5c..ff0a15d2 100644
--- a/ash/wm/splitview/split_view_divider_handler_view.cc
+++ b/ash/wm/splitview/split_view_divider_handler_view.cc
@@ -12,6 +12,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/timer/timer.h"
 #include "chromeos/constants/chromeos_features.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/color/color_id.h"
 #include "ui/compositor/layer.h"
@@ -167,4 +168,7 @@
   views::View::OnPaint(canvas);
 }
 
+BEGIN_METADATA(SplitViewDividerHandlerView)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/wm/splitview/split_view_divider_handler_view.h b/ash/wm/splitview/split_view_divider_handler_view.h
index eeff56e..953245c3 100644
--- a/ash/wm/splitview/split_view_divider_handler_view.h
+++ b/ash/wm/splitview/split_view_divider_handler_view.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/gfx/canvas.h"
 #include "ui/views/view.h"
 
@@ -14,6 +15,8 @@
 
 // The white handler bar in the middle of the divider.
 class SplitViewDividerHandlerView : public views::View {
+  METADATA_HEADER(SplitViewDividerHandlerView, views::View)
+
  public:
   SplitViewDividerHandlerView();
 
diff --git a/ash/wm/window_restore/informed_restore_dialog.cc b/ash/wm/window_restore/informed_restore_dialog.cc
index e402201..fdd4645 100644
--- a/ash/wm/window_restore/informed_restore_dialog.cc
+++ b/ash/wm/window_restore/informed_restore_dialog.cc
@@ -118,9 +118,13 @@
     auto* delegate = Shell::Get()->saved_desk_delegate();
     for (const std::string& app_id : app_ids) {
       std::string title;
-      cache->ForOneApp(app_id, [&title](const apps::AppUpdate& update) {
-        title = update.Name();
-      });
+      // `cache` might be null in a test environment. In that case, we will use
+      // an empty title.
+      if (cache) {
+        cache->ForOneApp(app_id, [&title](const apps::AppUpdate& update) {
+          title = update.Name();
+        });
+      }
 
       auto item_view = std::make_unique<InformedRestoreItemView>(title);
       auto* item_view_ptr = item_view.get();
diff --git a/ash/wm/window_restore/informed_restore_dialog_unittest.cc b/ash/wm/window_restore/informed_restore_dialog_unittest.cc
new file mode 100644
index 0000000..d301be16
--- /dev/null
+++ b/ash/wm/window_restore/informed_restore_dialog_unittest.cc
@@ -0,0 +1,31 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/wm/window_restore/informed_restore_dialog.h"
+
+#include "ash/shell.h"
+#include "ash/test/ash_test_base.h"
+#include "ash/wm/window_restore/window_restore_controller.h"
+#include "base/test/scoped_feature_list.h"
+
+namespace ash {
+
+class InformedRestoreDialogTest : public AshTestBase {
+ public:
+  InformedRestoreDialogTest() = default;
+  InformedRestoreDialogTest(const InformedRestoreDialogTest&) = delete;
+  InformedRestoreDialogTest& operator=(const InformedRestoreDialogTest&) =
+      delete;
+  ~InformedRestoreDialogTest() override = default;
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_{
+      features::kPostLoginGlanceables};
+};
+
+TEST_F(InformedRestoreDialogTest, Show) {
+  Shell::Get()->window_restore_controller()->MaybeStartInformedRestore();
+}
+
+}  // namespace ash
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 7f1993c..fb5aab4 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -629,6 +629,8 @@
     "strings/escape.h",
     "strings/latin1_string_conversions.cc",
     "strings/latin1_string_conversions.h",
+    "strings/levenshtein_distance.cc",
+    "strings/levenshtein_distance.h",
     "strings/pattern.cc",
     "strings/pattern.h",
     "strings/safe_sprintf.cc",
@@ -3297,6 +3299,7 @@
     "stl_util_unittest.cc",
     "strings/abseil_string_number_conversions_unittest.cc",
     "strings/escape_unittest.cc",
+    "strings/levenshtein_distance_unittest.cc",
     "strings/no_trigraphs_unittest.cc",
     "strings/pattern_unittest.cc",
     "strings/safe_sprintf_unittest.cc",
@@ -4136,6 +4139,7 @@
       "task/bind_post_task_nocompile.nc",
       "task/task_traits_nocompile.nc",
       "thread_annotations_nocompile.nc",
+      "types/pass_key_nocompile.nc",
       "types/variant_util_nocompile.nc",
       "values_nocompile.nc",
     ]
@@ -4159,7 +4163,6 @@
       "metrics/histogram_nocompile.nc",
       "strings/string_piece_nocompile.nc",
       "traits_bag_nocompile.nc",
-      "types/pass_key_nocompile.nc",
     ]
 
     deps = [
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index 5caeab5f..638d9bdf 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -51,6 +51,15 @@
 #define NOINLINE
 #endif
 
+// Annotate a function indicating it should not be optimized.
+#if defined(__clang__) && HAS_ATTRIBUTE(optnone)
+#define NOOPT [[clang::optnone]]
+#elif defined(COMPILER_GCC) && HAS_ATTRIBUTE(optimize)
+#define NOOPT __attribute__((optimize(0)))
+#else
+#define NOOPT
+#endif
+
 #if defined(__clang__) && defined(NDEBUG) && HAS_ATTRIBUTE(always_inline)
 #define ALWAYS_INLINE [[clang::always_inline]] inline
 #elif defined(COMPILER_GCC) && defined(NDEBUG) && HAS_ATTRIBUTE(always_inline)
diff --git a/base/debug/stack_trace_unittest.cc b/base/debug/stack_trace_unittest.cc
index 0662aa85..436ce78 100644
--- a/base/debug/stack_trace_unittest.cc
+++ b/base/debug/stack_trace_unittest.cc
@@ -348,9 +348,9 @@
 }
 
 template <size_t Depth>
-NOINLINE void ExpectStackFramePointers(const void** frames,
-                                       size_t max_depth,
-                                       bool copy_stack) {
+NOINLINE NOOPT void ExpectStackFramePointers(const void** frames,
+                                             size_t max_depth,
+                                             bool copy_stack) {
 code_start:
   // Calling __builtin_frame_address() forces compiler to emit
   // frame pointers, even if they are not enabled.
@@ -366,9 +366,9 @@
 }
 
 template <>
-NOINLINE void ExpectStackFramePointers<1>(const void** frames,
-                                          size_t max_depth,
-                                          bool copy_stack) {
+NOINLINE NOOPT void ExpectStackFramePointers<1>(const void** frames,
+                                                size_t max_depth,
+                                                bool copy_stack) {
 code_start:
   // Calling __builtin_frame_address() forces compiler to emit
   // frame pointers, even if they are not enabled.
diff --git a/base/file_version_info_win_unittest.cc b/base/file_version_info_win_unittest.cc
index 8a6c8246..7d7d7ae 100644
--- a/base/file_version_info_win_unittest.cc
+++ b/base/file_version_info_win_unittest.cc
@@ -105,25 +105,25 @@
 
   int j = 0;
   EXPECT_EQ(kExpectedValues[j++],
-            base::AsWStringPiece(version_info->company_name()));
+            base::AsWStringView(version_info->company_name()));
   EXPECT_EQ(kExpectedValues[j++],
-            base::AsWStringPiece(version_info->company_short_name()));
+            base::AsWStringView(version_info->company_short_name()));
   EXPECT_EQ(kExpectedValues[j++],
-            base::AsWStringPiece(version_info->product_name()));
+            base::AsWStringView(version_info->product_name()));
   EXPECT_EQ(kExpectedValues[j++],
-            base::AsWStringPiece(version_info->product_short_name()));
+            base::AsWStringView(version_info->product_short_name()));
   EXPECT_EQ(kExpectedValues[j++],
-            base::AsWStringPiece(version_info->internal_name()));
+            base::AsWStringView(version_info->internal_name()));
   EXPECT_EQ(kExpectedValues[j++],
-            base::AsWStringPiece(version_info->product_version()));
+            base::AsWStringView(version_info->product_version()));
   EXPECT_EQ(kExpectedValues[j++],
-            base::AsWStringPiece(version_info->special_build()));
+            base::AsWStringView(version_info->special_build()));
   EXPECT_EQ(kExpectedValues[j++],
-            base::AsWStringPiece(version_info->original_filename()));
+            base::AsWStringView(version_info->original_filename()));
   EXPECT_EQ(kExpectedValues[j++],
-            base::AsWStringPiece(version_info->file_description()));
+            base::AsWStringView(version_info->file_description()));
   EXPECT_EQ(kExpectedValues[j++],
-            base::AsWStringPiece(version_info->file_version()));
+            base::AsWStringView(version_info->file_version()));
 }
 
 TYPED_TEST(FileVersionInfoTest, CustomProperties) {
diff --git a/base/files/file_path.cc b/base/files/file_path.cc
index 2b2f81a..ef8100c 100644
--- a/base/files/file_path.cc
+++ b/base/files/file_path.cc
@@ -664,7 +664,7 @@
 
 // static
 FilePath FilePath::FromUTF16Unsafe(StringPiece16 utf16) {
-  return FilePath(AsWStringPiece(utf16));
+  return FilePath(AsWStringView(utf16));
 }
 
 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
diff --git a/base/stack_canary_linux_unittest.cc b/base/stack_canary_linux_unittest.cc
index f3dc1f1..3bdaeab9 100644
--- a/base/stack_canary_linux_unittest.cc
+++ b/base/stack_canary_linux_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "base/stack_canary_linux.h"
 
+#include "base/compiler_specific.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -13,12 +14,7 @@
     (defined(ARCH_CPU_ARM_FAMILY) || defined(ARCH_CPU_X86_FAMILY))
 
 namespace {
-#if defined(COMPILER_GCC) && !defined(__clang__)
-__attribute__((noinline, optimize(0)))
-#else
-__attribute__((noinline, optnone))
-#endif
-void ResetCanaryAndReturn() {
+NOINLINE NOOPT void ResetCanaryAndReturn() {
   // Create a buffer >=8 bytes to force the stack protector on this function,
   // which should work as long as -fno-stack-protector isn't passed in the
   // default options. We compile this file with -fstack-protector-all, but it
diff --git a/base/strings/levenshtein_distance.cc b/base/strings/levenshtein_distance.cc
new file mode 100644
index 0000000..7b6b379f
--- /dev/null
+++ b/base/strings/levenshtein_distance.cc
@@ -0,0 +1,102 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/levenshtein_distance.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <numeric>
+#include <optional>
+#include <string_view>
+#include <vector>
+
+namespace base {
+
+namespace {
+
+template <typename CharT>
+size_t LevenshteinDistanceImpl(std::basic_string_view<CharT> a,
+                               std::basic_string_view<CharT> b,
+                               std::optional<size_t> max_distance) {
+  if (a.size() > b.size()) {
+    a.swap(b);
+  }
+
+  // max(a.size(), b.size()) steps always suffice.
+  const size_t k = max_distance.value_or(b.size());
+  // If the string's lengths differ by more than `k`, so does their
+  // Levenshtein distance.
+  if (a.size() + k < b.size()) {
+    return k + 1;
+  }
+  // The classical Levenshtein distance DP defines dp[i][j] as the minimum
+  // number of insert, remove and replace operation to convert a[:i] to b[:j].
+  // To make this more efficient, one can define dp[i][d] as the distance of
+  // a[:i] and b[:i + d]. Intuitively, d represents the delta between j and i in
+  // the former dp. Since the Levenshtein distance is restricted by `k`, abs(d)
+  // can be bounded by `k`. Since dp[i][d] only depends on values from dp[i-1],
+  // it is not necessary to store the entire 2D table. Instead, this code just
+  // stores the d-dimension, which represents "the distance with the current
+  // prefix of the string, for a given delta d". Since d is between `-k` and
+  // `k`, the implementation shifts the d-index by `k`, bringing it in range
+  // [0, `2*k`].
+
+  // The algorithm only cares if the Levenshtein distance is at most `k`. Thus,
+  // any unreachable states and states in which the distance is certainly larger
+  // than `k` can be set to any value larger than `k`, without affecting the
+  // result.
+  const size_t kInfinity = k + 1;
+  std::vector<size_t> dp(2 * k + 1, kInfinity);
+  // Initially, `dp[d]` represents the Levenshtein distance of the empty prefix
+  // of `a` and the first j = d - k characters of `b`. Their distance is j,
+  // since j removals are required. States with negative d are not reachable,
+  // since that corresponds to a negative index into `b`.
+  std::iota(dp.begin() + static_cast<long>(k), dp.end(), 0);
+  for (size_t i = 0; i < a.size(); i++) {
+    // Right now, `dp` represents the Levenshtein distance when considering the
+    // first `i` characters (up to index `i-1`) of `a`. After the next loop,
+    // `dp` will represent the Levenshtein distance when considering the first
+    // `i+1` characters.
+    for (size_t d = 0; d <= 2 * k; d++) {
+      if (i + d < k || i + d >= b.size() + k) {
+        // `j = i + d - k` is out of range of `b`. Since j == -1 corresponds to
+        // the empty prefix of `b`, the distance is i + 1 in this case.
+        dp[d] = i + d + 1 == k ? i + 1 : kInfinity;
+        continue;
+      }
+      const size_t j = i + d - k;
+      // If `a[i] == `b[j]` the Levenshtein distance for `d` remained the same.
+      if (a[i] != b[j]) {
+        // (i, j) -> (i-1, j-1), `d` stays the same.
+        const size_t replace = dp[d];
+        // (i, j) -> (i-1, j), `d` increases by 1.
+        // If the distance between `i` and `j` becomes larger than `k`, their
+        // distance is at least `k + 1`. Same in the `insert` case.
+        const size_t remove = d != 2 * k ? dp[d + 1] : kInfinity;
+        // (i, j) -> (i, j-1), `d` decreases by 1. Since `i` stays the same,
+        // this is intentionally using the dp value updated in the previous
+        // iteration.
+        const size_t insert = d != 0 ? dp[d - 1] : kInfinity;
+        dp[d] = 1 + std::min({replace, remove, insert});
+      }
+    }
+  }
+  return std::min(dp[b.size() + k - a.size()], k + 1);
+}
+
+}  // namespace
+
+size_t LevenshteinDistance(std::string_view a,
+                           std::string_view b,
+                           std::optional<size_t> max_distance) {
+  return LevenshteinDistanceImpl(a, b, max_distance);
+}
+size_t LevenshteinDistance(std::u16string_view a,
+                           std::u16string_view b,
+                           std::optional<size_t> max_distance) {
+  return LevenshteinDistanceImpl(a, b, max_distance);
+}
+
+}  // namespace base
diff --git a/base/strings/levenshtein_distance.h b/base/strings/levenshtein_distance.h
new file mode 100644
index 0000000..7ec6149
--- /dev/null
+++ b/base/strings/levenshtein_distance.h
@@ -0,0 +1,37 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_STRINGS_LEVENSHTEIN_DISTANCE_H_
+#define BASE_STRINGS_LEVENSHTEIN_DISTANCE_H_
+
+#include <stddef.h>
+
+#include <optional>
+#include <string_view>
+
+#include "base/base_export.h"
+
+namespace base {
+
+// Returns the Levenshtein distance of `a` and `b`. Edits, inserts and removes
+// each count as one step.
+// If `k = max_distance` is provided, the distance is only correctly calculated
+// up to k. In case the actual Levenshtein distance is larger than k, k+1 is
+// returned instead. This is useful for checking whether the distance is at most
+// some small constant, since the algorithm is more efficient in this case.
+// Complexity:
+// - Without k: O(|a| * |b|) time and O(max(|a|, |b|)) memory.
+// - With k: O(min(|a|, |b|) * k + k) time and O(k) memory.
+BASE_EXPORT size_t
+LevenshteinDistance(std::string_view a,
+                    std::string_view b,
+                    std::optional<size_t> max_distance = std::nullopt);
+BASE_EXPORT size_t
+LevenshteinDistance(std::u16string_view a,
+                    std::u16string_view b,
+                    std::optional<size_t> max_distance = std::nullopt);
+
+}  // namespace base
+
+#endif  // BASE_STRINGS_LEVENSHTEIN_DISTANCE_H_
diff --git a/base/strings/levenshtein_distance_unittest.cc b/base/strings/levenshtein_distance_unittest.cc
new file mode 100644
index 0000000..8854d3f
--- /dev/null
+++ b/base/strings/levenshtein_distance_unittest.cc
@@ -0,0 +1,67 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/levenshtein_distance.h"
+
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+TEST(LevenshteinDistanceTest, WithoutMaxDistance) {
+  EXPECT_EQ(0u, LevenshteinDistance("banana", "banana"));
+
+  EXPECT_EQ(2u, LevenshteinDistance("ab", "ba"));
+  EXPECT_EQ(2u, LevenshteinDistance("ba", "ab"));
+
+  EXPECT_EQ(2u, LevenshteinDistance("ananas", "banana"));
+  EXPECT_EQ(2u, LevenshteinDistance("banana", "ananas"));
+
+  EXPECT_EQ(2u, LevenshteinDistance("unclear", "nuclear"));
+  EXPECT_EQ(2u, LevenshteinDistance("nuclear", "unclear"));
+
+  EXPECT_EQ(3u, LevenshteinDistance("chrome", "chromium"));
+  EXPECT_EQ(3u, LevenshteinDistance("chromium", "chrome"));
+
+  EXPECT_EQ(4u, LevenshteinDistance("", "abcd"));
+  EXPECT_EQ(4u, LevenshteinDistance("abcd", ""));
+
+  // `std::u16string_view` version.
+  EXPECT_EQ(4u, LevenshteinDistance(u"xxx", u"xxxxxxx"));
+  EXPECT_EQ(4u, LevenshteinDistance(u"xxxxxxx", u"xxx"));
+
+  EXPECT_EQ(7u, LevenshteinDistance(u"yyy", u"xxxxxxx"));
+  EXPECT_EQ(7u, LevenshteinDistance(u"xxxxxxx", u"yyy"));
+}
+
+TEST(LevenshteinDistanceTest, WithMaxDistance) {
+  EXPECT_EQ(LevenshteinDistance("aa", "aa", 0), 0u);
+
+  EXPECT_EQ(LevenshteinDistance("a", "aa", 1), 1u);
+  EXPECT_EQ(LevenshteinDistance("aa", "a", 1), 1u);
+
+  // If k is less than `LevenshteinDistance()`, the function should return k+1.
+  EXPECT_EQ(LevenshteinDistance("", "12", 1), 2u);
+  EXPECT_EQ(LevenshteinDistance("12", "", 1), 2u);
+
+  EXPECT_EQ(LevenshteinDistance("street", "str.", 1), 2u);
+  EXPECT_EQ(LevenshteinDistance("str.", "street", 1), 2u);
+
+  EXPECT_EQ(LevenshteinDistance("asdf", "fdsa", 2), 3u);
+  EXPECT_EQ(LevenshteinDistance("fdsa", "asdf", 2), 3u);
+
+  EXPECT_EQ(LevenshteinDistance(std::u16string(100, 'a'),
+                                std::u16string(200, 'a'), 50),
+            51u);
+  EXPECT_EQ(LevenshteinDistance(std::u16string(200, 'a'),
+                                std::u16string(100, 'a'), 50),
+            51u);
+}
+
+}  // namespace
+
+}  // namespace base
diff --git a/base/strings/strcat_win.cc b/base/strings/strcat_win.cc
index ce5079f..7a74e36 100644
--- a/base/strings/strcat_win.cc
+++ b/base/strings/strcat_win.cc
@@ -5,14 +5,14 @@
 #include "base/strings/strcat_win.h"
 
 #include <string>
+#include <string_view>
 
 #include "base/containers/span.h"
 #include "base/strings/strcat_internal.h"
-#include "base/strings/string_piece.h"
 
 namespace base {
 
-std::wstring StrCat(span<const WStringPiece> pieces) {
+std::wstring StrCat(span<const std::wstring_view> pieces) {
   return internal::StrCatT(pieces);
 }
 
@@ -20,7 +20,7 @@
   return internal::StrCatT(pieces);
 }
 
-void StrAppend(std::wstring* dest, span<const WStringPiece> pieces) {
+void StrAppend(std::wstring* dest, span<const std::wstring_view> pieces) {
   internal::StrAppendT(*dest, pieces);
 }
 
diff --git a/base/strings/strcat_win.h b/base/strings/strcat_win.h
index f103d829..e230373f 100644
--- a/base/strings/strcat_win.h
+++ b/base/strings/strcat_win.h
@@ -7,27 +7,29 @@
 
 #include <initializer_list>
 #include <string>
+#include <string_view>
 
 #include "base/base_export.h"
 #include "base/containers/span.h"
-#include "base/strings/string_piece.h"
 
 namespace base {
 
 // The following section contains overloads of the cross-platform APIs for
-// std::wstring and base::WStringPiece.
-BASE_EXPORT void StrAppend(std::wstring* dest, span<const WStringPiece> pieces);
+// std::wstring and std::wstring_view.
+BASE_EXPORT void StrAppend(std::wstring* dest,
+                           span<const std::wstring_view> pieces);
 BASE_EXPORT void StrAppend(std::wstring* dest, span<const std::wstring> pieces);
 
 inline void StrAppend(std::wstring* dest,
-                      std::initializer_list<WStringPiece> pieces) {
+                      std::initializer_list<std::wstring_view> pieces) {
   StrAppend(dest, make_span(pieces));
 }
 
-[[nodiscard]] BASE_EXPORT std::wstring StrCat(span<const WStringPiece> pieces);
+[[nodiscard]] BASE_EXPORT std::wstring StrCat(
+    span<const std::wstring_view> pieces);
 [[nodiscard]] BASE_EXPORT std::wstring StrCat(span<const std::wstring> pieces);
 
-inline std::wstring StrCat(std::initializer_list<WStringPiece> pieces) {
+inline std::wstring StrCat(std::initializer_list<std::wstring_view> pieces) {
   return StrCat(make_span(pieces));
 }
 
diff --git a/base/strings/string_number_conversions_win.cc b/base/strings/string_number_conversions_win.cc
index 8caa0ce..d1910175 100644
--- a/base/strings/string_number_conversions_win.cc
+++ b/base/strings/string_number_conversions_win.cc
@@ -5,9 +5,9 @@
 #include "base/strings/string_number_conversions_win.h"
 
 #include <string>
+#include <string_view>
 
 #include "base/strings/string_number_conversions_internal.h"
-#include "base/strings/string_piece.h"
 
 namespace base {
 
@@ -39,27 +39,27 @@
   return internal::DoubleToStringT<std::wstring>(value);
 }
 
-bool StringToInt(WStringPiece input, int* output) {
+bool StringToInt(std::wstring_view input, int* output) {
   return internal::StringToIntImpl(input, *output);
 }
 
-bool StringToUint(WStringPiece input, unsigned* output) {
+bool StringToUint(std::wstring_view input, unsigned* output) {
   return internal::StringToIntImpl(input, *output);
 }
 
-bool StringToInt64(WStringPiece input, int64_t* output) {
+bool StringToInt64(std::wstring_view input, int64_t* output) {
   return internal::StringToIntImpl(input, *output);
 }
 
-bool StringToUint64(WStringPiece input, uint64_t* output) {
+bool StringToUint64(std::wstring_view input, uint64_t* output) {
   return internal::StringToIntImpl(input, *output);
 }
 
-bool StringToSizeT(WStringPiece input, size_t* output) {
+bool StringToSizeT(std::wstring_view input, size_t* output) {
   return internal::StringToIntImpl(input, *output);
 }
 
-bool StringToDouble(WStringPiece input, double* output) {
+bool StringToDouble(std::wstring_view input, double* output) {
   return internal::StringToDoubleImpl(
       input, reinterpret_cast<const uint16_t*>(input.data()), *output);
 }
diff --git a/base/strings/string_number_conversions_win.h b/base/strings/string_number_conversions_win.h
index c167e5f..dd28d17 100644
--- a/base/strings/string_number_conversions_win.h
+++ b/base/strings/string_number_conversions_win.h
@@ -6,9 +6,9 @@
 #define BASE_STRINGS_STRING_NUMBER_CONVERSIONS_WIN_H_
 
 #include <string>
+#include <string_view>
 
 #include "base/base_export.h"
-#include "base/strings/string_piece.h"
 
 namespace base {
 
@@ -21,13 +21,13 @@
 BASE_EXPORT std::wstring NumberToWString(double value);
 
 // The following section contains overloads of the cross-platform APIs for
-// std::wstring and base::WStringPiece.
-BASE_EXPORT bool StringToInt(WStringPiece input, int* output);
-BASE_EXPORT bool StringToUint(WStringPiece input, unsigned* output);
-BASE_EXPORT bool StringToInt64(WStringPiece input, int64_t* output);
-BASE_EXPORT bool StringToUint64(WStringPiece input, uint64_t* output);
-BASE_EXPORT bool StringToSizeT(WStringPiece input, size_t* output);
-BASE_EXPORT bool StringToDouble(WStringPiece input, double* output);
+// std::wstring and std::wstring_view.
+BASE_EXPORT bool StringToInt(std::wstring_view input, int* output);
+BASE_EXPORT bool StringToUint(std::wstring_view input, unsigned* output);
+BASE_EXPORT bool StringToInt64(std::wstring_view input, int64_t* output);
+BASE_EXPORT bool StringToUint64(std::wstring_view input, uint64_t* output);
+BASE_EXPORT bool StringToSizeT(std::wstring_view input, size_t* output);
+BASE_EXPORT bool StringToDouble(std::wstring_view input, double* output);
 
 }  // namespace base
 
diff --git a/base/strings/string_split_win.cc b/base/strings/string_split_win.cc
index 59151e3..3e0f30a 100644
--- a/base/strings/string_split_win.cc
+++ b/base/strings/string_split_win.cc
@@ -5,6 +5,7 @@
 #include "base/strings/string_split_win.h"
 
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/strings/string_piece.h"
@@ -15,42 +16,42 @@
 namespace internal {
 
 template <>
-inline WStringPiece WhitespaceForType<wchar_t>() {
+inline std::wstring_view WhitespaceForType<wchar_t>() {
   return kWhitespaceWide;
 }
 
 }  // namespace internal
 
-std::vector<std::wstring> SplitString(WStringPiece input,
-                                      WStringPiece separators,
+std::vector<std::wstring> SplitString(std::wstring_view input,
+                                      std::wstring_view separators,
                                       WhitespaceHandling whitespace,
                                       SplitResult result_type) {
   return internal::SplitStringT<std::wstring>(input, separators, whitespace,
                                               result_type);
 }
 
-std::vector<WStringPiece> SplitStringPiece(WStringPiece input,
-                                           WStringPiece separators,
-                                           WhitespaceHandling whitespace,
-                                           SplitResult result_type) {
-  return internal::SplitStringT<WStringPiece>(input, separators, whitespace,
-                                              result_type);
+std::vector<std::wstring_view> SplitStringPiece(std::wstring_view input,
+                                                std::wstring_view separators,
+                                                WhitespaceHandling whitespace,
+                                                SplitResult result_type) {
+  return internal::SplitStringT<std::wstring_view>(input, separators,
+                                                   whitespace, result_type);
 }
 
-std::vector<std::wstring> SplitStringUsingSubstr(WStringPiece input,
-                                                 WStringPiece delimiter,
+std::vector<std::wstring> SplitStringUsingSubstr(std::wstring_view input,
+                                                 std::wstring_view delimiter,
                                                  WhitespaceHandling whitespace,
                                                  SplitResult result_type) {
   return internal::SplitStringUsingSubstrT<std::wstring>(
       input, delimiter, whitespace, result_type);
 }
 
-std::vector<WStringPiece> SplitStringPieceUsingSubstr(
-    WStringPiece input,
-    WStringPiece delimiter,
+std::vector<std::wstring_view> SplitStringPieceUsingSubstr(
+    std::wstring_view input,
+    std::wstring_view delimiter,
     WhitespaceHandling whitespace,
     SplitResult result_type) {
-  return internal::SplitStringUsingSubstrT<WStringPiece>(
+  return internal::SplitStringUsingSubstrT<std::wstring_view>(
       input, delimiter, whitespace, result_type);
 }
 
diff --git a/base/strings/string_split_win.h b/base/strings/string_split_win.h
index 98dd515..de29758 100644
--- a/base/strings/string_split_win.h
+++ b/base/strings/string_split_win.h
@@ -6,6 +6,7 @@
 #define BASE_STRINGS_STRING_SPLIT_WIN_H_
 
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/base_export.h"
@@ -15,30 +16,30 @@
 namespace base {
 
 // The following section contains overloads of the cross-platform APIs for
-// std::wstring and base::WStringPiece.
+// std::wstring and std::wstring_view.
 [[nodiscard]] BASE_EXPORT std::vector<std::wstring> SplitString(
-    WStringPiece input,
-    WStringPiece separators,
+    std::wstring_view input,
+    std::wstring_view separators,
     WhitespaceHandling whitespace,
     SplitResult result_type);
 
-[[nodiscard]] BASE_EXPORT std::vector<WStringPiece> SplitStringPiece(
-    WStringPiece input,
-    WStringPiece separators,
+[[nodiscard]] BASE_EXPORT std::vector<std::wstring_view> SplitStringPiece(
+    std::wstring_view input,
+    std::wstring_view separators,
     WhitespaceHandling whitespace,
     SplitResult result_type);
 
 [[nodiscard]] BASE_EXPORT std::vector<std::wstring> SplitStringUsingSubstr(
-    WStringPiece input,
-    WStringPiece delimiter,
+    std::wstring_view input,
+    std::wstring_view delimiter,
     WhitespaceHandling whitespace,
     SplitResult result_type);
 
-[[nodiscard]] BASE_EXPORT std::vector<WStringPiece> SplitStringPieceUsingSubstr(
-    WStringPiece input,
-    WStringPiece delimiter,
-    WhitespaceHandling whitespace,
-    SplitResult result_type);
+[[nodiscard]] BASE_EXPORT std::vector<std::wstring_view>
+SplitStringPieceUsingSubstr(std::wstring_view input,
+                            std::wstring_view delimiter,
+                            WhitespaceHandling whitespace,
+                            SplitResult result_type);
 
 }  // namespace base
 
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc
index 08917057..89477b6 100644
--- a/base/strings/string_util.cc
+++ b/base/strings/string_util.cc
@@ -15,6 +15,7 @@
 #include <wchar.h>
 
 #include <limits>
+#include <string_view>
 #include <type_traits>
 #include <vector>
 
@@ -234,7 +235,7 @@
 }
 
 #if defined(WCHAR_T_IS_32_BIT)
-bool IsStringASCII(WStringPiece str) {
+bool IsStringASCII(std::wstring_view str) {
   return internal::DoIsStringASCII(str.data(), str.length());
 }
 #endif
diff --git a/base/strings/string_util.h b/base/strings/string_util.h
index 53b17281..68aa069 100644
--- a/base/strings/string_util.h
+++ b/base/strings/string_util.h
@@ -7,12 +7,13 @@
 #ifndef BASE_STRINGS_STRING_UTIL_H_
 #define BASE_STRINGS_STRING_UTIL_H_
 
-#include <stdarg.h>   // va_list
+#include <stdarg.h>  // va_list
 #include <stddef.h>
 #include <stdint.h>
 
 #include <initializer_list>
 #include <string>
+#include <string_view>
 #include <type_traits>
 #include <vector>
 
@@ -108,7 +109,7 @@
 }
 
 template <typename Iter>
-constexpr WStringPiece MakeWStringPiece(Iter begin, Iter end) {
+constexpr std::wstring_view MakeWStringView(Iter begin, Iter end) {
   return MakeBasicStringPiece<wchar_t>(begin, end);
 }
 
@@ -345,7 +346,7 @@
 BASE_EXPORT bool IsStringASCII(StringPiece16 str);
 
 #if defined(WCHAR_T_IS_32_BIT)
-BASE_EXPORT bool IsStringASCII(WStringPiece str);
+BASE_EXPORT bool IsStringASCII(std::wstring_view str);
 #endif
 
 // Performs a case-sensitive string compare of the given 16-bit string against
diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc
index b1b7ced..e862fb51 100644
--- a/base/strings/string_util_unittest.cc
+++ b/base/strings/string_util_unittest.cc
@@ -11,6 +11,7 @@
 
 #include <algorithm>
 #include <string>
+#include <string_view>
 #include <type_traits>
 
 #include "base/bits.h"
@@ -399,7 +400,7 @@
                 "");
   EXPECT_EQ(static_cast<const void*>(ro_str.data()), as_u16cstr(ro_str));
 
-  WStringPiece piece = ro_buffer;
+  std::wstring_view piece = ro_buffer;
   static_assert(std::is_same_v<const char16_t*, decltype(as_u16cstr(piece))>,
                 "");
   EXPECT_EQ(static_cast<const void*>(piece.data()), as_u16cstr(piece));
@@ -1332,17 +1333,17 @@
   EXPECT_TRUE(MakeStringPiece16(bar.end(), bar.end()).empty());
 
   constexpr wchar_t kBaz[] = L"Baz";
-  static_assert(MakeWStringPiece(kBaz, kBaz + 3) == kBaz, "");
-  static_assert(MakeWStringPiece(kBaz, kBaz + 3).data() == kBaz, "");
-  static_assert(MakeWStringPiece(kBaz, kBaz + 3).size() == 3, "");
-  static_assert(MakeWStringPiece(kBaz + 3, kBaz + 3).empty(), "");
-  static_assert(MakeWStringPiece(kBaz + 4, kBaz + 4).empty(), "");
+  static_assert(MakeWStringView(kBaz, kBaz + 3) == kBaz, "");
+  static_assert(MakeWStringView(kBaz, kBaz + 3).data() == kBaz, "");
+  static_assert(MakeWStringView(kBaz, kBaz + 3).size() == 3, "");
+  static_assert(MakeWStringView(kBaz + 3, kBaz + 3).empty(), "");
+  static_assert(MakeWStringView(kBaz + 4, kBaz + 4).empty(), "");
 
   std::wstring baz = kBaz;
-  EXPECT_EQ(MakeWStringPiece(baz.begin(), baz.end()), baz);
-  EXPECT_EQ(MakeWStringPiece(baz.begin(), baz.end()).data(), baz.data());
-  EXPECT_EQ(MakeWStringPiece(baz.begin(), baz.end()).size(), baz.size());
-  EXPECT_TRUE(MakeWStringPiece(baz.end(), baz.end()).empty());
+  EXPECT_EQ(MakeWStringView(baz.begin(), baz.end()), baz);
+  EXPECT_EQ(MakeWStringView(baz.begin(), baz.end()).data(), baz.data());
+  EXPECT_EQ(MakeWStringView(baz.begin(), baz.end()).size(), baz.size());
+  EXPECT_TRUE(MakeWStringView(baz.end(), baz.end()).empty());
 }
 
 TEST(StringUtilTest, RemoveChars) {
@@ -1522,7 +1523,7 @@
   EXPECT_TRUE(EqualsCaseInsensitiveASCII("aaa \xc3\xa4", "AAA \xc3\xa4"));
   EXPECT_FALSE(EqualsCaseInsensitiveASCII("aaa \xc3\x84", "AAA \xc3\xa4"));
 
-  // The `WStringPiece` overloads are only defined on Windows.
+  // The `std::wstring_view` overloads are only defined on Windows.
 #if BUILDFLAG(IS_WIN)
   EXPECT_TRUE(EqualsCaseInsensitiveASCII(L"", L""));
   EXPECT_TRUE(EqualsCaseInsensitiveASCII(L"Asdf", L"aSDF"));
diff --git a/base/strings/string_util_win.cc b/base/strings/string_util_win.cc
index ce0069c5..52e2116 100644
--- a/base/strings/string_util_win.cc
+++ b/base/strings/string_util_win.cc
@@ -4,95 +4,99 @@
 
 #include "base/strings/string_util_win.h"
 
+#include <string_view>
+
 #include "base/ranges/algorithm.h"
 #include "base/strings/string_util_impl_helpers.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 
-bool IsStringASCII(WStringPiece str) {
+bool IsStringASCII(std::wstring_view str) {
   return internal::DoIsStringASCII(str.data(), str.length());
 }
 
-std::wstring ToLowerASCII(WStringPiece str) {
+std::wstring ToLowerASCII(std::wstring_view str) {
   return internal::ToLowerASCIIImpl(str);
 }
 
-std::wstring ToUpperASCII(WStringPiece str) {
+std::wstring ToUpperASCII(std::wstring_view str) {
   return internal::ToUpperASCIIImpl(str);
 }
 
-int CompareCaseInsensitiveASCII(WStringPiece a, WStringPiece b) {
+int CompareCaseInsensitiveASCII(std::wstring_view a, std::wstring_view b) {
   return internal::CompareCaseInsensitiveASCIIT(a, b);
 }
 
-bool RemoveChars(WStringPiece input,
-                 WStringPiece remove_chars,
+bool RemoveChars(std::wstring_view input,
+                 std::wstring_view remove_chars,
                  std::wstring* output) {
-  return internal::ReplaceCharsT(input, remove_chars, WStringPiece(), output);
+  return internal::ReplaceCharsT(input, remove_chars, std::wstring_view(),
+                                 output);
 }
 
-bool ReplaceChars(WStringPiece input,
-                  WStringPiece replace_chars,
-                  WStringPiece replace_with,
+bool ReplaceChars(std::wstring_view input,
+                  std::wstring_view replace_chars,
+                  std::wstring_view replace_with,
                   std::wstring* output) {
   return internal::ReplaceCharsT(input, replace_chars, replace_with, output);
 }
 
-bool TrimString(WStringPiece input,
-                WStringPiece trim_chars,
+bool TrimString(std::wstring_view input,
+                std::wstring_view trim_chars,
                 std::wstring* output) {
   return internal::TrimStringT(input, trim_chars, TRIM_ALL, output) !=
          TRIM_NONE;
 }
 
-WStringPiece TrimString(WStringPiece input,
-                        WStringPiece trim_chars,
-                        TrimPositions positions) {
+std::wstring_view TrimString(std::wstring_view input,
+                             std::wstring_view trim_chars,
+                             TrimPositions positions) {
   return internal::TrimStringPieceT(input, trim_chars, positions);
 }
 
-TrimPositions TrimWhitespace(WStringPiece input,
+TrimPositions TrimWhitespace(std::wstring_view input,
                              TrimPositions positions,
                              std::wstring* output) {
-  return internal::TrimStringT(input, WStringPiece(kWhitespaceWide), positions,
-                               output);
+  return internal::TrimStringT(input, std::wstring_view(kWhitespaceWide),
+                               positions, output);
 }
 
-WStringPiece TrimWhitespace(WStringPiece input, TrimPositions positions) {
-  return internal::TrimStringPieceT(input, WStringPiece(kWhitespaceWide),
+std::wstring_view TrimWhitespace(std::wstring_view input,
+                                 TrimPositions positions) {
+  return internal::TrimStringPieceT(input, std::wstring_view(kWhitespaceWide),
                                     positions);
 }
 
-std::wstring CollapseWhitespace(WStringPiece text,
+std::wstring CollapseWhitespace(std::wstring_view text,
                                 bool trim_sequences_with_line_breaks) {
   return internal::CollapseWhitespaceT(text, trim_sequences_with_line_breaks);
 }
 
-bool ContainsOnlyChars(WStringPiece input, WStringPiece characters) {
+bool ContainsOnlyChars(std::wstring_view input, std::wstring_view characters) {
   return input.find_first_not_of(characters) == StringPiece::npos;
 }
 
-bool EqualsASCII(WStringPiece str, StringPiece ascii) {
+bool EqualsASCII(std::wstring_view str, StringPiece ascii) {
   return ranges::equal(ascii, str);
 }
 
-bool StartsWith(WStringPiece str,
-                WStringPiece search_for,
+bool StartsWith(std::wstring_view str,
+                std::wstring_view search_for,
                 CompareCase case_sensitivity) {
   return internal::StartsWithT(str, search_for, case_sensitivity);
 }
 
-bool EndsWith(WStringPiece str,
-              WStringPiece search_for,
+bool EndsWith(std::wstring_view str,
+              std::wstring_view search_for,
               CompareCase case_sensitivity) {
   return internal::EndsWithT(str, search_for, case_sensitivity);
 }
 
 void ReplaceFirstSubstringAfterOffset(std::wstring* str,
                                       size_t start_offset,
-                                      WStringPiece find_this,
-                                      WStringPiece replace_with) {
+                                      std::wstring_view find_this,
+                                      std::wstring_view replace_with) {
   internal::DoReplaceMatchesAfterOffset(
       str, start_offset, internal::MakeSubstringMatcher(find_this),
       replace_with, internal::ReplaceType::REPLACE_FIRST);
@@ -100,8 +104,8 @@
 
 void ReplaceSubstringsAfterOffset(std::wstring* str,
                                   size_t start_offset,
-                                  WStringPiece find_this,
-                                  WStringPiece replace_with) {
+                                  std::wstring_view find_this,
+                                  std::wstring_view replace_with) {
   internal::DoReplaceMatchesAfterOffset(
       str, start_offset, internal::MakeSubstringMatcher(find_this),
       replace_with, internal::ReplaceType::REPLACE_ALL);
@@ -112,21 +116,21 @@
 }
 
 std::wstring JoinString(span<const std::wstring> parts,
-                        WStringPiece separator) {
+                        std::wstring_view separator) {
   return internal::JoinStringT(parts, separator);
 }
 
-std::wstring JoinString(span<const WStringPiece> parts,
-                        WStringPiece separator) {
+std::wstring JoinString(span<const std::wstring_view> parts,
+                        std::wstring_view separator) {
   return internal::JoinStringT(parts, separator);
 }
 
-std::wstring JoinString(std::initializer_list<WStringPiece> parts,
-                        WStringPiece separator) {
+std::wstring JoinString(std::initializer_list<std::wstring_view> parts,
+                        std::wstring_view separator) {
   return internal::JoinStringT(parts, separator);
 }
 
-std::wstring ReplaceStringPlaceholders(WStringPiece format_string,
+std::wstring ReplaceStringPlaceholders(std::wstring_view format_string,
                                        const std::vector<std::wstring>& subst,
                                        std::vector<size_t>* offsets) {
   absl::optional<std::wstring> replacement =
diff --git a/base/strings/string_util_win.h b/base/strings/string_util_win.h
index 716a697..e3e2be8 100644
--- a/base/strings/string_util_win.h
+++ b/base/strings/string_util_win.h
@@ -12,6 +12,7 @@
 #include <wchar.h>
 
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/check.h"
@@ -85,17 +86,17 @@
   return reinterpret_cast<const char16_t*>(str);
 }
 
-inline const char16_t* as_u16cstr(WStringPiece str) {
+inline const char16_t* as_u16cstr(std::wstring_view str) {
   return reinterpret_cast<const char16_t*>(str.data());
 }
 
-// Utility functions to convert between base::WStringPiece and
+// Utility functions to convert between std::wstring_view and
 // base::StringPiece16.
-inline WStringPiece AsWStringPiece(StringPiece16 str) {
-  return WStringPiece(as_wcstr(str.data()), str.size());
+inline std::wstring_view AsWStringView(StringPiece16 str) {
+  return std::wstring_view(as_wcstr(str.data()), str.size());
 }
 
-inline StringPiece16 AsStringPiece16(WStringPiece str) {
+inline StringPiece16 AsStringPiece16(std::wstring_view str) {
   return StringPiece16(as_u16cstr(str.data()), str.size());
 }
 
@@ -103,95 +104,100 @@
   return std::wstring(as_wcstr(str.data()), str.size());
 }
 
-inline std::u16string AsString16(WStringPiece str) {
+inline std::u16string AsString16(std::wstring_view str) {
   return std::u16string(as_u16cstr(str.data()), str.size());
 }
 
 // The following section contains overloads of the cross-platform APIs for
-// std::wstring and base::WStringPiece.
-BASE_EXPORT bool IsStringASCII(WStringPiece str);
+// std::wstring and std::wstring_view.
+BASE_EXPORT bool IsStringASCII(std::wstring_view str);
 
-BASE_EXPORT std::wstring ToLowerASCII(WStringPiece str);
+BASE_EXPORT std::wstring ToLowerASCII(std::wstring_view str);
 
-BASE_EXPORT std::wstring ToUpperASCII(WStringPiece str);
+BASE_EXPORT std::wstring ToUpperASCII(std::wstring_view str);
 
-BASE_EXPORT int CompareCaseInsensitiveASCII(WStringPiece a, WStringPiece b);
+BASE_EXPORT int CompareCaseInsensitiveASCII(std::wstring_view a,
+                                            std::wstring_view b);
 
-inline bool EqualsCaseInsensitiveASCII(WStringPiece a, WStringPiece b) {
+inline bool EqualsCaseInsensitiveASCII(std::wstring_view a,
+                                       std::wstring_view b) {
   return internal::EqualsCaseInsensitiveASCIIT(a, b);
 }
-inline bool EqualsCaseInsensitiveASCII(WStringPiece a, StringPiece b) {
+inline bool EqualsCaseInsensitiveASCII(std::wstring_view a, StringPiece b) {
   return internal::EqualsCaseInsensitiveASCIIT(a, b);
 }
-inline bool EqualsCaseInsensitiveASCII(StringPiece a, WStringPiece b) {
+inline bool EqualsCaseInsensitiveASCII(StringPiece a, std::wstring_view b) {
   return internal::EqualsCaseInsensitiveASCIIT(a, b);
 }
 
-BASE_EXPORT bool RemoveChars(WStringPiece input,
-                             WStringPiece remove_chars,
+BASE_EXPORT bool RemoveChars(std::wstring_view input,
+                             std::wstring_view remove_chars,
                              std::wstring* output);
 
-BASE_EXPORT bool ReplaceChars(WStringPiece input,
-                              WStringPiece replace_chars,
-                              WStringPiece replace_with,
+BASE_EXPORT bool ReplaceChars(std::wstring_view input,
+                              std::wstring_view replace_chars,
+                              std::wstring_view replace_with,
                               std::wstring* output);
 
-BASE_EXPORT bool TrimString(WStringPiece input,
-                            WStringPiece trim_chars,
+BASE_EXPORT bool TrimString(std::wstring_view input,
+                            std::wstring_view trim_chars,
                             std::wstring* output);
 
-BASE_EXPORT WStringPiece TrimString(WStringPiece input,
-                                    WStringPiece trim_chars,
-                                    TrimPositions positions);
+BASE_EXPORT std::wstring_view TrimString(std::wstring_view input,
+                                         std::wstring_view trim_chars,
+                                         TrimPositions positions);
 
-BASE_EXPORT TrimPositions TrimWhitespace(WStringPiece input,
+BASE_EXPORT TrimPositions TrimWhitespace(std::wstring_view input,
                                          TrimPositions positions,
                                          std::wstring* output);
 
-BASE_EXPORT WStringPiece TrimWhitespace(WStringPiece input,
-                                        TrimPositions positions);
+BASE_EXPORT std::wstring_view TrimWhitespace(std::wstring_view input,
+                                             TrimPositions positions);
 
 BASE_EXPORT std::wstring CollapseWhitespace(
-    WStringPiece text,
+    std::wstring_view text,
     bool trim_sequences_with_line_breaks);
 
-BASE_EXPORT bool ContainsOnlyChars(WStringPiece input, WStringPiece characters);
+BASE_EXPORT bool ContainsOnlyChars(std::wstring_view input,
+                                   std::wstring_view characters);
 
 BASE_EXPORT bool EqualsASCII(StringPiece16 str, StringPiece ascii);
 
 BASE_EXPORT bool StartsWith(
-    WStringPiece str,
-    WStringPiece search_for,
+    std::wstring_view str,
+    std::wstring_view search_for,
     CompareCase case_sensitivity = CompareCase::SENSITIVE);
 
 BASE_EXPORT bool EndsWith(
-    WStringPiece str,
-    WStringPiece search_for,
+    std::wstring_view str,
+    std::wstring_view search_for,
     CompareCase case_sensitivity = CompareCase::SENSITIVE);
 
-BASE_EXPORT void ReplaceFirstSubstringAfterOffset(std::wstring* str,
-                                                  size_t start_offset,
-                                                  WStringPiece find_this,
-                                                  WStringPiece replace_with);
+BASE_EXPORT void ReplaceFirstSubstringAfterOffset(
+    std::wstring* str,
+    size_t start_offset,
+    std::wstring_view find_this,
+    std::wstring_view replace_with);
 
 BASE_EXPORT void ReplaceSubstringsAfterOffset(std::wstring* str,
                                               size_t start_offset,
-                                              WStringPiece find_this,
-                                              WStringPiece replace_with);
+                                              std::wstring_view find_this,
+                                              std::wstring_view replace_with);
 
 BASE_EXPORT wchar_t* WriteInto(std::wstring* str, size_t length_with_null);
 
 BASE_EXPORT std::wstring JoinString(span<const std::wstring> parts,
-                                    WStringPiece separator);
+                                    std::wstring_view separator);
 
-BASE_EXPORT std::wstring JoinString(span<const WStringPiece> parts,
-                                    WStringPiece separator);
+BASE_EXPORT std::wstring JoinString(span<const std::wstring_view> parts,
+                                    std::wstring_view separator);
 
-BASE_EXPORT std::wstring JoinString(std::initializer_list<WStringPiece> parts,
-                                    WStringPiece separator);
+BASE_EXPORT std::wstring JoinString(
+    std::initializer_list<std::wstring_view> parts,
+    std::wstring_view separator);
 
 BASE_EXPORT std::wstring ReplaceStringPlaceholders(
-    WStringPiece format_string,
+    std::wstring_view format_string,
     const std::vector<std::wstring>& subst,
     std::vector<size_t>* offsets);
 
diff --git a/base/strings/utf_string_conversions.cc b/base/strings/utf_string_conversions.cc
index 58cb3b5..cb4ce30 100644
--- a/base/strings/utf_string_conversions.cc
+++ b/base/strings/utf_string_conversions.cc
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <ostream>
+#include <string_view>
 #include <type_traits>
 
 #include "base/strings/string_piece.h"
@@ -254,7 +255,7 @@
   return true;
 }
 
-std::u16string WideToUTF16(WStringPiece wide) {
+std::u16string WideToUTF16(std::wstring_view wide) {
   return std::u16string(wide.begin(), wide.end());
 }
 
@@ -270,10 +271,10 @@
 #elif defined(WCHAR_T_IS_32_BIT)
 
 bool WideToUTF16(const wchar_t* src, size_t src_len, std::u16string* output) {
-  return UTFConversion(base::WStringPiece(src, src_len), output);
+  return UTFConversion(std::wstring_view(src, src_len), output);
 }
 
-std::u16string WideToUTF16(WStringPiece wide) {
+std::u16string WideToUTF16(std::wstring_view wide) {
   std::u16string ret;
   // Ignore the success flag of this call, it will do the best it can for
   // invalid input, which is what we want here.
@@ -318,17 +319,17 @@
   return UTF16ToUTF8(as_u16cstr(src), src_len, output);
 }
 
-std::string WideToUTF8(WStringPiece wide) {
+std::string WideToUTF8(std::wstring_view wide) {
   return UTF16ToUTF8(StringPiece16(as_u16cstr(wide), wide.size()));
 }
 
 #elif defined(WCHAR_T_IS_32_BIT)
 
 bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) {
-  return UTFConversion(WStringPiece(src, src_len), output);
+  return UTFConversion(std::wstring_view(src, src_len), output);
 }
 
-std::string WideToUTF8(WStringPiece wide) {
+std::string WideToUTF8(std::wstring_view wide) {
   std::string ret;
   // Ignore the success flag of this call, it will do the best it can for
   // invalid input, which is what we want here.
@@ -354,7 +355,7 @@
   return std::wstring(ascii.begin(), ascii.end());
 }
 
-std::string WideToASCII(WStringPiece wide) {
+std::string WideToASCII(std::wstring_view wide) {
   DCHECK(IsStringASCII(wide)) << wide;
   return std::string(wide.begin(), wide.end());
 }
diff --git a/base/strings/utf_string_conversions.h b/base/strings/utf_string_conversions.h
index af1cc0d..c7417d6 100644
--- a/base/strings/utf_string_conversions.h
+++ b/base/strings/utf_string_conversions.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include <string>
+#include <string_view>
 
 #include "base/base_export.h"
 #include "base/strings/string_piece.h"
@@ -24,7 +25,7 @@
 // possible.
 BASE_EXPORT bool WideToUTF8(const wchar_t* src, size_t src_len,
                             std::string* output);
-[[nodiscard]] BASE_EXPORT std::string WideToUTF8(WStringPiece wide);
+[[nodiscard]] BASE_EXPORT std::string WideToUTF8(std::wstring_view wide);
 BASE_EXPORT bool UTF8ToWide(const char* src, size_t src_len,
                             std::wstring* output);
 [[nodiscard]] BASE_EXPORT std::wstring UTF8ToWide(StringPiece utf8);
@@ -32,7 +33,7 @@
 BASE_EXPORT bool WideToUTF16(const wchar_t* src,
                              size_t src_len,
                              std::u16string* output);
-[[nodiscard]] BASE_EXPORT std::u16string WideToUTF16(WStringPiece wide);
+[[nodiscard]] BASE_EXPORT std::u16string WideToUTF16(std::wstring_view wide);
 BASE_EXPORT bool UTF16ToWide(const char16_t* src,
                              size_t src_len,
                              std::wstring* output);
@@ -62,7 +63,7 @@
 
 // Converts to 7-bit ASCII by truncating. The result must be known to be ASCII
 // beforehand.
-[[nodiscard]] BASE_EXPORT std::string WideToASCII(WStringPiece wide);
+[[nodiscard]] BASE_EXPORT std::string WideToASCII(std::wstring_view wide);
 #endif  // defined(WCHAR_T_IS_16_BIT)
 
 // The conversion functions in this file should not be used to convert string
diff --git a/base/trace_event/traced_value_support.h b/base/trace_event/traced_value_support.h
index b797eb31..500e613 100644
--- a/base/trace_event/traced_value_support.h
+++ b/base/trace_event/traced_value_support.h
@@ -5,6 +5,8 @@
 #ifndef BASE_TRACE_EVENT_TRACED_VALUE_SUPPORT_H_
 #define BASE_TRACE_EVENT_TRACED_VALUE_SUPPORT_H_
 
+#include <string_view>
+
 #include "base/memory/raw_ptr.h"
 #include "base/memory/raw_ref.h"
 #include "base/memory/scoped_refptr.h"
@@ -200,7 +202,7 @@
   static void WriteIntoTrace(perfetto::TracedValue context,
                              const wchar_t value[N]) {
     return std::move(context).WriteString(
-        ::base::WideToUTF8(::base::WStringPiece(value)));
+        ::base::WideToUTF8(::std::wstring_view(value)));
   }
 };
 
@@ -209,7 +211,7 @@
   static void WriteIntoTrace(perfetto::TracedValue context,
                              const wchar_t* value) {
     return std::move(context).WriteString(
-        ::base::WideToUTF8(::base::WStringPiece(value)));
+        ::base::WideToUTF8(::std::wstring_view(value)));
   }
 };
 
@@ -223,9 +225,9 @@
 };
 
 template <>
-struct TraceFormatTraits<::base::WStringPiece> {
+struct TraceFormatTraits<::std::wstring_view> {
   static void WriteIntoTrace(perfetto::TracedValue context,
-                             ::base::WStringPiece value) {
+                             ::std::wstring_view value) {
     return std::move(context).WriteString(::base::WideToUTF8(value));
   }
 };
diff --git a/base/trace_event/traced_value_support_unittest.cc b/base/trace_event/traced_value_support_unittest.cc
index d902050..ba946c6 100644
--- a/base/trace_event/traced_value_support_unittest.cc
+++ b/base/trace_event/traced_value_support_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "base/trace_event/traced_value_support.h"
 
+#include <string_view>
+
 #include "base/memory/ref_counted.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -106,7 +108,7 @@
             "string");
   EXPECT_EQ(perfetto::TracedValueToString(base::StringPiece16(u"utf-16")),
             "utf-16");
-  EXPECT_EQ(perfetto::TracedValueToString(base::WStringPiece(L"wide")), "wide");
+  EXPECT_EQ(perfetto::TracedValueToString(std::wstring_view(L"wide")), "wide");
 }
 
 TEST(TracedValueSupportTest, RawPtr) {
diff --git a/base/tracing/stdlib/chrome/event_latency_description.sql b/base/tracing/stdlib/chrome/event_latency_description.sql
new file mode 100644
index 0000000..ca89dae
--- /dev/null
+++ b/base/tracing/stdlib/chrome/event_latency_description.sql
@@ -0,0 +1,183 @@
+-- Copyright 2023 The Chromium Authors
+-- Use of this source code is governed by a BSD-style license that can be
+-- found in the LICENSE file.
+
+-- Source of truth of the descriptions of EventLatency stages.
+CREATE PERFETTO TABLE chrome_event_latency_stage_descriptions (
+    -- The name of the EventLatency stage.
+    name STRING,
+    -- A description of the EventLatency stage.
+    description STRING
+) AS
+WITH event_latency_descriptions(
+  name,
+  description)
+AS (
+VALUES
+  ('TouchRendererHandlingToBrowserMain',
+    'Interval between when the website handled blocking touch move to when ' ||
+    'the browser UI thread started processing the input. Blocking touch ' ||
+    'move happens when a touch event has to be handled by the website ' ||
+    'before being converted to a scroll.'),
+  ('GenerationToBrowserMain',
+    'Interval between OS-provided hardware input timestamp to when the ' ||
+    'browser UI thread began processing the input.'),
+  ('GenerationToRendererCompositor',
+    'Interval between OS-provided hardware input timestamp to when the ' ||
+    'renderer compositor thread starts handling the artificial TOUCH_PRESS ' ||
+    'browser injects in the kTouchScrollStarted event. See ' ||
+    'PrependTouchScrollNotification for more info.'),
+  ('BrowserMainToRendererCompositor',
+    'Interval between when Browser UI thread starts to process the input to ' ||
+    'renderer compositor thread starting to process it. This stage includes ' ||
+    'browser UI thread processing, and task queueing times on the IO and ' ||
+    'renderer compositor threads.'),
+  ('RendererCompositorQueueingDelay',
+    'Interval between when the input event is queued in the renderer ' ||
+    'compositor and start of the BeginImplFrame producing a frame ' ||
+    'containing this input.'),
+  ('RendererCompositorToMain',
+    'Interval between when the Renderer Compositor finishes processing the ' ||
+    'event and when the Renderer Main (CrRendererMain) starts processing ' ||
+    'the event, only seen when the compositor thread cannot handle the ' ||
+    'scroll event by itself (known as "slow path"), usually caused by the ' ||
+    'presence of blocking JS event listeners or complex page layout.'),
+  ('RendererCompositorProcessing',
+    'Interval corresponding to the Renderer Compositor thread processing ' ||
+    'the frame updates.'),
+  ('RendererMainProcessing',
+    'Interval corresponding to the Renderer Main thread processing the ' ||
+    'frame updates.'),
+  ('EndActivateToSubmitCompositorFrame',
+    'Interval that the Renderer Compositor waits for the GPU to flush a ' ||
+    'frame to submit a new one.'),
+  ('SubmitCompositorFrameToPresentationCompositorFrame',
+    'Interval between the first Renderer Frame received to when the system ' ||
+    'presented the fully composited frame on the screen. Note that on some ' ||
+    'systems/apps this is incomplete/inaccurate due to lack of feedback ' ||
+    'timestamps from the platform (Mac, iOS, Android Webview, etc).'),
+  ('ArrivedInRendererCompositorToTermination',
+    'Interval between when Renderer Compositor received the frame to when ' ||
+    'this input was decided to either be ignored or merged into another ' ||
+    'frame being produced. This could be a dropped frame, or just a normal ' ||
+    'coalescing.'),
+  ('RendererCompositorStartedToTermination',
+    'Interval between when Renderer Compositor started processing the frame ' ||
+    'to when this input was decided to either be ignored or merged into ' ||
+    'another frame being produced. This could be a dropped frame, or just a ' ||
+    'normal coalescing.'),
+  ('RendererMainFinishedToTermination',
+    'Interval between when Renderer Main finished processing the frame ' ||
+    'to when this input was decided to either be ignored or merged into ' ||
+    'another frame being produced. This could be a dropped frame, or just a ' ||
+    'normal coalescing.'),
+  ('RendererCompositorFinishedToTermination',
+    'Interval between when Renderer Compositor finished processing the ' ||
+    'frame to when this input was decided to either be ignored or merged ' ||
+    'into another frame being produced. This could be just a normal ' ||
+    'coalescing.'),
+  ('RendererMainStartedToTermination',
+    'Interval between when Renderer Main started processing the frame ' ||
+    'to when this input was decided to either be ignored or merged into ' ||
+    'another frame being produced. This could be a dropped frame, or just a ' ||
+    'normal coalescing.'),
+  ('RendererCompositorFinishedToBeginImplFrame',
+    'Interval when Renderer Compositor has finished processing a vsync ' ||
+    '(with input), but did not end up producing a CompositorFrame due to ' ||
+    'reasons such as waiting on main thread, and is now waiting for the ' ||
+    'next BeginFrame from the GPU VizCompositor.'),
+  ('RendererCompositorFinishedToCommit',
+    'Interval between when the Renderer Compositor has finished its work ' ||
+    'and the current tree state will be committed from the Renderer Main ' ||
+    '(CrRendererMain) thread.'),
+  ('RendererCompositorFinishedToEndCommit',
+    'Interval between when the Renderer Compositor finishing processing to ' ||
+    'the Renderer Main (CrRendererMain) both starting and finishing the ' ||
+    'commit.'),
+  ('RendererCompositorFinishedToActivation',
+    'Interval of activation without a previous commit (not as a stage with ' ||
+    'ToEndCommit). Activation occurs on the Renderer Compositor Thread ' ||
+    'after it has been notified of a fully committed RendererMain tree.'),
+  ('RendererCompositorFinishedToEndActivate',
+    'Interval when the Renderer Compositor has finished processing and ' ||
+    'activating the Tree.'),
+  ('RendererCompositorFinishedToSubmitCompositorFrame',
+    'Interval when processing does not need to wait for a commit (can do an ' ||
+    'early out) for activation and can go straight to providing the frame ' ||
+    'to the GPU VizCompositor. The Renderer Compositor is waiting for the ' ||
+    'GPU to flush a frame so that it can then submit a new frame.'),
+  ('RendererMainFinishedToBeginImplFrame',
+    'Interval when the input was sent first to the RendererMain thread and ' ||
+    'now requires the Renderer Compositor to react, aka it is is waiting ' ||
+    'for a BeginFrame signal.'),
+  ('RendererMainFinishedToSendBeginMainFrame',
+    'Interval during which the Renderer Main (CrRendererMain) thread is ' ||
+    'waiting for BeginMainFrame.'),
+  ('RendererMainFinishedToCommit',
+    'Interval when the Renderer Main (CrRendererMain) is ready to commit ' ||
+    'its work to the Renderer Compositor.'),
+  ('BeginImplFrameToSendBeginMainFrame',
+    'Interval during which the Renderer Compositor has received the ' ||
+    'BeginFrame signal from the GPU VizCompositor, and now needs to send it ' ||
+    'to the Renderer Main thread (CrRendererMain).'),
+  ('RendererCompositorFinishedToSendBeginMainFrame',
+    'Interval during which the Renderer Compositor is waiting for a ' ||
+    'BeginFrame from the GPU VizCompositor, and it expects to have to do ' ||
+    'work on the Renderer Main thread (CrRendererMain), so we are waiting ' ||
+    'for a BeginMainFrame'),
+  ('SendBeginMainFrameToCommit',
+    'Interval when updates (such as HandleInputEvents, Animate, StyleUpdate ' ||
+    'and LayoutUpdate) are updatedon the Renderer Main thread ' ||
+    '(CrRendererMain).'),
+  ('Commit',
+    'Interval during which the Renderer Main thread (CrRendererMain) ' ||
+    'commits updates back to Renderer Compositor for activation. ' ||
+    'Specifically, the main thread copies its own version of layer tree ' ||
+    'onto the pending tree on the compositor thread. The main thread is ' ||
+    'blocked during the copying process.'),
+  ('EndCommitToActivation',
+    'Interval when the commit is ready and waiting for activation.'),
+  ('Activation',
+    'Interval when the layer trees and properties are on the pending tree ' ||
+    'is pused to the active tree on the Renderer Compositor.'),
+  ('SubmitToReceiveCompositorFrame',
+    'Interval of the delay b/w Renderer Compositor thread sending ' ||
+    'CompositorFrame and then GPU VizCompositorThread receiving the ' ||
+    'CompositorFrame.'),
+  ('ReceiveCompositorFrameToStartDraw',
+    'Interval between the first frame received to when all frames (or ' ||
+    'timeouts have occured) and we start drawing. It can be blocked by ' ||
+    'other processes (e.g to draw a toolbar it waiting for information from ' ||
+    'the Browser) as it waits for timeouts or frames to be provided. This ' ||
+    'is the tree of dependencies that the GPU VizCompositor is waiting for ' ||
+    'things to arrive. That is creating a single frame for multiple ' ||
+    'compositor frames. '),
+  ('StartDrawToSwapStart',
+    'Interval when all compositing sources are done, or compositing ' ||
+    'deadline passes - the viz thread takes all the latest composited ' ||
+    'surfaces and issues the software draw instructions to layer the ' ||
+    'composited tiles, this substage ends when the swap starts on Gpu ' ||
+    'CompositorGpuThread.'),
+  ('SwapStartToBufferAvailable',
+    'Interval that is a substage of stage "Swap" when the framebuffer ' ||
+    'is prepared by the system and the fence Chrome waits on before ' ||
+    'writing is signalled, and Chrome can start transferring the new frame.'),
+  ('BufferAvailableToBufferReady',
+    'Interval that is a Ssubstage of stage "Swap" when Chrome is ' ||
+    'transferring a new frame to when it has finished completely sending a ' ||
+    'frame to the framebuffer.'),
+  ('BufferReadyToLatch',
+    'Interval that is a substage of stage "Swap", when the system latches ' ||
+    'and is ready to use the frame, and then it can get to work producing ' ||
+    'the final frame.'),
+  ('LatchToSwapEnd',
+    'Intereval that is a substage of stage "Swap", when the latch has ' ||
+    'finished until the frame is fully swapped and in the queue of frames ' ||
+    'to be presented.'),
+  ('SwapEndToPresentationCompositorFrame',
+    'Interval that the frame is presented on the screen (and pixels became ' ||
+    'visible).'))
+SELECT
+  name,
+  description
+FROM event_latency_descriptions;
diff --git a/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_cause_map.sql b/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_cause_map.sql
new file mode 100644
index 0000000..f049075
--- /dev/null
+++ b/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_cause_map.sql
@@ -0,0 +1,94 @@
+-- Copyright 2023 The Chromium Authors
+-- Use of this source code is governed by a BSD-style license that can be
+-- found in the LICENSE file.
+
+-- Source of truth of the descriptions of EventLatency-based scroll jank causes.
+CREATE PERFETTO TABLE chrome_scroll_jank_cause_descriptions (
+  -- The name of the EventLatency stage.
+  event_latency_stage STRING,
+  -- The process where the cause of scroll jank occurred.
+  cause_process STRING,
+  -- The thread where the cause of scroll jank occurred.
+  cause_thread STRING,
+  -- A description of the cause of scroll jank.
+  cause_description STRING
+) AS
+WITH cause_descriptions(
+  event_latency_stage,
+  cause_process,
+  cause_thread,
+  cause_description)
+AS (
+VALUES
+  ('GenerationToBrowserMain', 'Browser', 'CrBrowserMain',
+    'This also corresponds to a matching InputLatency::TouchMove. Key ' ||
+    'things to look for: Browser Main thread (CrBrowserMain) is busy, often ' ||
+    'running tasks. The true cause can be confirmed by checking which tasks ' ||
+    'are being run on CrBrowserMain, or checking any ScopedBlockingCall ' ||
+    'slices during this stage from a ThreadPoolForegroundWorker, or ' ||
+    'checking if the NetworkService is busy. Common causes may include page' ||
+    'navigations (same document and new pages), slow BeginMainFrames, and ' ||
+    'Java Choreographer slowdowns.'),
+  ('RendererCompositorQueueingDelay', 'Renderer', 'Compositor',
+    'The renderer needs to decide to produce a frame in response to a ' ||
+    'BeginFrame signal. Sometimes it can not because it is waiting on the ' ||
+    'RendererMain thread to do touch targeting or javascript handling or ' ||
+    'other such things causing a long queuing delay after it has already ' ||
+    'started the scroll (so the TouchStart has been processed).'),
+  ('RendererCompositorQueueingDelay', 'GPU', 'VizCompositorThread',
+    'Waiting for a BeginFrame to be sent. Key things to look for: check if ' ||
+    'a fling occurred before or during the scroll; flings produce a single ' ||
+    'input and result in multiple inputs coalescing into a single frame.'),
+  ('ReceiveCompositorFrameToStartDraw', 'GPU', 'VizCompositorThread',
+    'A delay when the VizCompositor is waiting for the frame, but may be ' ||
+    'connected to other processes and threads. Key things to look for: ' ||
+    'check the BeginFrame task that finished during this EventLatency. The ' ||
+    'VizCompositor holds onto the frame/does not send it on. Alternately ' ||
+    'the system may be holding on to the buffer.'),
+  ('ReceiveCompositorFrameToStartDraw', 'GPU', 'CrGpuMain',
+    'Key things to look for: if the GPU Main thread is busy, and does not ' ||
+    'release the buffer; specific causes will be on the GPU Main thread. If ' ||
+    'this thread is not busy, the buffer may be held by the system instead.'),
+  ('ReceiveCompositorFrameToStartDraw', 'Browser', 'CrBrowserMain',
+    'Key things to look for: the toolbar on the Browser may be blocked by ' ||
+    'other tasks.'),
+  ('BufferReadyToLatch', 'GPU', 'VizCompositorThread',
+    'Often a scheduling issue. The frame was submitted, but missed the ' ||
+    'latch in the system that was received from the previous frame. The ' ||
+    'system only latches a buffer once per frame; when the latch deadline ' ||
+    'is missed, the system is forced to wait for another vsync interval to ' ||
+    'latch again. Key things to look for: whether the event duration before ' ||
+    'BufferReadyToLatch stage of the previous EventLatency is longer or ' ||
+    'shorter than the event duration before BufferReadyToLatch in the ' ||
+    'current EventLatency. If this duration is longer, then this is a ' ||
+    'System problem. If this duration is shorter, then it is a Chrome ' ||
+    'problem. The previous frame may have been drawn too quickly, or the ' ||
+    'GPU may be delayed.'),
+  ('SwapEndToPresentationCompositorFrame', 'GPU', 'VizCompositorThread',
+    'May be attributed to a scheduling issue as with BufferReadyToLatch. ' ||
+    'The frame was submitted, but missed the latch in the system that was ' ||
+    'received from the previous frame. The system only latches a buffer ' ||
+    'once per frame; when the latch deadline is missed, the system is ' ||
+    'forced to wait for another vsync interval to latch again. Key things ' ||
+    'to look for: whether the event duration before BufferReadyToLatch ' ||
+    'stage of the previous EventLatency is longer or shorter than the event ' ||
+    'duration before BufferReadyToLatch in the current EventLatency. If ' ||
+    'this duration is longer, then this is a System problem. If this ' ||
+    'duration is shorter, then it is a Chrome problem. The previous frame ' ||
+    'may have been drawn too quickly, or the GPU may be delayed.'),
+  ('SwapEndToPresentationCompositorFrame', 'GPU', 'CrGpuMain',
+    'Key things to look for: whether StartDrawToBufferAvailable is also ' ||
+    'present during this EventLatency. If so, then the GPU main thread may ' ||
+    'be descheduled or busy. If surfaceflinger is available, check there as ' ||
+    'well.'),
+  ('SwapEndToPresentationCompositorFrame', 'GPU', 'surfaceflinger',
+    'Key things to look for: whether StartDrawToBufferAvailable is also ' ||
+    'present during this EventLatency. If so, then the VizCompositor has ' ||
+    'not received a signal from surfaceflinger to start writing into the ' ||
+    'buffer.'))
+SELECT
+  event_latency_stage,
+  cause_process,
+  cause_thread,
+  cause_description
+FROM cause_descriptions;
diff --git a/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_cause_utils.sql b/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_cause_utils.sql
new file mode 100644
index 0000000..2c6d0d0
--- /dev/null
+++ b/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_cause_utils.sql
@@ -0,0 +1,48 @@
+-- Copyright 2023 The Chromium Authors
+-- Use of this source code is governed by a BSD-style license that can be
+-- found in the LICENSE file.
+
+
+-- Retrieve the thread id of the thread on a particular process, if the name of
+-- that process is known. Returns an error if there are multiple threads in
+-- the given process with the same name.
+CREATE PERFETTO FUNCTION internal_find_utid_by_upid_and_name(
+  -- Unique process id
+  upid INT,
+  -- The name of the thread
+  thread_name STRING)
+RETURNS TABLE (
+  -- Unique thread id.
+  utid INT
+) AS
+SELECT
+  DISTINCT utid
+FROM thread
+WHERE upid = $upid
+  AND name = $thread_name;
+
+-- Function to retrieve the track id of the thread on a particular process if
+-- there are any slices during a particular EventLatency slice duration; this
+-- upid/thread combination refers to a cause of Scroll Jank.
+CREATE PERFETTO FUNCTION chrome_select_scroll_jank_cause_track(
+  -- The slice id of an EventLatency slice.
+  event_latency_id INT,
+  -- The process id that the thread is on.
+  upid INT,
+  -- The name of the thread.
+  thread_name STRING)
+RETURNS TABLE (
+  -- The track id associated with |thread| on the process with |upid|.
+  track_id INT
+) AS
+SELECT
+ DISTINCT track_id
+FROM thread_slice
+WHERE utid IN
+  (
+    SELECT
+      utid
+    FROM internal_find_utid_by_upid_and_name($upid, $thread_name)
+  )
+  AND ts >= (SELECT ts FROM slice WHERE id = $event_latency_id LIMIT 1)
+  AND ts <= (SELECT ts + dur FROM slice WHERE id = $event_latency_id LIMIT 1);
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py b/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
index ed2328bd..b9d19fd 100755
--- a/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
+++ b/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
@@ -128,3 +128,26 @@
         1993,4687375224739,-81,-181
         1996,4687386343739,-66,-247
         """))
+
+  def test_scroll_jank_cause_map(self):
+    return DiffTestBlueprint(
+        trace=TextProto(''),
+        query="""
+        INCLUDE PERFETTO MODULE chrome.event_latency_description;
+        INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_cause_map;
+
+        SELECT
+          DISTINCT event_latency_stage
+        FROM chrome_scroll_jank_cause_descriptions
+        WHERE event_latency_stage NOT IN
+          (
+            SELECT
+              DISTINCT name
+            FROM chrome_event_latency_stage_descriptions
+          );
+        """,
+        # Empty output is expected to ensure that all scroll jank causes
+        # correspond to a valid EventLatency stage.
+        out=Csv("""
+        "event_latency_stage"
+        """))
diff --git a/base/types/pass_key_nocompile.nc b/base/types/pass_key_nocompile.nc
index 87b23f2..65fd325 100644
--- a/base/types/pass_key_nocompile.nc
+++ b/base/types/pass_key_nocompile.nc
@@ -17,57 +17,39 @@
   Restricted(base::PassKey<Manager>) {}
 };
 
-int Secret(base::PassKey<Manager>) {
-  return 1;
+void Secret(base::PassKey<Manager>) {}
+
+void CannotConstructFieldFromTemporaryPassKey() {
+  class NotAManager {
+   public:
+    NotAManager() : restricted_(base::PassKey<Manager>()) {}  // expected-error {{calling a private constructor of class 'base::PassKey<base::Manager>'}}
+
+   private:
+    Restricted restricted_;
+  };
 }
 
-#if defined(NCTEST_UNAUTHORIZED_PASS_KEY_IN_INITIALIZER)  // [r"fatal error: calling a private constructor of class 'base::PassKey<base::Manager>'"]
+void CannotConstructFieldFromImplicitPassKey() {
+  class NotAManager {
+   public:
+    NotAManager() : restricted_({}) {}  // expected-error {{calling a private constructor of class 'base::PassKey<base::Manager>'}}
 
-class NotAManager {
- public:
-  NotAManager() : restricted_(base::PassKey<Manager>()) {}
-
- private:
-  Restricted restricted_;
-};
-
-void WillNotCompile() {
-  NotAManager not_a_manager;
+   private:
+    Restricted restricted_;
+  };
 }
 
-#elif defined(NCTEST_UNAUTHORIZED_UNIFORM_INITIALIZED_PASS_KEY_IN_INITIALIZER)  // [r"fatal error: calling a private constructor of class 'base::PassKey<base::Manager>'"]
-
-class NotAManager {
- public:
-  NotAManager() : restricted_({}) {}
-
- private:
-  Restricted restricted_;
-};
-
-void WillNotCompile() {
-  NotAManager not_a_manager;
+void CannotConstructTemporaryPassKey() {
+  Secret(base::PassKey<Manager>());  // expected-error {{calling a private constructor of class 'base::PassKey<base::Manager>'}}
 }
 
-#elif defined(NCTEST_UNAUTHORIZED_PASS_KEY_IN_FUNCTION)  // [r"fatal error: calling a private constructor of class 'base::PassKey<base::Manager>'"]
-
-int WillNotCompile() {
-  return Secret(base::PassKey<Manager>());
+void CannotConstructPassKeyImplicitly() {
+  Secret({});  // expected-error {{calling a private constructor of class 'base::PassKey<base::Manager>'}}
 }
 
-#elif defined(NCTEST_UNAUTHORIZED_UNIFORM_INITIALIZATION_WITH_DEDUCED_PASS_KEY_TYPE)  // [r"fatal error: calling a private constructor of class 'base::PassKey<base::Manager>'"]
-
-int WillNotCompile() {
-  return Secret({});
+void CannotConstructNamedPassKey() {
+  base::PassKey<Manager> key {};  // expected-error {{calling a private constructor of class 'base::PassKey<base::Manager>'}}
+  Secret(key);
 }
 
-#elif defined(NCTEST_UNAUTHORIZED_UNIFORM_INITIALIZATION)  // [r"fatal error: calling a private constructor of class 'base::PassKey<base::Manager>'"]
-
-int WillNotCompile() {
-  base::PassKey<Manager> key {};
-  return Secret(key);
-}
-
-#endif
-
 }  // namespace base
diff --git a/base/win/default_apps_util.cc b/base/win/default_apps_util.cc
index 08475da..76ef576d 100644
--- a/base/win/default_apps_util.cc
+++ b/base/win/default_apps_util.cc
@@ -7,6 +7,8 @@
 #include <shobjidl.h>
 #include <wrl/client.h>
 
+#include <string_view>
+
 #include "base/logging.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
@@ -17,8 +19,8 @@
 // Returns the target used as a activate parameter when opening the settings
 // pointing to the page that is the most relevant to a user trying to change the
 // default handler for `protocol`.
-std::wstring GetTargetForDefaultAppsSettings(base::WStringPiece protocol) {
-  static constexpr base::WStringPiece kSystemSettingsDefaultAppsPrefix(
+std::wstring GetTargetForDefaultAppsSettings(std::wstring_view protocol) {
+  static constexpr std::wstring_view kSystemSettingsDefaultAppsPrefix(
       L"SystemSettings_DefaultApps_");
   if (base::EqualsCaseInsensitiveASCII(protocol, L"http"))
     return base::StrCat({kSystemSettingsDefaultAppsPrefix, L"Browser"});
@@ -31,7 +33,7 @@
 
 namespace base::win {
 
-bool LaunchDefaultAppsSettingsModernDialog(base::WStringPiece protocol) {
+bool LaunchDefaultAppsSettingsModernDialog(std::wstring_view protocol) {
   // The appModelId looks arbitrary but it is the same in Win8 and Win10. There
   // is no easy way to retrieve the appModelId from the registry.
   static constexpr wchar_t kControlPanelAppModelId[] =
diff --git a/base/win/default_apps_util.h b/base/win/default_apps_util.h
index ed39e0aa..1634f54 100644
--- a/base/win/default_apps_util.h
+++ b/base/win/default_apps_util.h
@@ -5,8 +5,9 @@
 #ifndef BASE_WIN_DEFAULT_APPS_UTIL_H_
 #define BASE_WIN_DEFAULT_APPS_UTIL_H_
 
+#include <string_view>
+
 #include "base/base_export.h"
-#include "base/strings/string_piece.h"
 
 namespace base::win {
 
@@ -15,7 +16,7 @@
 // the dialog. Returns true if the default apps dialog was successfully opened,
 // and the `protocol`, if not empty, was highlighted.
 BASE_EXPORT bool LaunchDefaultAppsSettingsModernDialog(
-    base::WStringPiece protocol);
+    std::wstring_view protocol);
 
 }  // namespace base::win
 
diff --git a/base/win/embedded_i18n/language_selector.cc b/base/win/embedded_i18n/language_selector.cc
index 8df39b6b..9f509362 100644
--- a/base/win/embedded_i18n/language_selector.cc
+++ b/base/win/embedded_i18n/language_selector.cc
@@ -11,6 +11,7 @@
 
 #include <algorithm>
 #include <functional>
+#include <string_view>
 
 #include "base/check_op.h"
 #include "base/memory/raw_ptr.h"
@@ -304,7 +305,7 @@
 }
 
 std::vector<std::wstring> GetCandidatesFromSystem(
-    WStringPiece preferred_language) {
+    std::wstring_view preferred_language) {
   std::vector<std::wstring> candidates;
 
   // Get the initial candidate list for this particular implementation (if
@@ -320,7 +321,7 @@
 
 }  // namespace
 
-LanguageSelector::LanguageSelector(WStringPiece preferred_language,
+LanguageSelector::LanguageSelector(std::wstring_view preferred_language,
                                    span<const LangToOffset> languages_to_offset)
     : LanguageSelector(GetCandidatesFromSystem(preferred_language),
                        languages_to_offset) {}
diff --git a/base/win/embedded_i18n/language_selector.h b/base/win/embedded_i18n/language_selector.h
index 8b3b991..96c1c88 100644
--- a/base/win/embedded_i18n/language_selector.h
+++ b/base/win/embedded_i18n/language_selector.h
@@ -9,12 +9,12 @@
 #define BASE_WIN_EMBEDDED_I18N_LANGUAGE_SELECTOR_H_
 
 #include <string>
+#include <string_view>
 #include <utility>
 #include <vector>
 
 #include "base/base_export.h"
 #include "base/containers/span.h"
-#include "base/strings/string_piece.h"
 
 namespace base {
 namespace win {
@@ -25,7 +25,7 @@
 // override selection should a corresponding translation be available.
 class BASE_EXPORT LanguageSelector {
  public:
-  using LangToOffset = std::pair<WStringPiece, size_t>;
+  using LangToOffset = std::pair<std::wstring_view, size_t>;
 
   // Constructor to be used for users of this class that will provide the actual
   // language offsets that will be used.
@@ -35,7 +35,7 @@
   // |languages_to_offset_begin| and |languages_to_offset_end| point to a sorted
   // array of language identifiers (and their offsets) for which translations
   // are available.
-  LanguageSelector(WStringPiece preferred_language,
+  LanguageSelector(std::wstring_view preferred_language,
                    span<const LangToOffset> languages_to_offset);
 
   // Constructor for testing purposes.
diff --git a/base/win/hstring_reference_unittest.cc b/base/win/hstring_reference_unittest.cc
index 64fa913..3f67ff2 100644
--- a/base/win/hstring_reference_unittest.cc
+++ b/base/win/hstring_reference_unittest.cc
@@ -5,8 +5,8 @@
 #include "base/win/hstring_reference.h"
 
 #include <string>
+#include <string_view>
 
-#include "base/strings/string_piece.h"
 #include "base/win/scoped_hstring.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -19,7 +19,7 @@
 
 void VerifyHSTRINGEquals(HSTRING hstring, const wchar_t* test_string) {
   const ScopedHString scoped_hstring(hstring);
-  const WStringPiece hstring_contents = scoped_hstring.Get();
+  const std::wstring_view hstring_contents = scoped_hstring.Get();
   EXPECT_EQ(hstring_contents.compare(test_string), 0);
 }
 
diff --git a/base/win/i18n.cc b/base/win/i18n.cc
index 5cee9ed..bd2b851 100644
--- a/base/win/i18n.cc
+++ b/base/win/i18n.cc
@@ -7,6 +7,7 @@
 #include <windows.h>
 
 #include <ostream>
+#include <string_view>
 
 #include "base/check_op.h"
 #include "base/strings/string_piece.h"
@@ -17,7 +18,7 @@
 
 using GetPreferredUILanguages_Fn = decltype(::GetSystemPreferredUILanguages)*;
 
-constexpr base::WStringPiece kNullTerminator{L"\0", 1};
+constexpr std::wstring_view kNullTerminator{L"\0", 1};
 
 bool GetPreferredUILanguageList(GetPreferredUILanguages_Fn function,
                                 ULONG flags,
diff --git a/base/win/registry_unittest.cc b/base/win/registry_unittest.cc
index 29358457..cda6b8a 100644
--- a/base/win/registry_unittest.cc
+++ b/base/win/registry_unittest.cc
@@ -11,6 +11,7 @@
 
 #include <cstring>
 #include <iterator>
+#include <string_view>
 #include <utility>
 
 #include "base/compiler_specific.h"
@@ -162,7 +163,7 @@
   ASSERT_TRUE(iterator.Valid());
   // Avoid having to use EXPECT_STREQ here by leveraging StringPiece's
   // operator== to perform a deep comparison.
-  EXPECT_EQ(WStringPiece(kName), WStringPiece(iterator.Name()));
+  EXPECT_EQ(std::wstring_view(kName), std::wstring_view(iterator.Name()));
   // ValueSize() is in bytes.
   ASSERT_EQ(std::size(kData), iterator.ValueSize());
   // Value() is NUL terminated.
@@ -183,17 +184,17 @@
 
 // Tests that the default value is seen by a value iterator.
 TEST_F(RegistryTest, ValueIteratorDefaultValue) {
-  const WStringPiece kTestString(L"i miss you");
+  const std::wstring_view kTestString(L"i miss you");
   ASSERT_EQ(RegKey(HKEY_CURRENT_USER, root_key().c_str(), KEY_SET_VALUE)
                 .WriteValue(nullptr, kTestString.data()),
             ERROR_SUCCESS);
   RegistryValueIterator iterator(HKEY_CURRENT_USER, root_key().c_str());
   EXPECT_EQ(iterator.ValueCount(), 1U);
   ASSERT_TRUE(iterator.Valid());
-  EXPECT_EQ(WStringPiece(iterator.Name()), WStringPiece());
+  EXPECT_EQ(std::wstring_view(iterator.Name()), std::wstring_view());
   EXPECT_EQ(iterator.ValueSize(), (kTestString.size() + 1) * sizeof(wchar_t));
   EXPECT_EQ(iterator.Type(), REG_SZ);
-  EXPECT_EQ(WStringPiece(iterator.Value()), kTestString);
+  EXPECT_EQ(std::wstring_view(iterator.Value()), kTestString);
   ++iterator;
   EXPECT_FALSE(iterator.Valid());
 }
diff --git a/base/win/scoped_bstr.cc b/base/win/scoped_bstr.cc
index d3146944..1927dd0 100644
--- a/base/win/scoped_bstr.cc
+++ b/base/win/scoped_bstr.cc
@@ -6,6 +6,8 @@
 
 #include <stdint.h>
 
+#include <string_view>
+
 #include "base/check.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/process/memory.h"
@@ -16,7 +18,7 @@
 
 namespace {
 
-BSTR AllocBstrOrDie(WStringPiece non_bstr) {
+BSTR AllocBstrOrDie(std::wstring_view non_bstr) {
   BSTR result = ::SysAllocStringLen(non_bstr.data(),
                                     checked_cast<UINT>(non_bstr.length()));
   if (!result) {
@@ -35,7 +37,7 @@
 
 }  // namespace
 
-ScopedBstr::ScopedBstr(WStringPiece non_bstr)
+ScopedBstr::ScopedBstr(std::wstring_view non_bstr)
     : bstr_(AllocBstrOrDie(non_bstr)) {}
 
 ScopedBstr::~ScopedBstr() {
@@ -68,7 +70,7 @@
   return &bstr_;
 }
 
-BSTR ScopedBstr::Allocate(WStringPiece str) {
+BSTR ScopedBstr::Allocate(std::wstring_view str) {
   Reset(AllocBstrOrDie(str));
   return bstr_;
 }
diff --git a/base/win/scoped_bstr.h b/base/win/scoped_bstr.h
index 6f303f8..d8e4f6f9 100644
--- a/base/win/scoped_bstr.h
+++ b/base/win/scoped_bstr.h
@@ -10,9 +10,10 @@
 #include <oleauto.h>
 #include <stddef.h>
 
+#include <string_view>
+
 #include "base/base_export.h"
 #include "base/check.h"
-#include "base/strings/string_piece.h"
 
 namespace base {
 namespace win {
@@ -27,7 +28,7 @@
   //
   // NOTE: Do not pass a BSTR to this constructor expecting ownership to
   // be transferred - even though it compiles! ;-)
-  explicit ScopedBstr(WStringPiece non_bstr);
+  explicit ScopedBstr(std::wstring_view non_bstr);
 
   ScopedBstr(const ScopedBstr&) = delete;
   ScopedBstr& operator=(const ScopedBstr&) = delete;
@@ -49,7 +50,7 @@
   // ScopedBstr instance, call |reset| instead.
   //
   // Returns a pointer to the new BSTR.
-  BSTR Allocate(WStringPiece str);
+  BSTR Allocate(std::wstring_view str);
 
   // Allocates a new BSTR with the specified number of bytes.
   // Returns a pointer to the new BSTR.
diff --git a/base/win/scoped_hstring.cc b/base/win/scoped_hstring.cc
index 042768f..20e027e3 100644
--- a/base/win/scoped_hstring.cc
+++ b/base/win/scoped_hstring.cc
@@ -8,6 +8,7 @@
 
 #include <ostream>
 #include <string>
+#include <string_view>
 
 #include "base/check.h"
 #include "base/notreached.h"
@@ -32,7 +33,7 @@
 ScopedHString::ScopedHString(HSTRING hstr) : ScopedGeneric(hstr) {}
 
 // static
-ScopedHString ScopedHString::Create(WStringPiece str) {
+ScopedHString ScopedHString::Create(std::wstring_view str) {
   HSTRING hstr;
   HRESULT hr = ::WindowsCreateString(str.data(),
                                      checked_cast<UINT32>(str.length()), &hstr);
@@ -57,10 +58,10 @@
 }
 
 // static
-WStringPiece ScopedHString::Get() const {
+std::wstring_view ScopedHString::Get() const {
   UINT32 length = 0;
   const wchar_t* buffer = ::WindowsGetStringRawBuffer(get(), &length);
-  return WStringPiece(buffer, length);
+  return std::wstring_view(buffer, length);
 }
 
 std::string ScopedHString::GetAsUTF8() const {
diff --git a/base/win/scoped_hstring.h b/base/win/scoped_hstring.h
index 4f30f72..50b8451 100644
--- a/base/win/scoped_hstring.h
+++ b/base/win/scoped_hstring.h
@@ -8,6 +8,7 @@
 #include <hstring.h>
 
 #include <string>
+#include <string_view>
 
 #include "base/scoped_generic.h"
 #include "base/strings/string_piece.h"
@@ -45,13 +46,13 @@
   // Constructs a ScopedHString from an HSTRING, and takes ownership of |hstr|.
   explicit ScopedHString(HSTRING hstr);
 
-  static ScopedHString Create(WStringPiece str);
+  static ScopedHString Create(std::wstring_view str);
   static ScopedHString Create(StringPiece str);
 
   // Returns a view into the memory buffer managed by the instance. The returned
   // StringPiece is only valid during the lifetime of this ScopedHString
   // instance.
-  WStringPiece Get() const;
+  std::wstring_view Get() const;
 
   // Returns a copy of the instance as a UTF-8 string.
   std::string GetAsUTF8() const;
diff --git a/base/win/scoped_hstring_unittest.cc b/base/win/scoped_hstring_unittest.cc
index aee4f27e..e83726bd 100644
--- a/base/win/scoped_hstring_unittest.cc
+++ b/base/win/scoped_hstring_unittest.cc
@@ -7,6 +7,7 @@
 #include <winstring.h>
 
 #include <string>
+#include <string_view>
 
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -24,7 +25,7 @@
   ScopedHString hstring = ScopedHString::Create(kTestString1);
   std::string buffer = hstring.GetAsUTF8();
   EXPECT_EQ(kTestString1, UTF8ToWide(buffer));
-  WStringPiece contents = hstring.Get();
+  std::wstring_view contents = hstring.Get();
   EXPECT_EQ(kTestString1, contents);
 
   hstring.reset();
diff --git a/base/win/win_util.cc b/base/win/win_util.cc
index 0d81e7c..71e8995 100644
--- a/base/win/win_util.cc
+++ b/base/win/win_util.cc
@@ -34,6 +34,7 @@
 
 #include <limits>
 #include <memory>
+#include <string_view>
 #include <utility>
 
 #include "base/base_switches.h"
@@ -740,7 +741,7 @@
   return object_name;
 }
 
-bool IsRunningUnderDesktopName(WStringPiece desktop_name) {
+bool IsRunningUnderDesktopName(std::wstring_view desktop_name) {
   HDESK thread_desktop = ::GetThreadDesktop(::GetCurrentThreadId());
   if (!thread_desktop)
     return false;
diff --git a/base/win/win_util.h b/base/win/win_util.h
index 8dfeca4..1276f27e 100644
--- a/base/win/win_util.h
+++ b/base/win/win_util.h
@@ -25,10 +25,10 @@
 #include <stdint.h>
 
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/base_export.h"
-#include "base/strings/string_piece.h"
 #include "base/win/windows_types.h"
 
 struct IPropertyStore;
@@ -223,7 +223,7 @@
 // Checks if the calling thread is running under a desktop with the name
 // given by |desktop_name|. |desktop_name| is ASCII case insensitive (non-ASCII
 // characters will be compared with exact matches).
-BASE_EXPORT bool IsRunningUnderDesktopName(WStringPiece desktop_name);
+BASE_EXPORT bool IsRunningUnderDesktopName(std::wstring_view desktop_name);
 
 // Returns true if current session is a remote session.
 BASE_EXPORT bool IsCurrentSessionRemote();
diff --git a/base/win/win_util_unittest.cc b/base/win/win_util_unittest.cc
index ddffd655..c5df0c7 100644
--- a/base/win/win_util_unittest.cc
+++ b/base/win/win_util_unittest.cc
@@ -6,6 +6,8 @@
 
 #include <objbase.h>
 
+#include <string_view>
+
 #include "base/containers/contains.h"
 #include "base/files/file_path.h"
 #include "base/scoped_native_library.h"
@@ -79,7 +81,7 @@
                       0xf5b0,
                       0x4328,
                       {0x92, 0x38, 0xbd, 0x70, 0x8a, 0x6d, 0xc9, 0x63}};
-  const base::WStringPiece kGuidStr = L"{7698F759-F5B0-4328-9238-BD708A6DC963}";
+  const std::wstring_view kGuidStr = L"{7698F759-F5B0-4328-9238-BD708A6DC963}";
   auto guid_wstring = WStringFromGUID(kGuid);
   EXPECT_EQ(guid_wstring, kGuidStr);
   wchar_t guid_wchar[39];
diff --git a/base/win/wmi.cc b/base/win/wmi.cc
index 525b305..b5b384e 100644
--- a/base/win/wmi.cc
+++ b/base/win/wmi.cc
@@ -8,6 +8,8 @@
 
 #include <objbase.h>
 #include <stdint.h>
+
+#include <string_view>
 #include <utility>
 
 #include "base/location.h"
@@ -132,8 +134,8 @@
 }
 
 bool CreateWmiClassMethodObject(IWbemServices* wmi_services,
-                                WStringPiece class_name,
-                                WStringPiece method_name,
+                                std::wstring_view class_name,
+                                std::wstring_view method_name,
                                 ComPtr<IWbemClassObject>* class_instance) {
   // We attempt to instantiate a COM object that represents a WMI object plus
   // a method rolled into one entity.
diff --git a/base/win/wmi.h b/base/win/wmi.h
index 02834da..d918ede0 100644
--- a/base/win/wmi.h
+++ b/base/win/wmi.h
@@ -23,8 +23,9 @@
 #include <wbemidl.h>
 #include <wrl/client.h>
 
+#include <string_view>
+
 #include "base/base_export.h"
-#include "base/strings/string_piece.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
@@ -84,8 +85,8 @@
 // WMI method that you can fill with parameter values using SetParameter.
 BASE_EXPORT bool CreateWmiClassMethodObject(
     IWbemServices* wmi_services,
-    WStringPiece class_name,
-    WStringPiece method_name,
+    std::wstring_view class_name,
+    std::wstring_view method_name,
     Microsoft::WRL::ComPtr<IWbemClassObject>* class_instance);
 
 // Creates a new process from |command_line|. The advantage over CreateProcess
diff --git a/build/rust/std/BUILD.gn.hbs b/build/rust/std/BUILD.gn.hbs
index 9f3b4d3..1423df8 100644
--- a/build/rust/std/BUILD.gn.hbs
+++ b/build/rust/std/BUILD.gn.hbs
@@ -7,8 +7,8 @@
 import("//build/rust/cargo_crate.gni")
 
 {{#each rules}}
-cargo_crate("{{this.0}}") {
-  {{#with this.1.concrete}}
+{{#with this.detail.crate}}
+cargo_crate("{{../name}}") {
   crate_type = "{{crate_type}}"
   crate_root = "{{crate_root}}"
   sources = [
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
index a40cdb7..b493a59 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
@@ -72,6 +72,7 @@
 
         for (Message message : mShownMessageItems.values()) {
             message.model.set(MessageCardViewProperties.IS_INCOGNITO, mIsIncognitoSupplier.get());
+            message.model.set(TabListModel.CardProperties.CARD_ALPHA, 1F);
         }
 
         return new ArrayList<>(mShownMessageItems.values());
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
index a81477b..8181276 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
@@ -795,8 +795,6 @@
                 mMessageCardProviderCoordinator.getMessageItems();
         for (int i = 0; i < messages.size(); i++) {
             if (!shouldAppendMessage(messages.get(i).model)) continue;
-            messages.get(i).model.set(TabListModel.CardProperties.CARD_ALPHA, 1F);
-
             if (messages.get(i).type == MessageService.MessageType.PRICE_MESSAGE) {
                 mTabListCoordinator.addSpecialListItem(
                         index, TabProperties.UiType.LARGE_MESSAGE, messages.get(i).model);
diff --git a/chrome/app/chrome_dll.rc b/chrome/app/chrome_dll.rc
index 08452da..fc761eab 100644
--- a/chrome/app/chrome_dll.rc
+++ b/chrome/app/chrome_dll.rc
@@ -171,6 +171,8 @@
 IDR_SXS             ICON                        "theme\google_chrome\win\chrome_sxs.ico"
 IDR_X004_DEV        ICON                        "theme\google_chrome\win\chrome_dev.ico"
 IDR_X005_BETA       ICON                        "theme\google_chrome\win\chrome_beta.ico"
+#elif BUILDFLAG(GOOGLE_CHROME_FOR_TESTING_BRANDING)
+IDR_MAINFRAME       ICON                        "theme\google_chrome\google_chrome_for_testing\win\chrome.ico"
 #else
 IDR_MAINFRAME       ICON                        "theme\chromium\win\chromium.ico"
 #endif
diff --git a/chrome/app/chrome_exe.rc b/chrome/app/chrome_exe.rc
index 5eb0c3b..37f98d7 100644
--- a/chrome/app/chrome_exe.rc
+++ b/chrome/app/chrome_exe.rc
@@ -46,6 +46,8 @@
 // The SXS icon must have an index of 4, the constant is used in Chrome code to
 // identify it.
 IDR_SXS                 ICON       "theme\\google_chrome\\win\\chrome_sxs.ico"
+#elif BUILDFLAG(GOOGLE_CHROME_FOR_TESTING_BRANDING)
+IDR_MAINFRAME           ICON       "theme\\google_chrome\\google_chrome_for_testing\\win\\chrome.ico"
 #else
 IDR_MAINFRAME           ICON       "theme\\chromium\\win\\chromium.ico"
 #endif
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index a73f18c..42f2455 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -441,7 +441,6 @@
   "+services/media_session/public",
   "+services/metrics/metrics_mojo_service.h",
   "+services/metrics/public",
-  "+services/network/cert_verifier_with_trust_anchors.h",
   "+services/network/network_service.h",
   "+services/network/public",
   "+services/network/test",
diff --git a/chrome/browser/android/webapk/webapk_sync_bridge.cc b/chrome/browser/android/webapk/webapk_sync_bridge.cc
index cbdaf68..debd0c5 100644
--- a/chrome/browser/android/webapk/webapk_sync_bridge.cc
+++ b/chrome/browser/android/webapk/webapk_sync_bridge.cc
@@ -7,7 +7,9 @@
 #include <memory>
 #include <vector>
 
+#include "base/functional/callback_helpers.h"
 #include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/time/clock.h"
 #include "base/time/default_clock.h"
 #include "base/time/time.h"
@@ -15,6 +17,7 @@
 #include "chrome/browser/android/webapk/webapk_database_factory.h"
 #include "chrome/browser/android/webapk/webapk_helpers.h"
 #include "chrome/browser/android/webapk/webapk_registry_update.h"
+#include "chrome/browser/android/webapk/webapk_specifics_fetcher.h"
 #include "chrome/common/channel_info.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/base/report_unrecoverable_error.h"
@@ -96,15 +99,18 @@
               syncer::WEB_APPS,
               base::BindRepeating(&syncer::ReportUnrecoverableError,
                                   chrome::GetChannel())),
-          std::make_unique<base::DefaultClock>()) {}
+          std::make_unique<base::DefaultClock>(),
+          std::make_unique<WebApkSpecificsFetcher>()) {}
 
 WebApkSyncBridge::WebApkSyncBridge(
     AbstractWebApkDatabaseFactory* database_factory,
     base::OnceClosure on_initialized,
     std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
-    std::unique_ptr<base::Clock> clock)
+    std::unique_ptr<base::Clock> clock,
+    std::unique_ptr<AbstractWebApkSpecificsFetcher> specifics_fetcher)
     : syncer::ModelTypeSyncBridge(std::move(change_processor)),
-      clock_(std::move(clock)) {
+      clock_(std::move(clock)),
+      webapk_specifics_fetcher_(std::move(specifics_fetcher)) {
   CHECK(database_factory);
   database_ = std::make_unique<WebApkDatabase>(
       database_factory,
@@ -227,10 +233,108 @@
   }
 }
 
+void WebApkSyncBridge::SendInstalledAndRegistryAppsToSync(
+    const std::vector<const sync_pb::WebApkSpecifics*>&
+        sync_update_from_installed,
+    const std::unique_ptr<RegistryUpdateData>&
+        registry_update_from_installed_and_sync,
+    syncer::MetadataChangeList* metadata_change_list) {
+  for (const sync_pb::WebApkSpecifics* sync_update :
+       sync_update_from_installed) {
+    webapps::AppId app_id = ManifestIdStrToAppId(sync_update->manifest_id());
+    change_processor()->Put(app_id,
+                            CreateSyncEntityDataFromSpecifics(*sync_update),
+                            metadata_change_list);
+  }
+
+  std::set<webapps::AppId> registry_update_from_installed_and_sync_set;
+  for (const auto& registry_update :
+       registry_update_from_installed_and_sync->apps_to_create) {
+    webapps::AppId app_id =
+        ManifestIdStrToAppId(registry_update->sync_data().manifest_id());
+    registry_update_from_installed_and_sync_set.insert(app_id);
+  }
+  for (const webapps::AppId& registry_update :
+       registry_update_from_installed_and_sync->apps_to_delete) {
+    registry_update_from_installed_and_sync_set.insert(registry_update);
+  }
+
+  for (const auto& registry_entry : registry_) {
+    const webapps::AppId& app_id = registry_entry.first;
+    const std::unique_ptr<WebApkProto>& app = registry_entry.second;
+
+    if (registry_update_from_installed_and_sync_set.count(app_id) != 0) {
+      continue;
+    }
+
+    change_processor()->Put(app_id,
+                            CreateSyncEntityDataFromSpecifics(app->sync_data()),
+                            metadata_change_list);
+  }
+}
+
+void WebApkSyncBridge::OnDataWritten(CommitCallback callback, bool success) {
+  if (!success) {
+    DLOG(ERROR) << "WebApkSyncBridge commit failed";
+  }
+
+  base::UmaHistogramBoolean("WebApk.Database.WriteResult", success);
+  std::move(callback).Run(success);
+}
+
+void WebApkSyncBridge::ApplyIncrementalSyncChangesToRegistry(
+    std::unique_ptr<RegistryUpdateData> update_data) {
+  if (update_data->isEmpty()) {
+    return;
+  }
+
+  for (auto& app : update_data->apps_to_create) {
+    webapps::AppId app_id =
+        ManifestIdStrToAppId(app->sync_data().manifest_id());
+    auto it = registry_.find(app_id);
+    if (it != registry_.end()) {
+      registry_.erase(it);
+    }
+    registry_.emplace(std::move(app_id), std::move(app));
+  }
+
+  for (const webapps::AppId& app_id : update_data->apps_to_delete) {
+    auto it = registry_.find(app_id);
+    CHECK(it != registry_.end());
+    registry_.erase(it);
+  }
+}
+
 absl::optional<syncer::ModelError> WebApkSyncBridge::MergeFullSyncData(
     std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
     syncer::EntityChangeList entity_changes) {
-  // TODO(hartmanng): implement
+  CHECK(change_processor()->IsTrackingMetadata());
+
+  std::vector<std::unique_ptr<sync_pb::WebApkSpecifics>> installed_apps =
+      webapk_specifics_fetcher_->GetWebApkSpecifics();
+
+  std::vector<const sync_pb::WebApkSpecifics*> sync_update_from_installed;
+  PrepareSyncUpdateFromInstalledApps(installed_apps, entity_changes,
+                                     &sync_update_from_installed);
+
+  std::unique_ptr<RegistryUpdateData> registry_update_from_installed_and_sync =
+      std::make_unique<RegistryUpdateData>();
+  PrepareRegistryUpdateFromInstalledAndSyncApps(
+      sync_update_from_installed, entity_changes,
+      registry_update_from_installed_and_sync.get());
+
+  SendInstalledAndRegistryAppsToSync(sync_update_from_installed,
+                                     registry_update_from_installed_and_sync,
+                                     metadata_change_list.get());
+
+  database_->Write(
+      *registry_update_from_installed_and_sync, std::move(metadata_change_list),
+      base::BindOnce(&WebApkSyncBridge::OnDataWritten,
+                     weak_ptr_factory_.GetWeakPtr(), base::DoNothing()));
+
+  ApplyIncrementalSyncChangesToRegistry(
+      std::move(registry_update_from_installed_and_sync));
+
   return absl::nullopt;
 }
 
@@ -284,4 +388,8 @@
   return GetClientTag(entity_data);
 }
 
+const Registry& WebApkSyncBridge::GetRegistryForTesting() const {
+  return registry_;
+}
+
 }  // namespace webapk
diff --git a/chrome/browser/android/webapk/webapk_sync_bridge.h b/chrome/browser/android/webapk/webapk_sync_bridge.h
index e9ee370..0f7058d9 100644
--- a/chrome/browser/android/webapk/webapk_sync_bridge.h
+++ b/chrome/browser/android/webapk/webapk_sync_bridge.h
@@ -10,6 +10,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/clock.h"
 #include "chrome/browser/android/webapk/webapk_database.h"
+#include "chrome/browser/android/webapk/webapk_specifics_fetcher.h"
 #include "components/sync/model/entity_change.h"
 #include "components/sync/model/model_type_sync_bridge.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -45,11 +46,14 @@
       AbstractWebApkDatabaseFactory* database_factory,
       base::OnceClosure on_initialized,
       std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
-      std::unique_ptr<base::Clock> clock);
+      std::unique_ptr<base::Clock> clock,
+      std::unique_ptr<AbstractWebApkSpecificsFetcher> specifics_fetcher);
   WebApkSyncBridge(const WebApkSyncBridge&) = delete;
   WebApkSyncBridge& operator=(const WebApkSyncBridge&) = delete;
   ~WebApkSyncBridge() override;
 
+  using CommitCallback = base::OnceCallback<void(bool success)>;
+
   // syncer::ModelTypeSyncBridge:
   std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
       override;
@@ -111,15 +115,48 @@
       const syncer::EntityChangeList& sync_changes,
       RegistryUpdateData* registry_update_from_installed_and_sync) const;
 
+  const Registry& GetRegistryForTesting() const;
+
  private:
+  void ReportErrorToChangeProcessor(const syncer::ModelError& error);
   void OnDatabaseOpened(base::OnceClosure callback,
                         Registry registry,
                         std::unique_ptr<syncer::MetadataBatch> metadata_batch);
-  void ReportErrorToChangeProcessor(const syncer::ModelError& error);
+  void OnDataWritten(CommitCallback callback, bool success);
+
+  // SendInstalledAndRegistryAppsToSync sends a collection of updates to Sync
+  // based on a combination of |registry_| and the app lists gathered in
+  // PrepareSyncUpdateFromInstalledApps() and
+  // PrepareRegistryUpdateFromInstalledAndSyncApps(). This is "Step 3" of
+  // https://docs.google.com/document/d/1Pce17EEuIs0dIbw-L1RZVf2HA4H8-Lu8RqVxHGmdJds.
+  //
+  // Concretely, we send all the updates from installed apps
+  // (|sync_update_from_installed|) as well as everything in |registry_| that
+  // isn't already covered in |registry_update_from_installed_and_sync|. In
+  // other words, this pushes all relevant updates from installed apps, and
+  // anything in the registry that appeared in neither installed nor synced
+  // apps.
+  //
+  // |sync_update_from_installed| and |registry_update_from_installed_and_sync|
+  // are inputs, and |metadata_change_list| is appended to as an output.
+  void SendInstalledAndRegistryAppsToSync(
+      const std::vector<const sync_pb::WebApkSpecifics*>&
+          sync_update_from_installed,
+      const std::unique_ptr<RegistryUpdateData>&
+          registry_update_from_installed_and_sync,
+      syncer::MetadataChangeList* metadata_change_list);
+
+  // ApplyIncrementalSyncChangesToRegistry applies the changes in the app list
+  // gathered in PrepareRegistryUpdateFromInstalledAndSyncApps() to the
+  // registry. This is "Step 5" (the final step) from
+  // https://docs.google.com/document/d/1Pce17EEuIs0dIbw-L1RZVf2HA4H8-Lu8RqVxHGmdJds.
+  void ApplyIncrementalSyncChangesToRegistry(
+      std::unique_ptr<RegistryUpdateData> update_data);
 
   std::unique_ptr<WebApkDatabase> database_;
   Registry registry_;
   std::unique_ptr<base::Clock> clock_;
+  std::unique_ptr<AbstractWebApkSpecificsFetcher> webapk_specifics_fetcher_;
 
   base::WeakPtrFactory<WebApkSyncBridge> weak_ptr_factory_{this};
 };
diff --git a/chrome/browser/android/webapk/webapk_sync_bridge_unittest.cc b/chrome/browser/android/webapk/webapk_sync_bridge_unittest.cc
index 6f65f07..2647953 100644
--- a/chrome/browser/android/webapk/webapk_sync_bridge_unittest.cc
+++ b/chrome/browser/android/webapk/webapk_sync_bridge_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "chrome/browser/android/webapk/test/fake_webapk_database_factory.h"
+#include "chrome/browser/android/webapk/test/fake_webapk_specifics_fetcher.h"
 #include "chrome/browser/android/webapk/webapk_database_factory.h"
 #include "chrome/browser/android/webapk/webapk_helpers.h"
 #include "chrome/browser/android/webapk/webapk_registry_update.h"
@@ -66,13 +67,14 @@
   return true;
 }
 
-std::unique_ptr<WebApkProto> CreateWebApkProto(const std::string& url) {
+std::unique_ptr<WebApkProto> CreateWebApkProto(const std::string& url,
+                                               const std::string& name) {
   std::unique_ptr<WebApkProto> web_apk = std::make_unique<WebApkProto>();
 
   sync_pb::WebApkSpecifics* sync_data = web_apk->mutable_sync_data();
   sync_data->set_manifest_id(url);
   sync_data->set_start_url(url);
-  sync_data->set_name("Name");
+  sync_data->set_name(name);
 
   return web_apk;
 }
@@ -110,9 +112,15 @@
     clock->SetNow(base::Time::FromSecondsSinceUnixEpoch(
         1136232245.0));  // Mon Jan 02 2006 15:04:05 GMT-0500
 
+    std::unique_ptr<FakeWebApkSpecificsFetcher> specifics_fetcher =
+        std::make_unique<FakeWebApkSpecificsFetcher>();
+    specifics_fetcher_ = specifics_fetcher.get();
+
     sync_bridge_ = std::make_unique<WebApkSyncBridge>(
         database_factory_.get(), loop.QuitClosure(),
-        mock_processor_.CreateForwardingProcessor(), std::move(clock));
+        mock_processor_.CreateForwardingProcessor(), std::move(clock),
+        std::move(specifics_fetcher));
+
     loop.Run();
   }
 
@@ -130,10 +138,17 @@
   FakeWebApkDatabaseFactory& database_factory() { return *database_factory_; }
 
   WebApkSyncBridge& sync_bridge() { return *sync_bridge_; }
+  FakeWebApkSpecificsFetcher& specifics_fetcher() {
+    return *specifics_fetcher_;
+  }
 
  private:
   std::unique_ptr<WebApkSyncBridge> sync_bridge_;
   std::unique_ptr<FakeWebApkDatabaseFactory> database_factory_;
+  raw_ptr<FakeWebApkSpecificsFetcher>
+      specifics_fetcher_;  // owned by sync_bridge_; should not be accessed
+                           // before InitSyncBridge() or after sync_bridge_ is
+                           // destroyed
 
   testing::NiceMock<syncer::MockModelTypeChangeProcessor> mock_processor_;
 };
@@ -317,7 +332,8 @@
 
   Registry registry;
 
-  std::unique_ptr<WebApkProto> synced_app1 = CreateWebApkProto(manifest_id_5);
+  std::unique_ptr<WebApkProto> synced_app1 =
+      CreateWebApkProto(manifest_id_5, "name");
   InsertAppIntoRegistry(&registry, std::move(synced_app1));
 
   database_factory().WriteRegistry(registry);
@@ -425,6 +441,303 @@
             registry_update_from_installed_and_sync.apps_to_delete.at(0));
 }
 
+TEST_F(WebApkSyncBridgeTest, MergeFullSyncData) {
+  // inputs:
+  //   installed:
+  //     * App1 middle timestamp
+  //     * App2 old
+  //     * App3 too old
+  //
+  //   sync:
+  //     * App1 add oldest
+  //     * App2 add new
+  //     * App4 add
+  //     * App5 delete
+  //
+  //   registry:
+  //     * App1 newest
+  //     * App5
+  //     * App6
+  //
+  // outputs:
+  //   send to sync:
+  //     * App1 middle (installed)
+  //     * App6 (registry)
+  //
+  //   final state (sync, registry, and db):
+  //     * App1 middle (installed)
+  //     * App2 new (sync)
+  //     * App4 (sync)
+  //     * App6 (registry)
+
+  base::test::SingleThreadTaskEnvironment task_environment;
+
+  const std::string manifest_id_1 = "https://example.com/app1";
+  const std::string manifest_id_2 = "https://example.com/app2";
+  const std::string manifest_id_3 = "https://example.com/app3";
+  const std::string manifest_id_4 = "https://example.com/app4";
+  const std::string manifest_id_5 = "https://example.com/app5";
+  const std::string manifest_id_6 = "https://example.com/app6";
+
+  Registry registry;
+
+  // not sent to sync or included in final state (installed version always
+  // overrides registry version)
+  std::unique_ptr<WebApkProto> registry_app1 =
+      CreateWebApkProto(manifest_id_1, "app1_registry");
+  registry_app1->mutable_sync_data()->set_last_used_time_windows_epoch_micros(
+      UnixTsSecToWindowsTsMsec(
+          1136145845.0));  // Sun Jan 01 2006 15:04:05 GMT-0500 - newest app1
+                           // timestamp
+  InsertAppIntoRegistry(&registry, std::move(registry_app1));
+
+  // not sent to sync or included in final state (deleted by sync)
+  std::unique_ptr<WebApkProto> registry_app5 =
+      CreateWebApkProto(manifest_id_5, "app5_registry");
+  InsertAppIntoRegistry(&registry, std::move(registry_app5));
+
+  // sent to sync and included in final state (no other version exists)
+  std::unique_ptr<WebApkProto> registry_app6 =
+      CreateWebApkProto(manifest_id_6, "app6_registry");
+  InsertAppIntoRegistry(&registry, std::move(registry_app6));
+
+  database_factory().WriteRegistry(registry);
+
+  EXPECT_CALL(processor(), ModelReadyToSync(_)).Times(1);
+  InitSyncBridge();
+
+  // sent to sync and included in final state (newer than sync version,
+  // installed always overrides registry version)
+  std::unique_ptr<sync_pb::WebApkSpecifics> installed_app1 =
+      std::make_unique<sync_pb::WebApkSpecifics>();
+  installed_app1->set_manifest_id(manifest_id_1);
+  installed_app1->set_name("app1_installed");
+  installed_app1->set_last_used_time_windows_epoch_micros(
+      UnixTsSecToWindowsTsMsec(
+          1135109045.0));  // Tue Dec 20 2005 15:04:05 GMT-0500 - between sync
+                           // and registry app1 timestamps
+
+  // not sent to sync or included in final state (older than sync version)
+  std::unique_ptr<sync_pb::WebApkSpecifics> installed_app2 =
+      std::make_unique<sync_pb::WebApkSpecifics>();
+  installed_app2->set_manifest_id(manifest_id_2);
+  installed_app2->set_name("app2_installed");
+  installed_app2->set_last_used_time_windows_epoch_micros(
+      UnixTsSecToWindowsTsMsec(
+          1134072245.0));  // Thu Dec 08 2005 15:04:05 GMT-0500 - oldest app2
+                           // timestamp
+
+  // not sent to sync or included in final state (more than 30 days old)
+  std::unique_ptr<sync_pb::WebApkSpecifics> installed_app3 =
+      std::make_unique<sync_pb::WebApkSpecifics>();
+  installed_app3->set_manifest_id(manifest_id_3);
+  installed_app3->set_name("app3_installed");
+  installed_app3->set_last_used_time_windows_epoch_micros(
+      UnixTsSecToWindowsTsMsec(
+          1131480245.0));  // Tue Nov 08 2005 15:04:05 GMT-0500 - too old
+
+  std::unique_ptr<std::vector<std::unique_ptr<sync_pb::WebApkSpecifics>>>
+      installed_apps = std::make_unique<
+          std::vector<std::unique_ptr<sync_pb::WebApkSpecifics>>>();
+  installed_apps->push_back(std::move(installed_app1));
+  installed_apps->push_back(std::move(installed_app2));
+  installed_apps->push_back(std::move(installed_app3));
+  specifics_fetcher().SetWebApkSpecifics(std::move(installed_apps));
+
+  // not included in final state (older than installed version)
+  syncer::EntityData sync_data_1;
+  sync_pb::WebApkSpecifics* sync_specifics_1 =
+      sync_data_1.specifics.mutable_web_apk();
+  sync_specifics_1->set_manifest_id(manifest_id_1);
+  sync_specifics_1->set_name("app1_sync");
+  sync_specifics_1->set_last_used_time_windows_epoch_micros(
+      UnixTsSecToWindowsTsMsec(
+          1134072245.0));  // Thu Dec 08 2005 15:04:05 GMT-0500 - oldest app1
+                           // timestamp
+  std::unique_ptr<syncer::EntityChange> sync_change_1 =
+      syncer::EntityChange::CreateAdd(ManifestIdStrToAppId(manifest_id_1),
+                                      std::move(sync_data_1));
+
+  // included in final state (newer than installed version)
+  syncer::EntityData sync_data_2;
+  sync_pb::WebApkSpecifics* sync_specifics_2 =
+      sync_data_2.specifics.mutable_web_apk();
+  sync_specifics_2->set_manifest_id(manifest_id_2);
+  sync_specifics_2->set_name("app2_sync");
+  sync_specifics_2->set_last_used_time_windows_epoch_micros(
+      UnixTsSecToWindowsTsMsec(
+          1136145845.0));  // Sun Jan 01 2006 15:04:05 GMT-0500 - newest app2
+                           // timestamp
+  std::unique_ptr<syncer::EntityChange> sync_change_2 =
+      syncer::EntityChange::CreateAdd(ManifestIdStrToAppId(manifest_id_2),
+                                      std::move(sync_data_2));
+
+  // included in final state (no other version exists)
+  syncer::EntityData sync_data_4;
+  sync_pb::WebApkSpecifics* sync_specifics_4 =
+      sync_data_4.specifics.mutable_web_apk();
+  sync_specifics_4->set_manifest_id(manifest_id_4);
+  sync_specifics_4->set_name("app4_sync");
+  std::unique_ptr<syncer::EntityChange> sync_change_4 =
+      syncer::EntityChange::CreateAdd(ManifestIdStrToAppId(manifest_id_4),
+                                      std::move(sync_data_4));
+
+  // causes app5 to be not included in final state (no installed version, only
+  // registry)
+  std::unique_ptr<syncer::EntityChange> sync_change_5 =
+      syncer::EntityChange::CreateDelete(ManifestIdStrToAppId(manifest_id_5));
+
+  syncer::EntityChangeList sync_changes;
+  sync_changes.push_back(std::move(sync_change_1));
+  sync_changes.push_back(std::move(sync_change_2));
+  sync_changes.push_back(std::move(sync_change_4));
+  sync_changes.push_back(std::move(sync_change_5));
+
+  std::unique_ptr<syncer::MetadataChangeList> metadata_change_list =
+      syncer::ModelTypeStore::WriteBatch::CreateMetadataChangeList();
+  syncer::MetadataChangeList* metadata_ptr = metadata_change_list.get();
+
+  base::RunLoop run_loop;
+
+  int iteration = 0;
+  ON_CALL(processor(), Put(_, _, _))
+      .WillByDefault([&](const std::string& storage_key,
+                         std::unique_ptr<syncer::EntityData> entity_data,
+                         syncer::MetadataChangeList* metadata) {
+        EXPECT_EQ(metadata_ptr, metadata);
+
+        if (iteration == 0) {
+          EXPECT_EQ(ManifestIdStrToAppId(manifest_id_1), storage_key);
+          EXPECT_EQ(manifest_id_1,
+                    entity_data->specifics.web_apk().manifest_id());
+          EXPECT_EQ("app1_installed", entity_data->specifics.web_apk().name());
+        } else {
+          EXPECT_EQ(ManifestIdStrToAppId(manifest_id_6), storage_key);
+          EXPECT_EQ(manifest_id_6,
+                    entity_data->specifics.web_apk().manifest_id());
+          EXPECT_EQ("app6_registry", entity_data->specifics.web_apk().name());
+
+          run_loop.Quit();
+        }
+
+        EXPECT_NE(2, iteration);  // Put() has been called too many times
+        iteration++;
+      });
+
+  EXPECT_CALL(processor(), Delete(_, _)).Times(0);
+
+  absl::optional<syncer::ModelError> result = sync_bridge().MergeFullSyncData(
+      std::move(metadata_change_list), std::move(sync_changes));
+
+  run_loop.Run();
+
+  EXPECT_EQ(absl::nullopt, result);
+
+  const Registry& final_registry = sync_bridge().GetRegistryForTesting();
+  EXPECT_EQ(4u, final_registry.size());
+
+  EXPECT_EQ(manifest_id_1,
+            final_registry.at(ManifestIdStrToAppId(manifest_id_1))
+                ->sync_data()
+                .manifest_id());
+  EXPECT_EQ("app1_installed",
+            final_registry.at(ManifestIdStrToAppId(manifest_id_1))
+                ->sync_data()
+                .name());
+  EXPECT_TRUE(final_registry.at(ManifestIdStrToAppId(manifest_id_1))
+                  ->is_locally_installed());
+
+  EXPECT_EQ(manifest_id_2,
+            final_registry.at(ManifestIdStrToAppId(manifest_id_2))
+                ->sync_data()
+                .manifest_id());
+  EXPECT_EQ("app2_sync", final_registry.at(ManifestIdStrToAppId(manifest_id_2))
+                             ->sync_data()
+                             .name());
+  EXPECT_FALSE(final_registry.at(ManifestIdStrToAppId(manifest_id_2))
+                   ->is_locally_installed());
+
+  EXPECT_EQ(manifest_id_4,
+            final_registry.at(ManifestIdStrToAppId(manifest_id_4))
+                ->sync_data()
+                .manifest_id());
+  EXPECT_EQ("app4_sync", final_registry.at(ManifestIdStrToAppId(manifest_id_4))
+                             ->sync_data()
+                             .name());
+  EXPECT_FALSE(final_registry.at(ManifestIdStrToAppId(manifest_id_4))
+                   ->is_locally_installed());
+
+  EXPECT_EQ(manifest_id_6,
+            final_registry.at(ManifestIdStrToAppId(manifest_id_6))
+                ->sync_data()
+                .manifest_id());
+  EXPECT_EQ("app6_registry",
+            final_registry.at(ManifestIdStrToAppId(manifest_id_6))
+                ->sync_data()
+                .name());
+  EXPECT_FALSE(final_registry.at(ManifestIdStrToAppId(manifest_id_6))
+                   ->is_locally_installed());
+
+  const Registry db_registry = database_factory().ReadRegistry();
+  EXPECT_EQ(4u, db_registry.size());
+
+  EXPECT_EQ(manifest_id_1, db_registry.at(ManifestIdStrToAppId(manifest_id_1))
+                               ->sync_data()
+                               .manifest_id());
+  EXPECT_EQ(
+      "app1_installed",
+      db_registry.at(ManifestIdStrToAppId(manifest_id_1))->sync_data().name());
+  EXPECT_TRUE(db_registry.at(ManifestIdStrToAppId(manifest_id_1))
+                  ->is_locally_installed());
+
+  EXPECT_EQ(manifest_id_2, db_registry.at(ManifestIdStrToAppId(manifest_id_2))
+                               ->sync_data()
+                               .manifest_id());
+  EXPECT_EQ(
+      "app2_sync",
+      db_registry.at(ManifestIdStrToAppId(manifest_id_2))->sync_data().name());
+  EXPECT_FALSE(db_registry.at(ManifestIdStrToAppId(manifest_id_2))
+                   ->is_locally_installed());
+
+  EXPECT_EQ(manifest_id_4, db_registry.at(ManifestIdStrToAppId(manifest_id_4))
+                               ->sync_data()
+                               .manifest_id());
+  EXPECT_EQ(
+      "app4_sync",
+      db_registry.at(ManifestIdStrToAppId(manifest_id_4))->sync_data().name());
+  EXPECT_FALSE(db_registry.at(ManifestIdStrToAppId(manifest_id_4))
+                   ->is_locally_installed());
+
+  EXPECT_EQ(manifest_id_6, db_registry.at(ManifestIdStrToAppId(manifest_id_6))
+                               ->sync_data()
+                               .manifest_id());
+  EXPECT_EQ(
+      "app6_registry",
+      db_registry.at(ManifestIdStrToAppId(manifest_id_6))->sync_data().name());
+  EXPECT_FALSE(db_registry.at(ManifestIdStrToAppId(manifest_id_6))
+                   ->is_locally_installed());
+}
+
+TEST_F(WebApkSyncBridgeTest, MergeFullSyncData_NoChanges) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+
+  EXPECT_CALL(processor(), ModelReadyToSync(_)).Times(1);
+  EXPECT_CALL(processor(), Put(_, _, _)).Times(0);
+  EXPECT_CALL(processor(), Delete(_, _)).Times(0);
+
+  InitSyncBridge();
+
+  std::unique_ptr<syncer::MetadataChangeList> metadata_change_list =
+      syncer::ModelTypeStore::WriteBatch::CreateMetadataChangeList();
+  syncer::EntityChangeList sync_changes;
+  absl::optional<syncer::ModelError> result = sync_bridge().MergeFullSyncData(
+      std::move(metadata_change_list), std::move(sync_changes));
+
+  EXPECT_EQ(absl::nullopt, result);
+  EXPECT_EQ(0u, sync_bridge().GetRegistryForTesting().size());
+  EXPECT_EQ(0u, database_factory().ReadRegistry().size());
+}
+
 // Tests that the WebApkSyncBridge correctly reports data from the
 // WebApkDatabase.
 TEST_F(WebApkSyncBridgeTest, GetData) {
@@ -433,11 +746,11 @@
   Registry registry;
 
   std::unique_ptr<WebApkProto> synced_app1 =
-      CreateWebApkProto("https://example.com/app1/");
+      CreateWebApkProto("https://example.com/app1/", "name1");
   InsertAppIntoRegistry(&registry, std::move(synced_app1));
 
   std::unique_ptr<WebApkProto> synced_app2 =
-      CreateWebApkProto("https://example.com/app2/");
+      CreateWebApkProto("https://example.com/app2/", "name2");
   InsertAppIntoRegistry(&registry, std::move(synced_app2));
 
   database_factory().WriteRegistry(registry);
@@ -485,7 +798,8 @@
   base::test::SingleThreadTaskEnvironment task_environment;
   InitSyncBridge();
 
-  std::unique_ptr<WebApkProto> app = CreateWebApkProto("https://example.com/");
+  std::unique_ptr<WebApkProto> app =
+      CreateWebApkProto("https://example.com/", "name");
   std::unique_ptr<syncer::EntityData> entity_data = CreateSyncEntityData(*app);
 
   EXPECT_EQ("ocjeedicdelkkoefdcgeopgiagdjbcng",
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h
index 007017d..2168a79 100644
--- a/chrome/browser/app_controller_mac.h
+++ b/chrome/browser/app_controller_mac.h
@@ -151,8 +151,8 @@
 - (BOOL)windowHasBrowserTabs:(NSWindow*)window;
 
 // Testing API.
-- (void)setCloseWindowMenuItemForTesting:(NSMenuItem*)menuItem;
-- (void)setCloseTabMenuItemForTesting:(NSMenuItem*)menuItem;
+- (void)setCmdWMenuItemForTesting:(NSMenuItem*)menuItem;
+- (void)setShiftCmdWMenuItemForTesting:(NSMenuItem*)menuItem;
 - (void)setLastProfileForTesting:(Profile*)profile;
 
 @end
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 56477e06..54434bb 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -603,11 +603,9 @@
   std::vector<GURL> _startupUrls;
   BOOL _startupComplete;
 
-  // Outlets for the close tab/window menu items so that we can adjust the
-  // command-key equivalent depending on the kind of window and how many
-  // tabs it has.
-  NSMenuItem* __strong _closeTabMenuItemForTesting;
-  NSMenuItem* __strong _closeWindowMenuItemForTesting;
+  // Outlets for testing close tab/window menu items.
+  NSMenuItem* __strong _cmdWMenuItemForTesting;
+  NSMenuItem* __strong _shiftCmdWMenuItemForTesting;
 
   std::unique_ptr<PrefChangeRegistrar> _profilePrefRegistrar;
   PrefChangeRegistrar _localPrefRegistrar;
@@ -678,20 +676,36 @@
   return [[NSApp.mainMenu itemWithTag:IDC_FILE_MENU] submenu];
 }
 
-- (NSMenuItem*)closeTabMenuItem {
-  if (_closeTabMenuItemForTesting != nil) {
-    return _closeTabMenuItemForTesting;
+// Returns the Cmd-W menu item in the File menu.
+- (NSMenuItem*)cmdWMenuItem {
+  if (_cmdWMenuItemForTesting != nil) {
+    return _cmdWMenuItemForTesting;
   }
 
-  return [[self fileMenu] itemWithTag:IDC_CLOSE_TAB];
+  for (NSMenuItem* item in [self fileMenu].itemArray) {
+    if ([@"w" isEqualToString:item.keyEquivalent] &&
+        item.keyEquivalentModifierMask == NSEventModifierFlagCommand) {
+      return item;
+    }
+  }
+
+  return nil;
 }
 
-- (NSMenuItem*)closeWindowMenuItem {
-  if (_closeWindowMenuItemForTesting != nil) {
-    return _closeWindowMenuItemForTesting;
+// Returns the Shift-Cmd-W menu item in the File menu.
+- (NSMenuItem*)shiftCmdWMenuItem {
+  if (_shiftCmdWMenuItemForTesting != nil) {
+    return _shiftCmdWMenuItemForTesting;
   }
 
-  return [[self fileMenu] itemWithTag:IDC_CLOSE_WINDOW];
+  for (NSMenuItem* item in [self fileMenu].itemArray) {
+    if ([@"W" isEqualToString:item.keyEquivalent] &&
+        item.keyEquivalentModifierMask == NSEventModifierFlagCommand) {
+      return item;
+    }
+  }
+
+  return nil;
 }
 
 // This method is called very early in application startup (ie, before
@@ -718,8 +732,8 @@
              name:NSWorkspaceWillPowerOffNotification
            object:nil];
 
-  DCHECK([self closeTabMenuItem]);
-  DCHECK([self closeWindowMenuItem]);
+  DCHECK([self cmdWMenuItem]);
+  DCHECK([self shiftCmdWMenuItem]);
 
   // Set up the command updater for when there are no windows open
   [self initMenuState];
@@ -1576,7 +1590,7 @@
 
 - (void)initShareMenu {
   _shareMenuController = [[ShareMenuController alloc] init];
-  NSMenu* fileMenu = [NSApp.mainMenu itemWithTag:IDC_FILE_MENU].submenu;
+  NSMenu* fileMenu = [self fileMenu];
   NSString* shareMenuTitle = l10n_util::GetNSString(IDS_SHARE_MAC);
   NSMenuItem* shareMenuItem = [fileMenu itemWithTitle:shareMenuTitle];
   NSMenu* shareSubmenu = [[NSMenu alloc] initWithTitle:shareMenuTitle];
@@ -1929,22 +1943,58 @@
     }
   }
 
-  NSMenuItem* closeTabMenuItem = [self closeTabMenuItem];
-  NSMenuItem* closeWindowMenuItem = [self closeWindowMenuItem];
+  // If the browser window has tabs, assign Shift-Cmd-W to "Close Window"
+  // and Cmd-W to "Close Tab", otherwise hide the "Close Tab" item and
+  // assign Cmd-W to "Close Window".
+  //
+  // One way to shuffle these shortcuts is to simply find the "Close Window"
+  // and "Close Tab" menu items and change their key equivalents. For some
+  // reason, the AppKit won't let us do that. For example, if the "Close Tab"
+  // item has @"w" as its equivalent and we temporarily assign @"w" to
+  // "Close Window", we can never set @"w" as the key equivalent for the
+  // "Close Tab" item. It doesn't appear to be an issue with some other item
+  // having that same equivalent, the AppKit just won't take it. We get around
+  // this problem by leaving key equivalents alone and instead change the
+  // titles and actions of the menu items that own those equivalents.
+  NSMenuItem* cmdWMenuItem = [self cmdWMenuItem];
+  NSMenuItem* shiftCmdWMenuItem = [self shiftCmdWMenuItem];
 
-  // If the browser window has tabs, assign Cmd-Shift-W to "Close Window",
-  // otherwise leave it as the normal Cmd-W. Capitalization of the key
-  // equivalent affects whether the Shift modifier is used.
   if ([self windowHasBrowserTabs:targetWindow]) {
-    [closeTabMenuItem cr_setKeyEquivalent:@"w"
-                             modifierMask:NSEventModifierFlagCommand];
-    [closeWindowMenuItem cr_setKeyEquivalent:@"W"
-                                modifierMask:NSEventModifierFlagCommand];
+    // Assign Shift-Cmd-W to "Close Window".
+    shiftCmdWMenuItem.hidden = NO;
+    shiftCmdWMenuItem.title =
+        l10n_util::GetNSStringWithFixup(IDS_CLOSE_WINDOW_MAC);
+    shiftCmdWMenuItem.tag = IDC_CLOSE_WINDOW;
+
+    // Assign Cmd-W to "Close Tab".
+    cmdWMenuItem.title = l10n_util::GetNSStringWithFixup(IDS_CLOSE_TAB_MAC);
+    cmdWMenuItem.tag = IDC_CLOSE_TAB;
   } else {
-    [closeTabMenuItem cr_clearKeyEquivalent];
-    [closeWindowMenuItem cr_setKeyEquivalent:@"w"
-                                modifierMask:NSEventModifierFlagCommand];
+    // We don't need a Shift-Cmd-W command, so hide the menu item.
+    shiftCmdWMenuItem.hidden = YES;
+
+    // Assign Cmd-W to "Close Window".
+    cmdWMenuItem.title = l10n_util::GetNSStringWithFixup(IDS_CLOSE_WINDOW_MAC);
+    cmdWMenuItem.tag = IDC_CLOSE_WINDOW;
   }
+
+  // This menu item shuffling makes a "Close All" item appear. The AppKit wants
+  // to own the File menu, so this item's appearance is likely a result of
+  // magic code in the AppKit. However, we prefer to add and manage our own
+  // menu items (localization, for example). Also, this "Close All" menu item
+  // complicates the positioning of the "Close Window" and "Close Tab" items.
+  // Locate the "Close All" menu item and remove it.
+  NSMenu* fileMenu = [self fileMenu];
+  for (NSMenuItem* item in [[fileMenu itemArray] copy]) {
+    if (item.action == @selector(closeAll:)) {
+      [fileMenu removeItem:item];
+      break;
+    }
+  }
+
+  // Force no longer hidden items to appear, or newly hidden items to
+  // disappear.
+  [fileMenu update];
 }
 
 // This only has an effect on macOS 12+, and requests any state restoration
@@ -2085,12 +2135,12 @@
   });
 }
 
-- (void)setCloseWindowMenuItemForTesting:(NSMenuItem*)menuItem {
-  _closeWindowMenuItemForTesting = menuItem;
+- (void)setCmdWMenuItemForTesting:(NSMenuItem*)menuItem {
+  _cmdWMenuItemForTesting = menuItem;
 }
 
-- (void)setCloseTabMenuItemForTesting:(NSMenuItem*)menuItem {
-  _closeTabMenuItemForTesting = menuItem;
+- (void)setShiftCmdWMenuItemForTesting:(NSMenuItem*)menuItem {
+  _shiftCmdWMenuItemForTesting = menuItem;
 }
 
 - (void)setLastProfileForTesting:(Profile*)profile {
diff --git a/chrome/browser/app_controller_mac_unittest.mm b/chrome/browser/app_controller_mac_unittest.mm
index 5d541cf..0647037 100644
--- a/chrome/browser/app_controller_mac_unittest.mm
+++ b/chrome/browser/app_controller_mac_unittest.mm
@@ -19,11 +19,13 @@
 #include "chrome/browser/profiles/profile_metrics.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/platform_test.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace {
 
@@ -92,56 +94,60 @@
         std::make_unique<base::apple::ScopedObjCClassSwizzler>(
             [NSApp class], [AppControllerKeyEquivalentTestHelper class],
             @selector(targetForAction:));
-    app_controller_swizzler_ =
+    _app_controller_swizzler =
         std::make_unique<base::apple::ScopedObjCClassSwizzler>(
             [AppController class], [AppControllerKeyEquivalentTestHelper class],
             @selector(windowHasBrowserTabs:));
 
-    app_controller_ = AppController.sharedController;
+    _app_controller = AppController.sharedController;
 
-    close_window_menu_item_ = [[NSMenuItem alloc] initWithTitle:@""
-                                                         action:nullptr
-                                                  keyEquivalent:@""];
-    [app_controller_ setCloseWindowMenuItemForTesting:close_window_menu_item_];
+    _cmdw_menu_item = [[NSMenuItem alloc] initWithTitle:@""
+                                                 action:nullptr
+                                          keyEquivalent:@"w"];
+    [_app_controller setCmdWMenuItemForTesting:_cmdw_menu_item];
 
-    close_tab_menu_item_ = [[NSMenuItem alloc] initWithTitle:@""
-                                                      action:nullptr
-                                               keyEquivalent:@""];
-    [app_controller_ setCloseTabMenuItemForTesting:close_tab_menu_item_];
+    _shift_cmdw_menu_item = [[NSMenuItem alloc] initWithTitle:@""
+                                                       action:nullptr
+                                                keyEquivalent:@"W"];
+    [_app_controller setShiftCmdWMenuItemForTesting:_shift_cmdw_menu_item];
   }
 
   void CheckMenuItemsMatchBrowserWindow() {
     ASSERT_EQ([NSApp targetForAction:@selector(performClose:)],
               *TargetForAction());
 
-    [app_controller_ updateMenuItemKeyEquivalents];
+    [_app_controller updateMenuItemKeyEquivalents];
 
-    EXPECT_TRUE([[close_window_menu_item_ keyEquivalent] isEqualToString:@"W"]);
-    EXPECT_EQ([close_window_menu_item_ keyEquivalentModifierMask],
-              NSEventModifierFlagCommand);
-    EXPECT_TRUE([[close_tab_menu_item_ keyEquivalent] isEqualToString:@"w"]);
-    EXPECT_EQ([close_tab_menu_item_ keyEquivalentModifierMask],
-              NSEventModifierFlagCommand);
+    EXPECT_FALSE(_shift_cmdw_menu_item.hidden);
+    EXPECT_EQ(_shift_cmdw_menu_item.tag, IDC_CLOSE_WINDOW);
+    EXPECT_TRUE([_shift_cmdw_menu_item.title
+        isEqualToString:l10n_util::GetNSStringWithFixup(IDS_CLOSE_WINDOW_MAC)]);
+
+    EXPECT_FALSE(_cmdw_menu_item.hidden);
+    EXPECT_EQ(_cmdw_menu_item.tag, IDC_CLOSE_TAB);
+    EXPECT_TRUE([_cmdw_menu_item.title
+        isEqualToString:l10n_util::GetNSStringWithFixup(IDS_CLOSE_TAB_MAC)]);
   }
 
   void CheckMenuItemsMatchNonBrowserWindow() {
     ASSERT_EQ([NSApp targetForAction:@selector(performClose:)],
               *TargetForAction());
 
-    [app_controller_ updateMenuItemKeyEquivalents];
+    [_app_controller updateMenuItemKeyEquivalents];
 
-    EXPECT_TRUE([[close_window_menu_item_ keyEquivalent] isEqualToString:@"w"]);
-    EXPECT_EQ([close_window_menu_item_ keyEquivalentModifierMask],
-              NSEventModifierFlagCommand);
-    EXPECT_TRUE([[close_tab_menu_item_ keyEquivalent] isEqualToString:@""]);
-    EXPECT_EQ([close_tab_menu_item_ keyEquivalentModifierMask], 0UL);
+    EXPECT_TRUE(_shift_cmdw_menu_item.hidden);
+
+    EXPECT_FALSE(_cmdw_menu_item.hidden);
+    EXPECT_EQ(_cmdw_menu_item.tag, IDC_CLOSE_WINDOW);
+    EXPECT_TRUE([_cmdw_menu_item.title
+        isEqualToString:l10n_util::GetNSStringWithFixup(IDS_CLOSE_WINDOW_MAC)]);
   }
 
   void TearDown() override {
     PlatformTest::TearDown();
 
-    [app_controller_ setCloseWindowMenuItemForTesting:nil];
-    [app_controller_ setCloseTabMenuItemForTesting:nil];
+    [_app_controller setCmdWMenuItemForTesting:nil];
+    [_app_controller setShiftCmdWMenuItemForTesting:nil];
     *TargetForAction() = nil;
   }
 
@@ -149,10 +155,10 @@
   std::unique_ptr<base::apple::ScopedObjCClassSwizzler>
       nsapp_target_for_action_swizzler_;
   std::unique_ptr<base::apple::ScopedObjCClassSwizzler>
-      app_controller_swizzler_;
-  AppController* __strong app_controller_;
-  NSMenuItem* __strong close_window_menu_item_;
-  NSMenuItem* __strong close_tab_menu_item_;
+      _app_controller_swizzler;
+  AppController* __strong _app_controller;
+  NSMenuItem* __strong _cmdw_menu_item;
+  NSMenuItem* __strong _shift_cmdw_menu_item;
 };
 
 TEST_F(AppControllerTest, DockMenuProfileNotLoaded) {
diff --git a/chrome/browser/ash/arc/input_overlay/ui/nudge.cc b/chrome/browser/ash/arc/input_overlay/ui/nudge.cc
index bd530cc..20699706 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/nudge.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/nudge.cc
@@ -11,6 +11,8 @@
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ash/arc/input_overlay/display_overlay_controller.h"
 #include "chrome/browser/ash/arc/input_overlay/ui/nudge_view.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_provider.h"
@@ -42,6 +44,8 @@
 constexpr int kIconTextSpace = 12;
 
 class Dot : public views::View {
+  METADATA_HEADER(Dot, views::View)
+
  public:
   explicit Dot(ui::ColorId color_id) : color_id_(color_id) {}
 
@@ -67,6 +71,9 @@
   const ui::ColorId color_id_;
 };
 
+BEGIN_METADATA(Dot)
+END_METADATA
+
 }  // namespace
 
 Nudge::Nudge(DisplayOverlayController* controller,
@@ -141,4 +148,7 @@
   widget->StackAtTop();
 }
 
+BEGIN_METADATA(Nudge)
+END_METADATA
+
 }  // namespace arc::input_overlay
diff --git a/chrome/browser/ash/arc/input_overlay/ui/nudge.h b/chrome/browser/ash/arc/input_overlay/ui/nudge.h
index 01e1c6e..5dc5089b 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/nudge.h
+++ b/chrome/browser/ash/arc/input_overlay/ui/nudge.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/memory/raw_ptr.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget_observer.h"
 
@@ -31,6 +32,8 @@
 // ||icon|  |text| |
 // +---------------+
 class Nudge : public views::View, public views::WidgetObserver {
+  METADATA_HEADER(Nudge, views::View)
+
  public:
   Nudge(DisplayOverlayController* controller,
         views::View* anchor_view,
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
index 95cc6c11..5435423 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
@@ -1285,43 +1285,64 @@
     DriveSpecific, /* drive_specific.js */
     LoggedInUserFilesAppBrowserTest,
     ::testing::Values(
-        // Google One offer banner checks device state. Device state is NOT set
-        // to `policy::DeviceMode::DEVICE_MODE_CONSUMER` in
-        // `FilesAppBrowserTest`.
+        // Google One offer banner checks device state, locale, and country.
         TestCase("driveGoogleOneOfferBannerEnabled")
             .SetDeviceMode(DeviceMode::kConsumerOwned)
             .SetTestAccountType(TestAccountType::kNonManaged)
-            .EnableGoogleOneOfferFilesBanner(),
-        // Google One offer banner is disabled by default.
+            .SetLocale("en-US")
+            .SetCountry("us"),
+        // Disabled by the flag case.
         TestCase("driveGoogleOneOfferBannerDisabled")
             .SetDeviceMode(DeviceMode::kConsumerOwned)
-            .SetTestAccountType(TestAccountType::kNonManaged),
+            .SetTestAccountType(TestAccountType::kNonManaged)
+            .SetLocale("en-US")
+            .SetCountry("us")
+            .DisableGoogleOneOfferFilesBanner(),
+        // A country is not in supported countries set case.
+        TestCase("driveGoogleOneOfferBannerDisabled")
+            .SetDeviceMode(DeviceMode::kConsumerOwned)
+            .SetTestAccountType(TestAccountType::kNonManaged)
+            .SetLocale("en-US")
+            .SetCountry("jp"),
+        // A locale is not in a supported locales set case.
+        TestCase("driveGoogleOneOfferBannerDisabled")
+            .SetDeviceMode(DeviceMode::kConsumerOwned)
+            .SetTestAccountType(TestAccountType::kNonManaged)
+            .SetLocale("ja")
+            .SetCountry("us"),
         TestCase("driveGoogleOneOfferBannerDismiss")
             .SetDeviceMode(DeviceMode::kConsumerOwned)
             .SetTestAccountType(TestAccountType::kNonManaged)
-            .EnableGoogleOneOfferFilesBanner(),
+            .SetLocale("en-US")
+            .SetCountry("us"),
         TestCase("driveGoogleOneOfferBannerDismiss")
             .SetDeviceMode(DeviceMode::kConsumerOwned)
             .SetTestAccountType(TestAccountType::kNonManaged)
-            .EnableGoogleOneOfferFilesBanner()
+            .SetLocale("en-US")
+            .SetCountry("us")
             .EnableCrosComponents(),
         TestCase("driveGoogleOneOfferBannerDisabled")
-            .EnableGoogleOneOfferFilesBanner()
+            .SetLocale("en-US")
+            .SetCountry("us")
             .SetDeviceMode(DeviceMode::kConsumerOwned)
             .SetTestAccountType(TestAccountType::kEnterprise),
         TestCase("driveGoogleOneOfferBannerDisabled")
-            .EnableGoogleOneOfferFilesBanner()
+            .SetLocale("en-US")
+            .SetCountry("us")
             .SetDeviceMode(DeviceMode::kConsumerOwned)
             .SetTestAccountType(TestAccountType::kChild),
         // Google One offer is for a device. The banner will not
         // be shown for an enrolled device.
         TestCase("driveGoogleOneOfferBannerDisabled")
-            .EnableGoogleOneOfferFilesBanner()
+            .SetLocale("en-US")
+            .SetCountry("us")
             .SetDeviceMode(DeviceMode::kEnrolled)
             .SetTestAccountType(TestAccountType::kNonManaged),
         // We do not show a banner if a profile is not an owner profile.
         TestCase("driveGoogleOneOfferBannerDisabled")
             .EnableGoogleOneOfferFilesBanner()
+            .SetLocale("en-US")
+            .SetCountry("us")
             .SetDeviceMode(kConsumerOwned)
             .SetTestAccountType(kNonManagedNonOwner),
         TestCase("driveBulkPinningBannerEnabled")
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
index cfc3f4f..cc0c60a 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -137,6 +137,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/user_manager/user_manager.h"
+#include "components/variations/service/variations_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/storage_partition.h"
@@ -199,6 +200,39 @@
 namespace file_manager {
 namespace {
 
+// Waits `ash::locale_util::SwitchLanguage`.
+class SwitchLanguageWaiter {
+ public:
+  ash::locale_util::SwitchLanguageCallback CreateCallback() {
+    CHECK(!callback_created_)
+        << "Only a single callback can be created for a waiter.";
+
+    callback_created_ = true;
+    return base::BindOnce(&SwitchLanguageWaiter::OnLanguageSwitch,
+                          weak_ptr_factory_.GetWeakPtr());
+  }
+
+  void Wait() {
+    CHECK(!run_loop_.running()) << "This waiter is already waiting.";
+    run_loop_.Run();
+  }
+
+ private:
+  void OnLanguageSwitch(const ash::locale_util::LanguageSwitchResult& result) {
+    CHECK(result.success);
+    CHECK_EQ(result.requested_locale, result.loaded_locale)
+        << "Requested " << result.requested_locale << " but "
+        << result.loaded_locale << " is loaded.";
+
+    run_loop_.Quit();
+  }
+
+  bool callback_created_ = false;
+  base::RunLoop run_loop_;
+
+  base::WeakPtrFactory<SwitchLanguageWaiter> weak_ptr_factory_{this};
+};
+
 // Specialization of the navigation observer that stores web content every time
 // the OnDidFinishNavigation is called.
 class WebContentCapturingObserver : public content::TestNavigationObserver {
@@ -2434,6 +2468,20 @@
   CHECK(profile());
   CHECK_EQ(!!browser(), options.browser);
 
+  if (!options.locale.empty()) {
+    SwitchLanguageWaiter waiter;
+    ash::locale_util::SwitchLanguage(
+        options.locale, /*enable_locale_keyboard_layouts=*/true,
+        /*login_layouts_only=*/false, waiter.CreateCallback(), profile());
+    waiter.Wait();
+  }
+
+  if (!options.country.empty()) {
+    CHECK(
+        g_browser_process->variations_service()->OverrideStoredPermanentCountry(
+            options.country));
+  }
+
   if (!options.mount_volumes) {
     VolumeManager::Get(profile())->RemoveDownloadsDirectoryForTesting();
   } else {
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.h b/chrome/browser/ash/file_manager/file_manager_browsertest_base.h
index 8104526..61939c8 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.h
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.h
@@ -85,6 +85,12 @@
     // Should test run in Guest or Incognito mode?
     GuestMode guest_mode = NOT_IN_GUEST_MODE;
 
+    // Locale used for this test to run.
+    std::string locale;
+
+    // A stored permanent country in `VariationsService` for this test to run.
+    std::string country;
+
     // Account type used to log-in for a test session. This option is valid only
     // for `LoggedInUserFilesAppBrowserTest`. This won't work with `guest_mode`
     // option.
@@ -184,8 +190,9 @@
     // Whether test should run with the fsps-in-recents flag.
     bool enable_fsps_in_recents = false;
 
-    // Whether tests should enable Google One offer Files banner.
-    bool enable_google_one_offer_files_banner = false;
+    // Whether tests should enable Google One offer Files banner. This flag is
+    // enabled by default.
+    bool enable_google_one_offer_files_banner = true;
 
     // Whether tests should enable the Google Drive bulk pinning feature.
     bool enable_drive_bulk_pinning = false;
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_utils.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_utils.cc
index a89990a..a10952d 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_utils.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_utils.cc
@@ -26,6 +26,16 @@
   return *this;
 }
 
+TestCase& TestCase::SetLocale(const std::string& locale) {
+  options.locale = locale;
+  return *this;
+}
+
+TestCase& TestCase::SetCountry(const std::string& country) {
+  options.country = country;
+  return *this;
+}
+
 TestCase& TestCase::EnableGenericDocumentsProvider() {
   options.arc = true;
   options.generic_documents_provider = true;
@@ -174,6 +184,11 @@
   return *this;
 }
 
+TestCase& TestCase::DisableGoogleOneOfferFilesBanner() {
+  options.enable_google_one_offer_files_banner = false;
+  return *this;
+}
+
 TestCase& TestCase::FeatureIds(const std::vector<std::string>& ids) {
   options.feature_ids = ids;
   return *this;
@@ -219,6 +234,17 @@
     full_name += "_TabletMode";
   }
 
+  if (!options.locale.empty()) {
+    // You cannot use `-` in a test case name.
+    std::string locale_for_name;
+    base::ReplaceChars(options.locale, "-", "_", &locale_for_name);
+    full_name += "_" + locale_for_name;
+  }
+
+  if (!options.country.empty()) {
+    full_name += "_" + options.country;
+  }
+
   if (options.offline) {
     full_name += "_Offline";
   }
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_utils.h b/chrome/browser/ash/file_manager/file_manager_browsertest_utils.h
index 48b7d62..388cf84 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_utils.h
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_utils.h
@@ -32,6 +32,10 @@
 
   TestCase& TabletMode();
 
+  TestCase& SetLocale(const std::string& locale);
+
+  TestCase& SetCountry(const std::string& country);
+
   TestCase& EnableGenericDocumentsProvider();
 
   TestCase& DisableGenericDocumentsProvider();
@@ -98,6 +102,8 @@
 
   TestCase& EnableGoogleOneOfferFilesBanner();
 
+  TestCase& DisableGoogleOneOfferFilesBanner();
+
   TestCase& FeatureIds(const std::vector<std::string>& ids);
 
   TestCase& EnableBulkPinning();
diff --git a/chrome/browser/ash/file_manager/file_manager_string_util.cc b/chrome/browser/ash/file_manager/file_manager_string_util.cc
index 13bde33..d7abbb6 100644
--- a/chrome/browser/ash/file_manager/file_manager_string_util.cc
+++ b/chrome/browser/ash/file_manager/file_manager_string_util.cc
@@ -11,6 +11,7 @@
 #include "ash/constants/ash_features.h"
 #include "ash/system/time/calendar_utils.h"
 #include "ash/system/time/date_helper.h"
+#include "base/containers/fixed_flat_set.h"
 #include "base/feature_list.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -38,6 +39,7 @@
 #include "chromeos/constants/chromeos_features.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/user_manager/user_manager.h"
+#include "components/variations/service/variations_service.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/webui/web_ui_util.h"
 #include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
@@ -86,6 +88,14 @@
 // Location of the help page about no-action-available files.
 const int kNoActionForFileHelpNumber = 1700055;
 
+// Supported locales of Google One offer banner.
+constexpr auto kGoogleOneOfferBannerSupportedLocales =
+    base::MakeFixedFlatSet<std::string>({"en-US", "en-GB", "en-AU", "en-CA"});
+
+// Supported countries of Google One offer banner.
+constexpr auto kGoogleOneOfferBannerSupportedCountries =
+    base::MakeFixedFlatSet<std::string>({"us", "gb", "au", "ca"});
+
 #define SET_STRING(id, idr) dict->Set(id, l10n_util::GetStringUTF16(idr))
 
 #define SET_STRING_PLURAL(id, idr, n) \
@@ -1209,6 +1219,17 @@
     return false;
   }
 
+  if (!kGoogleOneOfferBannerSupportedLocales.contains(
+          g_browser_process->GetApplicationLocale())) {
+    return false;
+  }
+
+  if (!kGoogleOneOfferBannerSupportedCountries.contains(
+          g_browser_process->variations_service()
+              ->GetStoredPermanentCountry())) {
+    return false;
+  }
+
   return base::FeatureList::IsEnabled(
       ash::features::kGoogleOneOfferFilesBanner);
 }
diff --git a/chrome/browser/ash/input_method/autocorrect_manager.cc b/chrome/browser/ash/input_method/autocorrect_manager.cc
index 9fad548..a999dd23 100644
--- a/chrome/browser/ash/input_method/autocorrect_manager.cc
+++ b/chrome/browser/ash/input_method/autocorrect_manager.cc
@@ -10,6 +10,7 @@
 #include "base/i18n/case_conversion.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/strings/levenshtein_distance.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -258,45 +259,6 @@
   return AutocorrectRejectionBreakdown::kRejectedSelectedInvalidRange;
 }
 
-// Returns the Levenshtein distance between |str1| and |str2|.
-// Which is the minimum number of single-character edits (i.e. insertions,
-// deletions or substitutions) required to change one word into the other.
-// https://en.wikipedia.org/wiki/Levenshtein_distance
-int GetLevenshteinDistance(const std::u16string& str1,
-                           const std::u16string& str2) {
-  if (str1.size() > str2.size()) {
-    return GetLevenshteinDistance(str2, str1);
-  }
-  if (str1.size() + static_cast<size_t>(kMaxEditDistance) < str2.size()) {
-    return kMaxEditDistance;
-  }
-
-  std::vector<int> row(str1.size() + 1);
-  for (size_t i = 0; i < row.size(); ++i) {
-    row[i] = static_cast<int>(i);
-  }
-
-  for (size_t i = 0; i < str2.size(); ++i) {
-    ++row[0];
-    int previous = static_cast<int>(i);
-    bool under_cutoff = false;
-    for (size_t j = 0; j < str1.size(); ++j) {
-      int old_row = row[j + 1];
-      int cost = str2[i] == str1[j] ? 0 : 1;
-      row[j + 1] = std::min(std::min(row[j], row[j + 1]) + 1, previous + cost);
-      if (row[j + 1] < kMaxEditDistance) {
-        under_cutoff = true;
-      }
-      previous = old_row;
-    }
-
-    if (!under_cutoff) {
-      return kMaxEditDistance;
-    }
-  }
-  return row[str1.size()];
-}
-
 void MeasureAndLogAssistiveAutocorrectEditDistance(
     const std::u16string& original_text,
     const std::u16string& suggested_text,
@@ -304,8 +266,8 @@
     const bool virtual_keyboard_visible) {
   const int text_length =
       std::min(static_cast<int>(original_text.length()), kMaxEditDistance);
-  const int distance = std::min(
-      GetLevenshteinDistance(original_text, suggested_text), kMaxEditDistance);
+  const int distance = base::LevenshteinDistance(original_text, suggested_text,
+                                                 kMaxEditDistance - 1);
   if (text_length <= 0 || distance <= 0) {
     return;
   }
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.cc b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.cc
index f01a044..3ce33f51 100644
--- a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.cc
+++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.cc
@@ -6,6 +6,7 @@
 
 #include <array>
 
+#include "base/base64url.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/json/json_writer.h"
@@ -233,7 +234,12 @@
       quick_start_message->get_fido_assertion_response();
   FidoAssertionInfo assertion_info;
   assertion_info.email = fido_response->email;
-  assertion_info.credential_id = fido_response->credential_id;
+
+  // The credential_id response is sent to us as raw bytes, Base64 encode them.
+  base::Base64UrlEncode(fido_response->credential_id,
+                        base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+                        &assertion_info.credential_id);
+
   assertion_info.authenticator_data = fido_response->auth_data;
   assertion_info.signature = fido_response->signature;
 
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc
index f429fc7..ec5ff08a 100644
--- a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc
+++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc
@@ -5,6 +5,7 @@
 #include "connection.h"
 
 #include "base/base64.h"
+#include "base/base64url.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/json/json_reader.h"
@@ -482,8 +483,13 @@
 
   // Emulate a GetAssertion response.
   std::vector<uint8_t> credential_id = {0x01, 0x02, 0x03};
-  std::string expected_credential_id(credential_id.begin(),
-                                     credential_id.end());
+
+  // The credential ID should be Base64Url encoded with padding.
+  std::string expected_credential_id;
+  base::Base64UrlEncode(credential_id,
+                        base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+                        &expected_credential_id);
+
   std::vector<uint8_t> auth_data = {0x02, 0x03, 0x04};
   std::vector<uint8_t> signature = {0x03, 0x04, 0x05};
   std::string email = "testcase@google.com";
@@ -496,7 +502,8 @@
   fake_quick_start_decoder_->SetAssertionResponse(
       mojom::FidoAssertionResponse::New(
           /*email=*/email,
-          /*credential_id=*/expected_credential_id,
+          /*credential_id=*/
+          std::string(credential_id.begin(), credential_id.end()),
           /*auth_data=*/auth_data,
           /*signature=*/signature));
   fake_nearby_connection_->AppendReadableData(data);
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/fido_assertion_info.h b/chrome/browser/ash/login/oobe_quick_start/connectivity/fido_assertion_info.h
index c720df9..c30e2b83 100644
--- a/chrome/browser/ash/login/oobe_quick_start/connectivity/fido_assertion_info.h
+++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/fido_assertion_info.h
@@ -22,7 +22,7 @@
   // User's email.
   std::string email;
 
-  // Base64 url encoded key identifier of the key used.
+  // Key identifier of the key used. (encoded as Base64 URL with padding)
   std::string credential_id;
 
   // The authenticator data returned by the authenticator.
diff --git a/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.cc b/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.cc
index 066c1e5..c3183c2 100644
--- a/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.cc
+++ b/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.cc
@@ -75,8 +75,10 @@
   }
 
   void ReconnectToSession(remoting::SessionId session_id,
+                          const std::string& oauth_access_token,
                           StartSessionCallback callback) override {
-    return GetSupportHost().ReconnectToSession(session_id, std::move(callback));
+    return GetSupportHost().ReconnectToSession(session_id, oauth_access_token,
+                                               std::move(callback));
   }
 
  private:
@@ -286,7 +288,7 @@
       CRD_LOG(INFO) << "Attempting to resume reconnectable session";
 
       remoting_service_->ReconnectToSession(
-          id.value(),
+          id.value(), "TODO(joedow): Provide real oauth access token",
           base::BindOnce(&CrdHostSession::OnStartSupportSessionResponse,
                          weak_factory_.GetWeakPtr()));
     } else {
diff --git a/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.h b/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.h
index 2f89e9d..584656dd 100644
--- a/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.h
+++ b/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller.h
@@ -52,6 +52,7 @@
     // Starts a new remote support session, which will resume the reconnectable
     // session with the given `session_id`.
     virtual void ReconnectToSession(remoting::SessionId session_id,
+                                    const std::string& oauth_access_token,
                                     StartSessionCallback callback) = 0;
   };
 
diff --git a/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller_unittest.cc b/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller_unittest.cc
index 03e40c5..1b200bd 100644
--- a/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller_unittest.cc
+++ b/chrome/browser/ash/policy/remote_commands/crd_admin_session_controller_unittest.cc
@@ -113,7 +113,7 @@
   MOCK_METHOD(void, GetReconnectableSessionId, (SessionIdCallback));
   MOCK_METHOD(void,
               ReconnectToSession,
-              (remoting::SessionId, StartSessionCallback));
+              (remoting::SessionId, const std::string&, StartSessionCallback));
 };
 
 // Wrapper around the `RemotingServiceMock`, solving the lifetime issue
@@ -140,8 +140,10 @@
   }
 
   void ReconnectToSession(remoting::SessionId session_id,
+                          const std::string& oauth_access_token,
                           StartSessionCallback callback) override {
-    implementation_->ReconnectToSession(session_id, std::move(callback));
+    implementation_->ReconnectToSession(session_id, oauth_access_token,
+                                        std::move(callback));
   }
 
  private:
@@ -677,8 +679,10 @@
       .WillOnce([&](auto callback) { std::move(callback).Run(kSessionId); });
 
   // And next we should use this session id to reconnect.
-  EXPECT_CALL(remoting_service(), ReconnectToSession(kSessionId, testing::_))
-      .WillOnce([&](remoting::SessionId, StartSupportSessionCallback callback) {
+  EXPECT_CALL(remoting_service(),
+              ReconnectToSession(kSessionId, testing::_, testing::_))
+      .WillOnce([&](remoting::SessionId, const std::string&,
+                    StartSupportSessionCallback callback) {
         std::move(callback).Run(
             StartSupportSessionResponse::NewObserver(BindObserver()));
       });
diff --git a/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.cc b/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.cc
index 899db4f..0325157 100644
--- a/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.cc
+++ b/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/scalable_iph/scalable_iph_factory.h"
 #include "chrome/browser/scalable_iph/scalable_iph_factory_impl.h"
+#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chromeos/ash/components/scalable_iph/scalable_iph.h"
 #include "chromeos/ash/components/scalable_iph/scalable_iph_constants.h"
@@ -97,6 +98,21 @@
     return;
   }
 
+  if (enable_multi_user_) {
+    // Add a secondary user.
+    LoginManagerMixin* login_manager_mixin = GetLoginManagerMixin();
+    CHECK(login_manager_mixin);
+    login_manager_mixin->AppendRegularUsers(1);
+    CHECK_EQ(login_manager_mixin->users().size(), 2ul);
+
+    // By default, `MultiUserWindowManager` is created with multi profile off.
+    // Re-create for multi profile tests. This has to be done after
+    // `SetUpOnMainThread` of a base class as the original multi-profile-off
+    // `MultiUserWindowManager` is created there.
+    MultiUserWindowManagerHelper::CreateInstanceForTest(
+        GetPrimaryUserContext().GetAccountId());
+  }
+
   // If we don't intend to enforce ScalableIph setup (i.e. the user profile
   // doesn't qualify for ScalableIph), do not set up mocks as ScalableIph
   // should not be available for the profile.
@@ -185,6 +201,8 @@
   std::vector<base::test::FeatureRefAndParams> enabled_features({test_config});
   std::vector<base::test::FeatureRef> disabled_features;
 
+  AppendTestSpecificFeatures(enabled_features, disabled_features);
+
   if (enable_scalable_iph_) {
     enabled_features.push_back(
         base::test::FeatureRefAndParams(ash::features::kScalableIph, {}));
@@ -341,6 +359,17 @@
   scalable_iph->RecordEvent(event);
 }
 
+ash::UserContext ScalableIphBrowserTestBase::GetPrimaryUserContext() {
+  return ash::LoginManagerMixin::CreateDefaultUserContext(
+      GetLoginManagerMixin()->users()[0]);
+}
+
+ash::UserContext ScalableIphBrowserTestBase::GetSecondaryUserContext() {
+  CHECK(enable_multi_user_);
+  return ash::LoginManagerMixin::CreateDefaultUserContext(
+      GetLoginManagerMixin()->users()[1]);
+}
+
 void ScalableIphBrowserTestBase::ShutdownScalableIph() {
   scalable_iph::ScalableIph* scalable_iph =
       ScalableIphFactory::GetForBrowserContext(browser()->profile());
diff --git a/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.h b/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.h
index 75c9b33..3badb63 100644
--- a/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.h
+++ b/chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.h
@@ -64,6 +64,9 @@
   // TODO(b/297565024): Abstract this as we initialize more than just IPH
   //                    configs in this method.
   virtual void InitializeScopedFeatureList();
+  virtual void AppendTestSpecificFeatures(
+      std::vector<base::test::FeatureRefAndParams>& enabled_features,
+      std::vector<base::test::FeatureRef>& disabled_features) {}
   void AppendVersionNumber(base::FieldTrialParams& params,
                            const base::Feature& feature,
                            const std::string& version_number);
@@ -101,6 +104,13 @@
   void TriggerConditionsCheckWithAFakeEvent(
       scalable_iph::ScalableIph::Event event);
 
+  // Returns a user context of primary user.
+  ash::UserContext GetPrimaryUserContext();
+
+  // Returns a user context of secondary user. Note that `enable_multi_user_`
+  // has to be true to use this method.
+  ash::UserContext GetSecondaryUserContext();
+
   // A sub-class might override this from `InitializeScopedFeatureList`.
   base::test::ScopedFeatureList scoped_feature_list_;
 
@@ -118,6 +128,9 @@
   // If `enable_scalable_iph_` is set to false, this should also be false.
   bool setup_scalable_iph_ = true;
 
+  // Set true in the constructor to enable multi user in this test case.
+  bool enable_multi_user_ = false;
+
  private:
   static void SetTestingFactories(bool enable_mock_tracker,
                                   content::BrowserContext* browser_context);
diff --git a/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc b/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc
index fc3be66..f813633a 100644
--- a/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc
+++ b/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc
@@ -2,15 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "ash/constants/app_types.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
+#include "ash/game_dashboard/game_dashboard_controller.h"
 #include "ash/public/cpp/app_list/app_list_controller.h"
 #include "ash/public/cpp/app_list/app_list_metrics.h"
+#include "ash/public/cpp/multi_user_window_manager.h"
 #include "ash/public/cpp/shelf_model.h"
 #include "ash/public/cpp/system/anchored_nudge_manager.h"
+#include "ash/public/cpp/window_properties.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shell.h"
 #include "ash/system/toast/anchored_nudge_manager_impl.h"
+#include "ash/test/test_widget_builder.h"
 #include "base/feature_list.h"
 #include "base/scoped_observation.h"
 #include "base/strings/pattern.h"
@@ -20,6 +25,7 @@
 #include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ash/login/lock/screen_locker_tester.h"
 #include "chrome/browser/ash/login/test/device_state_mixin.h"
+#include "chrome/browser/ash/login/ui/user_adding_screen.h"
 #include "chrome/browser/ash/login/wizard_controller.h"
 #include "chrome/browser/ash/printing/cups_print_job.h"
 #include "chrome/browser/ash/printing/cups_print_job_manager.h"
@@ -31,6 +37,7 @@
 #include "chrome/browser/ash/scalable_iph/scalable_iph_delegate_impl.h"
 #include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
 #include "chrome/browser/scalable_iph/scalable_iph_factory.h"
+#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h"
 #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
@@ -51,9 +58,12 @@
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/test/browser_test.h"
+#include "extensions/common/constants.h"
 #include "net/http/http_response_headers.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "ui/aura/client/aura_constants.h"
 #include "ui/aura/test/event_generator_delegate_aura.h"
+#include "ui/aura/window.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/message_center_observer.h"
@@ -72,6 +82,7 @@
 constexpr char kTestLogMessagePattern[] = "*test-log-message*";
 constexpr char kScalableIphDebugLogTextUrl[] =
     "chrome-untrusted://scalable-iph-debug/log.txt";
+constexpr char16_t kTestGameWindowTitle[] = u"ScalableIphTestGameWindow";
 
 BASE_FEATURE(kScalableIphTestTwo,
              "ScalableIphTestTwo",
@@ -103,6 +114,16 @@
   chromeos::FakePowerManagerClient::Get()->SendSuspendDone();
 }
 
+std::unique_ptr<aura::Window> CreateAuraWindow(std::u16string window_title) {
+  ash::TestWidgetBuilder builder;
+  builder.SetWindowTitle(window_title);
+  builder.SetTestWidgetDelegate();
+  builder.SetContext(ash::Shell::GetPrimaryRootWindow());
+  builder.SetBounds(gfx::Rect(0, 0, 600, 400));
+  views::Widget* widget = builder.BuildOwnedByNativeWidget();
+  return std::unique_ptr<aura::Window>(widget->GetNativeWindow());
+}
+
 class IsOnlineValueWaiter {
  public:
   IsOnlineValueWaiter(scalable_iph::ScalableIphDelegate* scalable_iph_delegate,
@@ -194,6 +215,28 @@
   int job_id_;
 };
 
+class ScalableIphBrowserTestGame : public ScalableIphBrowserTest {
+ public:
+  void AppendTestSpecificFeatures(
+      std::vector<base::test::FeatureRefAndParams>& enabled_features,
+      std::vector<base::test::FeatureRef>& disabled_features) override {
+    enabled_features.push_back(
+        base::test::FeatureRefAndParams(ash::features::kGameDashboard, {}));
+  }
+
+  void SetUpOnMainThread() override {
+    ScalableIphBrowserTest::SetUpOnMainThread();
+
+    CHECK(ash::GameDashboardController::Get())
+        << "Game dashboard has to be enabled for this test.";
+  }
+};
+
+class ScalableIphBrowserTestGameMultiUser : public ScalableIphBrowserTestGame {
+ public:
+  ScalableIphBrowserTestGameMultiUser() { enable_multi_user_ = true; }
+};
+
 class ScalableIphBrowserTestDebugOff : public ScalableIphBrowserTest {
  public:
   ScalableIphBrowserTestDebugOff() { enable_scalable_iph_debug_ = false; }
@@ -838,6 +881,66 @@
   print_job_manager_waiter.Wait();
 }
 
+IN_PROC_BROWSER_TEST_F(ScalableIphBrowserTestGame, GameWindowOpened) {
+  EXPECT_CALL(*mock_tracker(),
+              NotifyEvent(scalable_iph::kEventNameGameWindowOpened));
+
+  std::unique_ptr<aura::Window> window = CreateAuraWindow(kTestGameWindowTitle);
+  window->SetProperty(ash::kAppIDKey,
+                      std::string(extension_misc::kGeForceNowAppId));
+}
+
+IN_PROC_BROWSER_TEST_F(ScalableIphBrowserTestGameMultiUser,
+                       NoGameWindowOpenedForSecondaryUser) {
+  EXPECT_CALL(*mock_tracker(),
+              NotifyEvent(scalable_iph::kEventNameGameWindowOpened))
+      .Times(0);
+
+  // Login with secondary user and open a game window with the user.
+  ash::UserAddingScreen::Get()->Start();
+  CHECK(GetLoginManagerMixin()->LoginAndWaitForActiveSession(
+      GetSecondaryUserContext()));
+
+  std::unique_ptr<aura::Window> window = CreateAuraWindow(kTestGameWindowTitle);
+  window->SetProperty(ash::kAppIDKey,
+                      std::string(extension_misc::kGeForceNowAppId));
+  ash::MultiUserWindowManager* multi_user_window_manager =
+      MultiUserWindowManagerHelper::GetWindowManager();
+  CHECK(multi_user_window_manager);
+  multi_user_window_manager->SetWindowOwner(
+      window.get(), GetSecondaryUserContext().GetAccountId());
+}
+
+IN_PROC_BROWSER_TEST_F(ScalableIphBrowserTestGameMultiUser,
+                       NoGameWindowOpenedTeleport) {
+  EXPECT_CALL(*mock_tracker(),
+              NotifyEvent(scalable_iph::kEventNameGameWindowOpened))
+      .Times(0);
+
+  // Login with secondary user and open a game window with the user.
+  ash::UserAddingScreen::Get()->Start();
+  CHECK(GetLoginManagerMixin()->LoginAndWaitForActiveSession(
+      GetSecondaryUserContext()));
+
+  std::unique_ptr<aura::Window> window = CreateAuraWindow(kTestGameWindowTitle);
+  ash::MultiUserWindowManager* multi_user_window_manager =
+      MultiUserWindowManagerHelper::GetWindowManager();
+  CHECK(multi_user_window_manager);
+  multi_user_window_manager->SetWindowOwner(
+      window.get(), GetSecondaryUserContext().GetAccountId());
+
+  // Teleport the window before app id is set.
+  multi_user_window_manager->ShowWindowForUser(
+      window.get(), GetPrimaryUserContext().GetAccountId());
+
+  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
+  CHECK(user_manager);
+  CHECK_EQ(user_manager->GetActiveUser()->GetAccountId(),
+           GetPrimaryUserContext().GetAccountId());
+
+  window->SetProperty(ash::kAppIDKey,
+                      std::string(extension_misc::kGeForceNowAppId));
+}
 // Logging feature is on by default in `ScalableIphBrowserTest`.
 IN_PROC_BROWSER_TEST_F(ScalableIphBrowserTest, Log) {
   constexpr char kTestFileNamePattern[] = "*scalable_iph_browsertest.cc*";
diff --git a/chrome/browser/ash/scanning/lorgnette_scanner_manager.cc b/chrome/browser/ash/scanning/lorgnette_scanner_manager.cc
index 2238a0ad..e37295a 100644
--- a/chrome/browser/ash/scanning/lorgnette_scanner_manager.cc
+++ b/chrome/browser/ash/scanning/lorgnette_scanner_manager.cc
@@ -532,6 +532,7 @@
                               const lorgnette::ListScannersResponse& response,
                               GetScannerInfoListCallback callback) {
     lorgnette::ListScannersResponse combined_results;
+    combined_results.set_result(response.result());
 
     for (const auto& scanner : response.scanners()) {
       if (ShouldIncludeScanner(scanner, local_only, secure_only)) {
diff --git a/chrome/browser/ash/scanning/lorgnette_scanner_manager_unittest.cc b/chrome/browser/ash/scanning/lorgnette_scanner_manager_unittest.cc
index 2f79148d..c4dd482 100644
--- a/chrome/browser/ash/scanning/lorgnette_scanner_manager_unittest.cc
+++ b/chrome/browser/ash/scanning/lorgnette_scanner_manager_unittest.cc
@@ -84,6 +84,7 @@
     const std::string& model = "MX3100") {
   lorgnette::ScannerInfo scanner = CreateLorgnetteScanner(name, model);
   lorgnette::ListScannersResponse response;
+  response.set_result(lorgnette::OPERATION_RESULT_SUCCESS);
   *response.add_scanners() = std::move(scanner);
   return response;
 }
@@ -688,6 +689,8 @@
                      SecureScannerFilter::kIncludeUnsecureScanners);
   WaitForResult();
   ASSERT_TRUE(list_scanners_response());
+  EXPECT_EQ(list_scanners_response()->result(),
+            lorgnette::OPERATION_RESULT_SUCCESS);
   ASSERT_EQ(list_scanners_response().value().scanners_size(), 1);
   EXPECT_FALSE(
       list_scanners_response().value().scanners(0).device_uuid().empty());
@@ -799,6 +802,8 @@
                      SecureScannerFilter::kIncludeUnsecureScanners);
   WaitForResult();
   ASSERT_TRUE(list_scanners_response());
+  EXPECT_EQ(list_scanners_response()->result(),
+            lorgnette::OPERATION_RESULT_SUCCESS);
   ASSERT_EQ(list_scanners_response().value().scanners_size(), 2);
   EXPECT_FALSE(
       list_scanners_response().value().scanners(0).device_uuid().empty());
@@ -815,6 +820,7 @@
   info.set_connection_type(lorgnette::CONNECTION_USB);
   info.set_secure(false);
   *response.add_scanners() = std::move(info);
+  response.set_result(lorgnette::OPERATION_RESULT_SUCCESS);
 
   // This scanner should get filtered out because it's a network scanner.
   GetLorgnetteManagerClient()->SetListScannersResponse(response);
@@ -825,6 +831,8 @@
                      SecureScannerFilter::kIncludeUnsecureScanners);
   WaitForResult();
   ASSERT_TRUE(list_scanners_response());
+  EXPECT_EQ(list_scanners_response()->result(),
+            lorgnette::OPERATION_RESULT_SUCCESS);
   ASSERT_EQ(list_scanners_response().value().scanners_size(), 1);
   EXPECT_EQ(list_scanners_response().value().scanners(0).name(),
             kLorgnetteUsbDeviceName);
@@ -838,6 +846,7 @@
   info.set_connection_type(lorgnette::CONNECTION_USB);
   info.set_secure(false);
   *response.add_scanners() = std::move(info);
+  response.set_result(lorgnette::OPERATION_RESULT_SUCCESS);
 
   GetLorgnetteManagerClient()->SetListScannersResponse(response);
   fake_zeroconf_scanner_detector()->AddDetections({CreateZeroconfScanner()});
@@ -847,6 +856,8 @@
                      SecureScannerFilter::kSecureScannersOnly);
   WaitForResult();
   ASSERT_TRUE(list_scanners_response());
+  EXPECT_EQ(list_scanners_response()->result(),
+            lorgnette::OPERATION_RESULT_SUCCESS);
   ASSERT_EQ(list_scanners_response().value().scanners_size(), 1);
   EXPECT_EQ(list_scanners_response().value().scanners(0).name(),
             "airscan:escl:Test MX3100:https://192.168.0.3:5/");
@@ -861,6 +872,7 @@
   info.set_connection_type(lorgnette::CONNECTION_USB);
   info.set_secure(false);
   *response.add_scanners() = std::move(info);
+  response.set_result(lorgnette::OPERATION_RESULT_SUCCESS);
 
   // This scanner should get filtered out because it's a network scanner.
   GetLorgnetteManagerClient()->SetListScannersResponse(response);
@@ -871,6 +883,8 @@
                      SecureScannerFilter::kSecureScannersOnly);
   WaitForResult();
   ASSERT_TRUE(list_scanners_response());
+  EXPECT_EQ(list_scanners_response()->result(),
+            lorgnette::OPERATION_RESULT_SUCCESS);
   ASSERT_EQ(list_scanners_response().value().scanners_size(), 0);
 }
 
diff --git a/chrome/browser/compose/chrome_compose_client.cc b/chrome/browser/compose/chrome_compose_client.cc
index c67efa1..a8b84af 100644
--- a/chrome/browser/compose/chrome_compose_client.cc
+++ b/chrome/browser/compose/chrome_compose_client.cc
@@ -25,6 +25,7 @@
 #include "chrome/common/compose/type_conversions.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/compose/core/browser/compose_manager_impl.h"
+#include "components/compose/core/browser/compose_metrics.h"
 #include "components/optimization_guide/core/optimization_guide_decider.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/optimization_guide_util.h"
@@ -127,7 +128,13 @@
 void ChromeComposeClient::CloseUI(compose::mojom::CloseReason reason) {
   switch (reason) {
     case compose::mojom::CloseReason::kCloseButton:
+      SetSessionCloseReason(
+          compose::ComposeSessionCloseReason::kAcceptedSuggestion);
+      RemoveActiveSession();
+      break;
     case compose::mojom::CloseReason::kInsertButton:
+      SetSessionCloseReason(
+          compose::ComposeSessionCloseReason::kCloseButtonPressed);
       RemoveActiveSession();
       break;
   }
@@ -182,10 +189,25 @@
   last_compose_field_id_.reset();
 }
 
+void ChromeComposeClient::SetSessionCloseReason(
+    compose::ComposeSessionCloseReason close_reason) {
+  if (debug_session_) {
+    return;
+  }
+
+  if (last_compose_field_id_.has_value()) {
+    auto it = sessions_.find(last_compose_field_id_.value());
+    if (it != sessions_.end()) {
+      it->second->SetCloseReason(close_reason);
+    }
+  }
+}
+
 void ChromeComposeClient::RemoveAllSessions() {
   if (debug_session_) {
     debug_session_.reset();
   }
+
   sessions_.erase(sessions_.begin(), sessions_.end());
   last_compose_field_id_.reset();
 }
diff --git a/chrome/browser/compose/chrome_compose_client.h b/chrome/browser/compose/chrome_compose_client.h
index fa07dd33..584216f 100644
--- a/chrome/browser/compose/chrome_compose_client.h
+++ b/chrome/browser/compose/chrome_compose_client.h
@@ -114,6 +114,9 @@
   void CreateSessionIfNeeded(const autofill::FormFieldData& trigger_field,
                              ComposeCallback callback);
 
+  // Set the exit reason for a session.
+  void SetSessionCloseReason(compose::ComposeSessionCloseReason close_reason);
+
   // Removes `last_compose_field_id_` from `sessions_` and resets
   // `last_compose_field_id_`.
   void RemoveActiveSession();
diff --git a/chrome/browser/compose/chrome_compose_client_unittest.cc b/chrome/browser/compose/chrome_compose_client_unittest.cc
index cba1303..3c10ca52 100644
--- a/chrome/browser/compose/chrome_compose_client_unittest.cc
+++ b/chrome/browser/compose/chrome_compose_client_unittest.cc
@@ -229,6 +229,8 @@
     return any;
   }
 
+  const base::HistogramTester& histograms() const { return histogram_tester_; }
+
   base::test::ScopedFeatureList scoped_feature_list_;
 
  private:
@@ -238,6 +240,7 @@
   MockComposeDialog compose_dialog_;
   autofill::FormFieldData field_data_;
   raw_ptr<content::WebContents> contents_;
+  base::HistogramTester histogram_tester_;
 
   std::unique_ptr<mojo::Receiver<compose::mojom::ComposeDialog>>
       callback_router_;
@@ -1004,6 +1007,36 @@
   EXPECT_EQ(0, client().GetSessionCountForTest());
 }
 
+TEST_F(ChromeComposeClientTest, CloseButtonHistogramTest) {
+  ShowDialogAndBindMojo();
+  client().CloseUI(compose::mojom::CloseReason::kCloseButton);
+
+  histograms().ExpectBucketCount("Compose.SessionCloseReason",
+                                 0,  // close button pressed
+                                 1);
+}
+
+TEST_F(ChromeComposeClientTest, AcceptSuggestionHistogramTest) {
+  ShowDialogAndBindMojo();
+  client().CloseUI(compose::mojom::CloseReason::kInsertButton);
+
+  histograms().ExpectBucketCount("Compose.SessionCloseReason",
+                                 1,  // Accept button pressed
+                                 1);
+}
+
+TEST_F(ChromeComposeClientTest, LoseFocusHistogramTest) {
+  ShowDialogAndBindMojo();
+
+  // Dismiss dialog by losing focus by navigating.
+  GURL next_page("http://example.com/a.html");
+  NavigateAndCommit(web_contents(), next_page);
+
+  histograms().ExpectBucketCount("Compose.SessionCloseReason",
+                                 2,  // lost focus
+                                 1);
+}
+
 #if defined(GTEST_HAS_DEATH_TEST)
 // Tests that the Compose client crashes the browser if a webcontents
 // tries to bind mojo without opening the dialog at a non Compose URL.
diff --git a/chrome/browser/compose/compose_enabling.cc b/chrome/browser/compose/compose_enabling.cc
index 6751ddcdb..3fc8a24 100644
--- a/chrome/browser/compose/compose_enabling.cc
+++ b/chrome/browser/compose/compose_enabling.cc
@@ -171,7 +171,8 @@
   // sufficient for now. TODO(b/309162238) follow up on whether this is
   // sufficient long-term.
   if (top_level_frame_origin != element_frame_origin) {
-    return base::unexpected(compose::ComposeShowStatus::kGenericBlocked);
+    return base::unexpected(
+        compose::ComposeShowStatus::kFormFieldInCrossOriginFrame);
   }
 
   if (!base::FeatureList::IsEnabled(
diff --git a/chrome/browser/compose/compose_enabling_unittest.cc b/chrome/browser/compose/compose_enabling_unittest.cc
index 78c2d72..85e91d4 100644
--- a/chrome/browser/compose/compose_enabling_unittest.cc
+++ b/chrome/browser/compose/compose_enabling_unittest.cc
@@ -5,6 +5,7 @@
 #include <memory>
 
 #include "base/memory/raw_ptr.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/types/expected.h"
@@ -459,6 +460,7 @@
 }
 
 TEST_F(ComposeEnablingTest, ShouldTriggerContextMenuCrossOrigin) {
+  base::HistogramTester histogram_tester;
   ComposeEnabling compose_enabling(&mock_translate_language_provider_);
   // Enable everything.
   compose_enabling.SetEnabledForTesting();
@@ -470,4 +472,9 @@
   EXPECT_FALSE(compose_enabling.ShouldTriggerContextMenu(
       GetProfile(), mock_translate_manager_.get(), /*rfh=*/GetRenderFrameHost(),
       context_menu_params_));
+
+  // Check that a response result OK metric was emitted.
+  histogram_tester.ExpectUniqueSample(
+      compose::kComposeShowStatus,
+      compose::ComposeShowStatus::kFormFieldInCrossOriginFrame, 1);
 }
diff --git a/chrome/browser/compose/compose_session.cc b/chrome/browser/compose/compose_session.cc
index 97d3030..b953a21 100644
--- a/chrome/browser/compose/compose_session.cc
+++ b/chrome/browser/compose/compose_session.cc
@@ -53,6 +53,7 @@
     ComposeCallback callback)
     : executor_(executor),
       handler_receiver_(this),
+      close_reason_(compose::ComposeSessionCloseReason::kEndedImplicitly),
       web_contents_(web_contents),
       weak_ptr_factory_(this) {
   callback_ = std::move(callback);
@@ -63,7 +64,9 @@
                                                weak_ptr_factory_.GetWeakPtr()));
 }
 
-ComposeSession::~ComposeSession() = default;
+ComposeSession::~ComposeSession() {
+  LogComposeSessionCloseReason(close_reason_);
+}
 
 void ComposeSession::Bind(
     mojo::PendingReceiver<compose::mojom::ComposeSessionPageHandler> handler,
@@ -248,3 +251,8 @@
                                 base::BindOnce(&ComposeSession::FindInnerText,
                                                weak_ptr_factory_.GetWeakPtr()));
 }
+
+void ComposeSession::SetCloseReason(
+    compose::ComposeSessionCloseReason close_reason) {
+  close_reason_ = close_reason;
+}
diff --git a/chrome/browser/compose/compose_session.h b/chrome/browser/compose/compose_session.h
index d30e2ab..18be14b 100644
--- a/chrome/browser/compose/compose_session.h
+++ b/chrome/browser/compose/compose_session.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/compose/inner_text_extractor.h"
 #include "chrome/common/compose/compose.mojom.h"
 #include "components/autofill/core/common/unique_ids.h"
+#include "components/compose/core/browser/compose_metrics.h"
 #include "components/optimization_guide/core/optimization_guide_model_executor.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -96,6 +97,8 @@
   // Refresh the inner text on session resumption.
   void RefreshInnerText();
 
+  void SetCloseReason(compose::ComposeSessionCloseReason close_reason);
+
  private:
   void ProcessError(compose::mojom::ComposeStatus status);
   void ModelExecutionCallback(
@@ -127,6 +130,9 @@
   // Renderer provided text selection.
   std::string initial_input_;
 
+  // Reason that a compose session was exited, used for metrics.
+  compose::ComposeSessionCloseReason close_reason_;
+
   // ComposeSession is owned by WebContentsUserData, so `web_contents_` outlives
   // `this`.
   raw_ptr<content::WebContents> web_contents_;
diff --git a/chrome/browser/extensions/event_metrics_browsertest.cc b/chrome/browser/extensions/event_metrics_browsertest.cc
index c078e29e..ed05fac 100644
--- a/chrome/browser/extensions/event_metrics_browsertest.cc
+++ b/chrome/browser/extensions/event_metrics_browsertest.cc
@@ -2,11 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/test/browser_test.h"
+#include "extensions/browser/background_script_executor.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/test_extension_dir.h"
+#include "net/dns/mock_host_resolver.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace extensions {
@@ -28,12 +31,12 @@
     const std::vector<std::string> event_metrics_not_emitted;
   } test_cases[] = {
       // DispatchToAckTime
-      {"Extensions.Events.DispatchToAckTime.ExtensionEventPage2",
+      {"Extensions.Events.DispatchToAckTime.ExtensionEventPage3",
        ContextType::kFromManifest,  // event page
        {"Extensions.Events.DispatchToAckTime.ExtensionServiceWorker2"}},
       {"Extensions.Events.DispatchToAckTime.ExtensionServiceWorker2",
        ContextType::kServiceWorker,
-       {"Extensions.Events.DispatchToAckTime.ExtensionEventPage2"}},
+       {"Extensions.Events.DispatchToAckTime.ExtensionEventPage3"}},
       // TODO(crbug.com/1441221): Add `event_metrics_not_emitted` when other
       // versions are created.
       // DispatchToAckLongTime
@@ -254,6 +257,107 @@
                          EventMetricsDispatchToSenderBrowserTest,
                          ::testing::Values(ContextType::kServiceWorker));
 
+class LazyBackgroundEventMetricsApiTest : public ExtensionApiTest {
+ public:
+  LazyBackgroundEventMetricsApiTest() = default;
+
+  LazyBackgroundEventMetricsApiTest(const LazyBackgroundEventMetricsApiTest&) =
+      delete;
+  LazyBackgroundEventMetricsApiTest& operator=(
+      const LazyBackgroundEventMetricsApiTest&) = delete;
+
+  void SetUpOnMainThread() override {
+    ExtensionApiTest::SetUpOnMainThread();
+    host_resolver()->AddRule("*", "127.0.0.1");
+    ASSERT_TRUE(StartEmbeddedTestServer());
+  }
+
+  content::WebContents* web_contents() {
+    return browser()->tab_strip_model()->GetActiveWebContents();
+  }
+};
+
+// Tests that if there is a listener in the extension renderer process, but that
+// listener is not in the lazy background page script, then do not emit
+// background context event dispatching histograms.
+IN_PROC_BROWSER_TEST_F(
+    LazyBackgroundEventMetricsApiTest,
+    ContextsOutsideLazyBackgroundDoNotEmitBackgroundContextMetrics) {
+  // Load an extension with a page script that runs in the extension renderer
+  // process, and has the only chrome.storage.onChanged listener.
+  static constexpr char kManifest[] =
+      R"({
+           "name": "Event page",
+           "version": "0.1",
+           "manifest_version": 2,
+           "background": {
+             "scripts": ["background.js"],
+             "persistent": false
+            },
+           "permissions": ["storage"]
+         })";
+  TestExtensionDir test_dir;
+  test_dir.WriteManifest(kManifest);
+  constexpr char kPageHtml[] = R"(<script src="page.js"></script>)";
+  test_dir.WriteFile(FILE_PATH_LITERAL("page.html"), kPageHtml);
+  constexpr char kPageScriptJs[] =
+      R"(
+       chrome.storage.onChanged.addListener((details) => {
+         // Asynchronously send the message that the listener fired so that the
+         // event is considered ack'd in the browser C++ code.
+         setTimeout(() => {
+           chrome.test.sendMessage('listener fired');
+         }, 0);
+       });
+
+       chrome.test.sendMessage('page script loaded');
+      )";
+  test_dir.WriteFile(FILE_PATH_LITERAL("page.js"), kPageScriptJs);
+  constexpr char kBackgroundJs[] =
+      R"(
+      chrome.runtime.onInstalled.addListener((details) => {
+        // Asynchronously send the message that the listener fired so that the
+        // event is considered ack'd in the browser C++ code.
+        setTimeout(() => {
+          chrome.test.sendMessage('installed listener fired');
+        }, 0);
+      });
+    )";
+  test_dir.WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundJs);
+  ExtensionTestMessageListener extension_oninstall_listener_fired(
+      "installed listener fired");
+  const Extension* extension = LoadExtension(test_dir.UnpackedPath());
+  ASSERT_TRUE(extension);
+  // This ensures that we wait until the the browser receives the ack from the
+  // renderer. This prevents unexpected histogram emits later.
+  ASSERT_TRUE(extension_oninstall_listener_fired.WaitUntilSatisfied());
+
+  ExtensionTestMessageListener page_script_loaded("page script loaded");
+  // Navigate to page.html to get the content_script to load.
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), extension->GetResourceURL("page.html")));
+  ASSERT_TRUE(content::WaitForLoadStop(web_contents()));
+  ASSERT_TRUE(page_script_loaded.WaitUntilSatisfied());
+
+  // Set storage value which should fire chrome.storage.onChanged listener in
+  // the page.
+  base::HistogramTester histogram_tester;
+  ExtensionTestMessageListener page_script_event_listener_fired(
+      "listener fired");
+  static constexpr char kScript[] =
+      R"(chrome.storage.local.set({"key" : "value"});)";
+  BackgroundScriptExecutor::ExecuteScriptAsync(profile(), extension->id(),
+                                               kScript);
+
+  // Confirm that the listener in the page script was fired, but that we do not
+  // emit a histogram for it.
+  EXPECT_TRUE(page_script_event_listener_fired.WaitUntilSatisfied());
+  // Call to storage.onChanged expected.
+  histogram_tester.ExpectTotalCount(
+      "Extensions.Events.DispatchToAckTime.ExtensionEventPage3",
+      /*expected_count=*/0);
+}
+
 }  // namespace
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/process_map_browsertest.cc b/chrome/browser/extensions/process_map_browsertest.cc
index 73161ec..50d80a6 100644
--- a/chrome/browser/extensions/process_map_browsertest.cc
+++ b/chrome/browser/extensions/process_map_browsertest.cc
@@ -13,6 +13,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/browser/site_isolation_policy.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
@@ -508,9 +509,11 @@
 }
 
 // Tests that sandboxed extension frames are considered privileged
-// extension processes, since they execute within the same process (even
-// though they don't have direct API access). This isn't a security bug
+// extension processes. Historically they execute within the same process (even
+// though they don't have direct API access), so this isn't a security bug
 // since any compromised renderer could just access an un-sandboxed context.
+// But when IsolateSandboxedIframes is enabled, they do end up in a separate
+// process, and are still listed as privileged in the ProcessMap.
 // TODO(https://crbug.com/510122): This could change with out-of-process-
 // sandboxed-iframes.
 IN_PROC_BROWSER_TEST_F(ProcessMapBrowserTest,
@@ -531,7 +534,12 @@
   int main_frame_process_id = main_frame->GetProcess()->GetID();
   int sandboxed_frame_process_id = sandboxed_frame->GetProcess()->GetID();
 
-  EXPECT_EQ(main_frame_process_id, sandboxed_frame_process_id);
+  if (content::SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled()) {
+    EXPECT_NE(main_frame_process_id, sandboxed_frame_process_id);
+  } else {
+    EXPECT_EQ(main_frame_process_id, sandboxed_frame_process_id);
+  }
+
   EXPECT_TRUE(process_map()->IsPrivilegedExtensionProcess(
       *extension, main_frame_process_id));
   EXPECT_TRUE(process_map()->IsPrivilegedExtensionProcess(
@@ -559,7 +567,11 @@
   content::RenderProcessHost& sandboxed_frame_process =
       *sandboxed_frame->GetProcess();
 
-  EXPECT_EQ(main_frame_process.GetID(), sandboxed_frame_process.GetID());
+  if (content::SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled()) {
+    EXPECT_NE(main_frame_process.GetID(), sandboxed_frame_process.GetID());
+  } else {
+    EXPECT_EQ(main_frame_process.GetID(), sandboxed_frame_process.GetID());
+  }
 
   RunCanProcessHostContextTypeChecks(
       extension, main_frame_process,
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index b72d8a5..dd0ad3c 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -6760,7 +6760,7 @@
   {
     "name": "reduce-accept-language",
     "owners": [ "miketaylr@chromium.org", "victortan@chromium.org"],
-    "expiry_milestone": 120
+    "expiry_milestone": 125
   },
   {
     "name": "reengagement-notification",
diff --git a/chrome/browser/metrics/chromeos_system_profile_provider.cc b/chrome/browser/metrics/chromeos_system_profile_provider.cc
index 7041d7a..c41668c 100644
--- a/chrome/browser/metrics/chromeos_system_profile_provider.cc
+++ b/chrome/browser/metrics/chromeos_system_profile_provider.cc
@@ -9,6 +9,7 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/task/thread_pool.h"
+#include "base/version.h"
 #include "chrome/browser/ash/login/demo_mode/demo_mode_dimensions.h"
 #include "chrome/browser/ash/login/demo_mode/demo_session.h"
 #include "chrome/browser/ash/login/users/chrome_user_manager_util.h"
@@ -176,6 +177,11 @@
         metrics::
             SystemProfileProto_DemoModeDimensions_CustomizationFacet_FEATURE_AWARE_DEVICE);
   }
+
+  demo_mode_dimensions->set_app_version(
+      ash::demo_mode::AppVersion().GetString());
+  demo_mode_dimensions->set_resources_version(
+      ash::demo_mode::ResourcesVersion().GetString());
 }
 
 void ChromeOSSystemProfileProvider::InitTaskGetFullHardwareClass(
diff --git a/chrome/browser/metrics/chromeos_system_profile_provider_unittest.cc b/chrome/browser/metrics/chromeos_system_profile_provider_unittest.cc
index 71271d5..a584af8 100644
--- a/chrome/browser/metrics/chromeos_system_profile_provider_unittest.cc
+++ b/chrome/browser/metrics/chromeos_system_profile_provider_unittest.cc
@@ -260,6 +260,8 @@
   const std::string expected_country = "CA";
   const std::string expected_retailer_id = "ABC";
   const std::string expected_store_id = "12345";
+  const std::string app_expected_version = "0.0.0.0";
+  const std::string resources_expected_version = "0.0.0.1";
   scoped_feature_list_.InitWithFeatures(
       {chromeos::features::kCloudGamingDevice,
        ash::features::kFeatureManagementFeatureAwareDeviceDemoMode},
@@ -270,6 +272,10 @@
                                               expected_retailer_id);
   g_browser_process->local_state()->SetString("demo_mode.store_id",
                                               expected_store_id);
+  g_browser_process->local_state()->SetString("demo_mode.app_version",
+                                              app_expected_version);
+  g_browser_process->local_state()->SetString("demo_mode.resources_version",
+                                              resources_expected_version);
 
   TestChromeOSSystemProfileProvider provider;
   provider.OnDidCreateMetricsLog();
@@ -297,10 +303,15 @@
       system_profile.demo_mode_dimensions().retailer().retailer_id();
   std::string store_id =
       system_profile.demo_mode_dimensions().retailer().store_id();
+  std::string app_version = system_profile.demo_mode_dimensions().app_version();
+  std::string resources_version =
+      system_profile.demo_mode_dimensions().resources_version();
 
   EXPECT_EQ(country, expected_country);
   EXPECT_EQ(retailer_id, expected_retailer_id);
   EXPECT_EQ(store_id, expected_store_id);
+  EXPECT_EQ(app_version, app_expected_version);
+  EXPECT_EQ(resources_version, resources_expected_version);
 }
 
 TEST_F(ChromeOSSystemProfileProviderTest, TpmRwFirmwareVersion) {
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc
index 39212763..ff90240 100644
--- a/chrome/browser/net/profile_network_context_service.cc
+++ b/chrome/browser/net/profile_network_context_service.cc
@@ -146,10 +146,11 @@
 }
 
 #if BUILDFLAG(IS_CHROMEOS)
-network::mojom::AdditionalCertificatesPtr GetAdditionalCertificates(
+cert_verifier::mojom::AdditionalCertificatesPtr GetAdditionalCertificates(
     const policy::PolicyCertService* policy_cert_service,
     const base::FilePath& storage_partition_path) {
-  auto additional_certificates = network::mojom::AdditionalCertificates::New();
+  auto additional_certificates =
+      cert_verifier::mojom::AdditionalCertificates::New();
   policy_cert_service->GetPolicyCertificatesForStoragePartition(
       storage_partition_path, &(additional_certificates->all_certificates),
       &(additional_certificates->trust_anchors));
@@ -354,8 +355,8 @@
          content::StoragePartition* storage_partition) {
         auto additional_certificates = GetAdditionalCertificates(
             policy_cert_service, storage_partition->GetPath());
-        storage_partition->GetNetworkContext()->UpdateAdditionalCertificates(
-            std::move(additional_certificates));
+        storage_partition->GetCertVerifierServiceUpdater()
+            ->UpdateAdditionalCertificates(std::move(additional_certificates));
       },
       policy_cert_service));
 }
@@ -773,12 +774,12 @@
 #if BUILDFLAG(IS_CHROMEOS)
 void ProfileNetworkContextService::PopulateInitialAdditionalCerts(
     const base::FilePath& relative_partition_path,
-    network::mojom::NetworkContextParams* network_context_params) {
+    cert_verifier::mojom::CertVerifierCreationParams* creation_params) {
   if (policy::PolicyCertServiceFactory::CreateAndStartObservingForProfile(
           profile_)) {
     const policy::PolicyCertService* policy_cert_service =
         policy::PolicyCertServiceFactory::GetForProfile(profile_);
-    network_context_params->initial_additional_certificates =
+    creation_params->initial_additional_certificates =
         GetAdditionalCertificates(policy_cert_service,
                                   GetPartitionPath(relative_partition_path));
   }
@@ -949,7 +950,7 @@
   }
 
   PopulateInitialAdditionalCerts(relative_partition_path,
-                                 network_context_params);
+                                 cert_verifier_creation_params);
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -974,7 +975,7 @@
   }
   if (profile_supports_policy_certs) {
     PopulateInitialAdditionalCerts(relative_partition_path,
-                                   network_context_params);
+                                   cert_verifier_creation_params);
   }
 #endif
 
diff --git a/chrome/browser/net/profile_network_context_service.h b/chrome/browser/net/profile_network_context_service.h
index 1f0e5ff..6099e20 100644
--- a/chrome/browser/net/profile_network_context_service.h
+++ b/chrome/browser/net/profile_network_context_service.h
@@ -170,7 +170,7 @@
   // authority certificates for |relative_partition_path|.
   void PopulateInitialAdditionalCerts(
       const base::FilePath& relative_partition_path,
-      network::mojom::NetworkContextParams* network_context_params);
+      cert_verifier::mojom::CertVerifierCreationParams* creation_params);
 
   // content_settings::Observer:
   void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern,
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc
index 5a28cf8..696858d 100644
--- a/chrome/browser/net/system_network_context_manager.cc
+++ b/chrome/browser/net/system_network_context_manager.cc
@@ -892,6 +892,9 @@
       cert_verifier_creation_params =
           cert_verifier::mojom::CertVerifierCreationParams::New();
   ConfigureDefaultNetworkContextParams(network_context_params.get());
+  // The system network context doesn't update the CertVerifyProc
+  // InstanceParams while running, so it does not attach a
+  // CertVerifierServiceUpdater.
   network_context_params->cert_verifier_params =
       content::GetCertVerifierParams(std::move(cert_verifier_creation_params));
   network_context_params->acam_preflight_spec_conformant =
diff --git a/chrome/browser/policy/networking/policy_cert_service_factory.cc b/chrome/browser/policy/networking/policy_cert_service_factory.cc
index 79e0e1e..17f3937 100644
--- a/chrome/browser/policy/networking/policy_cert_service_factory.cc
+++ b/chrome/browser/policy/networking/policy_cert_service_factory.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/scoped_user_pref_update.h"
-#include "services/network/cert_verifier_with_trust_anchors.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/constants/ash_features.h"
diff --git a/chrome/browser/policy/test/policy_certs_browsertest.cc b/chrome/browser/policy/test/policy_certs_browsertest.cc
index 2dcf4cd7..5eb3bb7 100644
--- a/chrome/browser/policy/test/policy_certs_browsertest.cc
+++ b/chrome/browser/policy/test/policy_certs_browsertest.cc
@@ -19,6 +19,8 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/net/nss_service.h"
 #include "chrome/browser/net/nss_service_factory.h"
+#include "chrome/browser/policy/networking/policy_cert_service.h"
+#include "chrome/browser/policy/networking/policy_cert_service_factory.h"
 #include "chrome/browser/policy/networking/user_network_configuration_updater_ash.h"
 #include "chrome/browser/policy/networking/user_network_configuration_updater_factory.h"
 #include "chrome/browser/policy/profile_policy_connector_builder.h"
@@ -247,6 +249,9 @@
 
     // Note that this relies on the implementation detail that the notification
     // is sent even if the trust roots effectively remain the same.
+    //
+    // Ideally this should wait on the roots making it all the way to the
+    // CertVerifierService, but there is no good way to do this currently.
     trust_roots_changed_observer.Wait();
     user_network_configuration_updater->RemovePolicyProvidedCertsObserver(
         &trust_roots_changed_observer);
@@ -427,6 +432,8 @@
   EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
             VerifyTestServerCert(multi_profile_policy_helper_.profile_2(),
                                  user_policy_certs_helper_.server_cert()));
+  EXPECT_FALSE(PolicyCertServiceFactory::GetForProfile(browser()->profile())
+                   ->UsedPolicyCertificates());
 }
 
 IN_PROC_BROWSER_TEST_F(PolicyProvidedCertsRegularUserTest, TrustAnchorApplied) {
@@ -436,6 +443,8 @@
   EXPECT_EQ(net::OK,
             VerifyTestServerCert(multi_profile_policy_helper_.profile_1(),
                                  user_policy_certs_helper_.server_cert()));
+  EXPECT_TRUE(PolicyCertServiceFactory::GetForProfile(browser()->profile())
+                  ->UsedPolicyCertificates());
 }
 
 // Test that policy provided trust anchors are available in Incognito mode.
@@ -466,6 +475,12 @@
   EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
             VerifyTestServerCert(multi_profile_policy_helper_.profile_2(),
                                  user_policy_certs_helper_.server_cert()));
+  EXPECT_TRUE(PolicyCertServiceFactory::GetForProfile(
+                  multi_profile_policy_helper_.profile_1())
+                  ->UsedPolicyCertificates());
+  EXPECT_FALSE(PolicyCertServiceFactory::GetForProfile(
+                   multi_profile_policy_helper_.profile_2())
+                   ->UsedPolicyCertificates());
 }
 
 IN_PROC_BROWSER_TEST_F(PolicyProvidedCertsRegularUserTest,
@@ -583,6 +598,11 @@
   EXPECT_EQ(net::OK,
             VerifyTestServerCert(ash::ProfileHelper::GetLockScreenProfile(),
                                  user_policy_certs_helper_.server_cert()));
+  EXPECT_TRUE(PolicyCertServiceFactory::GetForProfile(browser()->profile())
+                  ->UsedPolicyCertificates());
+  EXPECT_TRUE(PolicyCertServiceFactory::GetForProfile(
+                  ash::ProfileHelper::GetLockScreenProfile())
+                  ->UsedPolicyCertificates());
 }
 
 // Test that the lock screen profile doesn't use the policy provided custom
@@ -644,6 +664,11 @@
   EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
             VerifyTestServerCert(ash::ProfileHelper::GetLockScreenProfile(),
                                  user_policy_certs_helper_.server_cert()));
+  EXPECT_TRUE(PolicyCertServiceFactory::GetForProfile(browser()->profile())
+                  ->UsedPolicyCertificates());
+  // The lock screen profile does not have a PolicyCertService initialized.
+  EXPECT_FALSE(PolicyCertServiceFactory::GetForProfile(
+      ash::ProfileHelper::GetLockScreenProfile()));
 }
 
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/printing/system_access_process_print_browsertest.cc b/chrome/browser/printing/system_access_process_print_browsertest.cc
index 543ff44f..bb66cde 100644
--- a/chrome/browser/printing/system_access_process_print_browsertest.cc
+++ b/chrome/browser/printing/system_access_process_print_browsertest.cc
@@ -804,6 +804,15 @@
 #if BUILDFLAG(IS_WIN)
   void PrimeForPdfConversionErrorOnPageIndex(uint32_t page_index) {
     simulate_pdf_conversion_error_on_page_index_ = page_index;
+
+    // Queuing converted pages to be spooled occurs on the UI thread, while the
+    // actual spooling occurs on the worker thread.  The worker thread polls for
+    // pages, making it difficult to know if earlier pages that are successfully
+    // converted will get spooled before some other error causes the job to be
+    // canceled.  Do not use rendered page counts as part of any test
+    // expectations in this case.  Other events should be used to know when it
+    // is safe to terminate the test.
+    DisableCheckForOnRenderedPrintedPage();
   }
 #endif
 
@@ -866,6 +875,12 @@
         /*cause_errors=*/true);
   }
 
+#if BUILDFLAG(IS_WIN)
+  void DisableCheckForOnRenderedPrintedPage() {
+    check_for_rendered_printed_page_ = false;
+  }
+#endif
+
   void SetCheckForPrintPreviewDone(bool check) {
     check_for_print_preview_done_ = check;
   }
@@ -1013,7 +1028,9 @@
     if (result == mojom::ResultCode::kSuccess) {
       render_printed_pages_count_++;
     }
-    CheckForQuit();
+    if (check_for_rendered_printed_page_) {
+      CheckForQuit();
+    }
   }
 #endif
 
@@ -1056,6 +1073,9 @@
   }
 
   base::test::ScopedFeatureList feature_list_;
+#if BUILDFLAG(IS_WIN)
+  bool check_for_rendered_printed_page_ = true;
+#endif
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
   bool check_for_print_preview_done_ = false;
   TestPrintJobWorker::PrintCallbacks test_print_job_worker_callbacks_;
@@ -1475,8 +1495,7 @@
 
 #if BUILDFLAG(IS_WIN)
 IN_PROC_BROWSER_TEST_P(SystemAccessProcessPrintBrowserTest,
-                       // TODO(crbug.com/1491616): Re-enable this test
-                       DISABLED_StartPrintingPdfConversionFails) {
+                       StartPrintingPdfConversionFails) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
   PrimeForPdfConversionErrorOnPageIndex(/*page_index=*/1);
@@ -1514,13 +1533,12 @@
   // only for OOP.
   if (UseService()) {
     EXPECT_EQ(start_printing_result(), mojom::ResultCode::kSuccess);
-    // TODO(crbug.com/1008222)  Include Windows coverage of
-    // RenderPrintedDocument() once XPS print pipeline is added.
-    EXPECT_EQ(render_printed_page_result(), mojom::ResultCode::kFailed);
   } else {
     EXPECT_THAT(in_process_last_error_result_code(),
                 testing::Optional(mojom::ResultCode::kCanceled));
   }
+  // TODO(crbug.com/1500445):  Update expectation once an error is shown for
+  // this failure.
   EXPECT_EQ(error_dialog_shown_count(), 0u);
   EXPECT_EQ(print_job_destruction_count(), 1);
 }
@@ -2323,13 +2341,12 @@
 
   if (UseService()) {
     EXPECT_EQ(start_printing_result(), mojom::ResultCode::kSuccess);
-    // TODO(crbug.com/1008222)  Include Windows coverage of
-    // RenderPrintedDocument() once XPS print pipeline is added.
-    EXPECT_EQ(render_printed_page_result(), mojom::ResultCode::kFailed);
   } else {
     EXPECT_THAT(in_process_last_error_result_code(),
                 testing::Optional(mojom::ResultCode::kCanceled));
   }
+  // TODO(crbug.com/1500445):  Update expectation once an error is shown for
+  // this failure.
   EXPECT_EQ(error_dialog_shown_count(), 0u);
   EXPECT_EQ(print_job_destruction_count(), 1);
 }
diff --git a/chrome/browser/readaloud/android/BUILD.gn b/chrome/browser/readaloud/android/BUILD.gn
index ca60fe6..22864d4 100644
--- a/chrome/browser/readaloud/android/BUILD.gn
+++ b/chrome/browser/readaloud/android/BUILD.gn
@@ -202,6 +202,7 @@
     "java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayout.java",
     "java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java",
     "java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerViewBinder.java",
+    "java/src/org/chromium/chrome/browser/readaloud/player/mini/Properties.java",
   ]
   deps = [
     ":java_resources",
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediator.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediator.java
index 6f0af4ed..1d59ff7a 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediator.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediator.java
@@ -30,6 +30,8 @@
                 @Override
                 public void onPlaybackDataChanged(PlaybackData data) {
                     setPlaybackState(data.state());
+                    mModel.set(PlayerProperties.ELAPSED_NANOS, data.absolutePositionNanos());
+                    mModel.set(PlayerProperties.DURATION_NANOS, data.totalDurationNanos());
                     float percent =
                             (float) data.absolutePositionNanos()
                                     / (float) data.totalDurationNanos();
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerProperties.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerProperties.java
index 837409d..edaf25f 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerProperties.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerProperties.java
@@ -4,19 +4,13 @@
 
 package org.chromium.chrome.browser.readaloud.player;
 
-import org.chromium.chrome.browser.readaloud.player.mini.MiniPlayerMediator;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
 
 /** Keys for Read Aloud player model properties. */
 public class PlayerProperties {
-    // VisibilityState
-    public static final WritableObjectPropertyKey<Integer> MINI_PLAYER_VISIBILITY =
-            new WritableObjectPropertyKey<>();
     public static final WritableObjectPropertyKey<Integer> EXPANDED_PLAYER_VISIBILITY =
             new WritableObjectPropertyKey<>();
-    public static final WritableObjectPropertyKey<Boolean> MINI_PLAYER_ANIMATE_VISIBILITY_CHANGES =
-            new WritableObjectPropertyKey<>();
     public static final WritableObjectPropertyKey<String> TITLE = new WritableObjectPropertyKey<>();
     public static final WritableObjectPropertyKey<String> PUBLISHER =
             new WritableObjectPropertyKey<>();
@@ -31,17 +25,12 @@
             new WritableObjectPropertyKey<>();
     public static final WritableObjectPropertyKey<InteractionHandler> INTERACTION_HANDLER =
             new WritableObjectPropertyKey<>();
-    public static final WritableObjectPropertyKey<MiniPlayerMediator> MINI_PLAYER_MEDIATOR =
-            new WritableObjectPropertyKey<>();
     public static final PropertyKey[] ALL_KEYS = {
-        MINI_PLAYER_VISIBILITY, //
         EXPANDED_PLAYER_VISIBILITY, //
-        MINI_PLAYER_ANIMATE_VISIBILITY_CHANGES, //
         TITLE, //
         PUBLISHER, //
         PLAYBACK_STATE, //
         PROGRESS, //
-        MINI_PLAYER_MEDIATOR, //
         SPEED, //
         ELAPSED_NANOS, //
         DURATION_NANOS, //
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerCoordinatorUnitTest.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerCoordinatorUnitTest.java
index e0e764d..8406679 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerCoordinatorUnitTest.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerCoordinatorUnitTest.java
@@ -32,7 +32,7 @@
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
 import org.chromium.ui.modelutil.PropertyModel;
 
-/** Unit tests for {@link ExpandedPlayerCoordinator}. */
+/** Unit tests for {@link ExpandedPlayerCoordinator} and ExpandedPlayerViewBinder. */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class ExpandedPlayerCoordinatorUnitTest {
@@ -124,6 +124,20 @@
     }
 
     @Test
+    public void testBindElapsed() {
+        mModel.set(PlayerProperties.ELAPSED_NANOS, 20L);
+        verify(mSheetContent).setElapsed(20L);
+        assertTrue(mModel.get(PlayerProperties.ELAPSED_NANOS).equals(20L));
+    }
+
+    @Test
+    public void testBindDuration() {
+        mModel.set(PlayerProperties.DURATION_NANOS, 30L);
+        verify(mSheetContent).setDuration(30L);
+        assertTrue(mModel.get(PlayerProperties.DURATION_NANOS).equals(30L));
+    }
+
+    @Test
     public void testBindSpeed() {
         mModel.set(PlayerProperties.SPEED, 2f);
         verify(mSheetContent).setSpeed(eq(2f));
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContent.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContent.java
index 185bd16..ce1bd5b 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContent.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContent.java
@@ -6,6 +6,7 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.text.format.DateUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
@@ -86,6 +87,25 @@
                 .setText(publisher);
     }
 
+    void setElapsed(Long nanos) {
+        ((TextView) mContentView.findViewById(R.id.readaloud_player_time))
+                .setText(formatTimeNanos(nanos));
+    }
+
+    void setDuration(Long nanos) {
+        ((TextView) mContentView.findViewById(R.id.readaloud_player_duration))
+                .setText(formatTimeNanos(nanos));
+    }
+
+    private static String formatTimeNanos(long nanos) {
+        if (nanos <= 0) {
+            return DateUtils.formatElapsedTime(0);
+        }
+        final long nanosPerSecond = 1_000_000_000L;
+        long seconds = nanos / nanosPerSecond;
+        return DateUtils.formatElapsedTime(seconds);
+    }
+
     void setInteractionHandler(InteractionHandler handler) {
         setOnClickListener(R.id.readaloud_play_pause_button, handler::onPlayPauseClick);
         setOnClickListener(R.id.readaloud_seek_back_button, handler::onSeekBackClick);
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContentUnitTest.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContentUnitTest.java
index 34919130..5ed47bb 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContentUnitTest.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContentUnitTest.java
@@ -118,6 +118,39 @@
     }
 
     @Test
+    public void testSetElapsed() {
+        mContent.setElapsed(1_000_000_000L * 20);
+        assertEquals(
+                "00:20",
+                ((TextView) mContentView.findViewById(R.id.readaloud_player_time)).getText());
+        mContent.setElapsed(1_000_000_000L * 123);
+        assertEquals(
+                "02:03",
+                ((TextView) mContentView.findViewById(R.id.readaloud_player_time)).getText());
+
+        mContent.setElapsed(1_000_000_000L * -30);
+        assertEquals(
+                "00:00",
+                ((TextView) mContentView.findViewById(R.id.readaloud_player_time)).getText());
+    }
+
+    @Test
+    public void testSetDuration() {
+        mContent.setDuration(1_000_000_000L * 20);
+        assertEquals(
+                "00:20",
+                ((TextView) mContentView.findViewById(R.id.readaloud_player_duration)).getText());
+        mContent.setDuration(1_000_000_000L * 12345);
+        assertEquals(
+                "3:25:45",
+                ((TextView) mContentView.findViewById(R.id.readaloud_player_duration)).getText());
+        mContent.setDuration(1_000_000_000L * -100);
+        assertEquals(
+                "00:00",
+                ((TextView) mContentView.findViewById(R.id.readaloud_player_duration)).getText());
+    }
+
+    @Test
     public void testSetSpeed() {
         mContent.setSpeed(0.5f);
         assertEquals("0.5x", mSpeedView.getText());
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerViewBinder.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerViewBinder.java
index 5747858..59b6b813 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerViewBinder.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerViewBinder.java
@@ -37,6 +37,10 @@
                     model.get(PlayerProperties.PLAYBACK_STATE) == PlaybackListener.State.PLAYING);
         } else if (key == PlayerProperties.SPEED) {
             content.setSpeed(model.get(PlayerProperties.SPEED));
+        } else if (key == PlayerProperties.ELAPSED_NANOS) {
+            content.setElapsed(model.get(PlayerProperties.ELAPSED_NANOS));
+        } else if (key == PlayerProperties.DURATION_NANOS) {
+            content.setDuration(model.get(PlayerProperties.DURATION_NANOS));
         } else if (key == PlayerProperties.INTERACTION_HANDLER) {
             content.setInteractionHandler(model.get(PlayerProperties.INTERACTION_HANDLER));
         }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerCoordinator.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerCoordinator.java
index e44cd20..979b27f 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerCoordinator.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerCoordinator.java
@@ -22,9 +22,11 @@
 
 /** Coordinator responsible for Read Aloud mini player lifecycle. */
 public class MiniPlayerCoordinator {
-    private final PropertyModel mModel;
     private final PropertyModelChangeProcessor<PropertyModel, MiniPlayerLayout, PropertyKey>
-            mModelChangeProcessor;
+            mPlayerModelChangeProcessor;
+    private final PropertyModelChangeProcessor<
+                    PropertyModel, MiniPlayerViewBinder.ViewHolder, PropertyKey>
+            mMiniPlayerModelChangeProcessor;
     private final MiniPlayerMediator mMediator;
     private final MiniPlayerLayout mLayout;
     // Compositor layer to be shown during show and hide while browser controls are
@@ -35,17 +37,17 @@
      * @param activity App activity containing a placeholder FrameLayout with ID
      *     R.id.readaloud_mini_player.
      * @param context View-inflation-capable Context for read_aloud_playback isolated split.
-     * @param model Player UI property model.
+     * @param sharedModel Player UI property model for properties shared with expanded player.
      */
     public MiniPlayerCoordinator(
             Activity activity,
             Context context,
-            PropertyModel model,
+            PropertyModel sharedModel,
             BrowserControlsSizer browserControlsSizer,
             LayoutManager layoutManager) {
         this(
-                model,
-                new MiniPlayerMediator(model, browserControlsSizer),
+                sharedModel,
+                new MiniPlayerMediator(browserControlsSizer),
                 inflateLayout(activity, context),
                 new ReadAloudMiniPlayerSceneLayer(browserControlsSizer),
                 layoutManager);
@@ -61,20 +63,25 @@
 
     @VisibleForTesting
     MiniPlayerCoordinator(
-            PropertyModel model,
+            PropertyModel sharedModel,
             MiniPlayerMediator mediator,
             MiniPlayerLayout layout,
             ReadAloudMiniPlayerSceneLayer sceneLayer,
             LayoutManager layoutManager) {
-        mModel = model;
         mMediator = mediator;
         mLayout = layout;
         assert layout != null;
         mSceneLayer = sceneLayer;
         layoutManager.addSceneOverlay(mSceneLayer);
 
-        mModelChangeProcessor =
-                PropertyModelChangeProcessor.create(mModel, layout, MiniPlayerViewBinder::bind);
+        mPlayerModelChangeProcessor =
+                PropertyModelChangeProcessor.create(
+                        sharedModel, mLayout, MiniPlayerViewBinder::bindPlayerProperties);
+        mMiniPlayerModelChangeProcessor =
+                PropertyModelChangeProcessor.create(
+                        mMediator.getModel(),
+                        new MiniPlayerViewBinder.ViewHolder(layout, sceneLayer),
+                        MiniPlayerViewBinder::bindMiniPlayerProperties);
     }
 
     public void destroy() {
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerCoordinatorUnitTest.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerCoordinatorUnitTest.java
index cfecefe..d0c2ed40 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerCoordinatorUnitTest.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerCoordinatorUnitTest.java
@@ -56,6 +56,7 @@
     @Mock private MiniPlayerLayout mLayout;
     @Mock private MiniPlayerMediator mMediator;
     @Mock private ReadAloudMiniPlayerSceneLayer mSceneLayer;
+    private PropertyModel mSharedModel;
     private PropertyModel mModel;
 
     private MiniPlayerCoordinator mCoordinator;
@@ -68,11 +69,14 @@
         doReturn(mLayoutInflater)
                 .when(mContextForInflation)
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        mModel = new PropertyModel.Builder(PlayerProperties.ALL_KEYS).build();
+        mSharedModel = new PropertyModel.Builder(PlayerProperties.ALL_KEYS).build();
+        mModel = new PropertyModel.Builder(Properties.ALL_KEYS).build();
         mJniMocker.mock(ReadAloudMiniPlayerSceneLayerJni.TEST_HOOKS, mSceneLayerNativeMock);
         doReturn(123456789L).when(mSceneLayerNativeMock).init(any());
+        doReturn(mModel).when(mMediator).getModel();
         mCoordinator =
-                new MiniPlayerCoordinator(mModel, mMediator, mLayout, mSceneLayer, mLayoutManager);
+                new MiniPlayerCoordinator(
+                        mSharedModel, mMediator, mLayout, mSceneLayer, mLayoutManager);
     }
 
     @Test
@@ -84,7 +88,7 @@
                 new MiniPlayerCoordinator(
                         mActivity,
                         mContextForInflation,
-                        mModel,
+                        mSharedModel,
                         mBrowserControlsSizer,
                         mLayoutManager);
         verify(mViewStub).inflate();
@@ -118,37 +122,28 @@
     @Test
     public void testBindPlaybackState() {
         mCoordinator.show(/* animate= */ true);
-        mModel.set(PlayerProperties.PLAYBACK_STATE, PlaybackListener.State.PLAYING);
+        mSharedModel.set(PlayerProperties.PLAYBACK_STATE, PlaybackListener.State.PLAYING);
         verify(mLayout).onPlaybackStateChanged(eq(PlaybackListener.State.PLAYING));
     }
 
     @Test
     public void testBindTitle() {
         mCoordinator.show(/* animate= */ true);
-        mModel.set(PlayerProperties.TITLE, TITLE);
+        mSharedModel.set(PlayerProperties.TITLE, TITLE);
         verify(mLayout).setTitle(eq(TITLE));
     }
 
     @Test
     public void testBindPublisher() {
         mCoordinator.show(/* animate= */ true);
-        mModel.set(PlayerProperties.PUBLISHER, PUBLISHER);
+        mSharedModel.set(PlayerProperties.PUBLISHER, PUBLISHER);
         verify(mLayout).setPublisher(eq(PUBLISHER));
     }
 
     @Test
     public void testBindProgress() {
         mCoordinator.show(/* animate= */ true);
-        mModel.set(PlayerProperties.PROGRESS, 0.5f);
+        mSharedModel.set(PlayerProperties.PROGRESS, 0.5f);
         verify(mLayout).setProgress(eq(0.5f));
     }
-
-    @Test
-    public void testBindVisibility() {
-        mModel.set(PlayerProperties.MINI_PLAYER_VISIBILITY, VisibilityState.SHOWING);
-        verify(mLayout).updateVisibility(eq(VisibilityState.SHOWING));
-
-        mModel.set(PlayerProperties.MINI_PLAYER_ANIMATE_VISIBILITY_CHANGES, true);
-        verify(mLayout).enableAnimations(eq(true));
-    }
 }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java
index 848ad2f..7a05038 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java
@@ -4,8 +4,9 @@
 
 package org.chromium.chrome.browser.readaloud.player.mini;
 
+import android.view.View;
+
 import org.chromium.chrome.browser.browser_controls.BrowserControlsSizer;
-import org.chromium.chrome.browser.readaloud.player.PlayerProperties;
 import org.chromium.chrome.browser.readaloud.player.VisibilityState;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -14,25 +15,34 @@
     private final PropertyModel mModel;
     private final BrowserControlsSizer mBrowserControlsSizer;
 
-    MiniPlayerMediator(PropertyModel model, BrowserControlsSizer browserControlsSizer) {
-        mModel = model;
+    MiniPlayerMediator(BrowserControlsSizer browserControlsSizer) {
+        mModel =
+                new PropertyModel.Builder(Properties.ALL_KEYS)
+                        .with(Properties.VISIBILITY, VisibilityState.GONE)
+                        .with(Properties.ANDROID_VIEW_VISIBILITY, View.GONE)
+                        .with(Properties.COMPOSITED_VIEW_VISIBLE, false)
+                        .with(Properties.MEDIATOR, this)
+                        .build();
         mBrowserControlsSizer = browserControlsSizer;
-        mModel.set(PlayerProperties.MINI_PLAYER_MEDIATOR, this);
+    }
+
+    PropertyModel getModel() {
+        return mModel;
     }
 
     @VisibilityState
     int getVisibility() {
-        return mModel.get(PlayerProperties.MINI_PLAYER_VISIBILITY);
+        return mModel.get(Properties.VISIBILITY);
     }
 
     void show(boolean animate) {
-        mModel.set(PlayerProperties.MINI_PLAYER_ANIMATE_VISIBILITY_CHANGES, animate);
-        mModel.set(PlayerProperties.MINI_PLAYER_VISIBILITY, VisibilityState.SHOWING);
+        mModel.set(Properties.ANIMATE_VISIBILITY_CHANGES, animate);
+        mModel.set(Properties.VISIBILITY, VisibilityState.SHOWING);
     }
 
     void dismiss(boolean animate) {
-        mModel.set(PlayerProperties.MINI_PLAYER_ANIMATE_VISIBILITY_CHANGES, animate);
-        mModel.set(PlayerProperties.MINI_PLAYER_VISIBILITY, VisibilityState.HIDING);
+        mModel.set(Properties.ANIMATE_VISIBILITY_CHANGES, animate);
+        mModel.set(Properties.VISIBILITY, VisibilityState.HIDING);
     }
 
     /**
@@ -41,6 +51,6 @@
      * @param newState New visibility.
      */
     public void onVisibilityChanged(@VisibilityState int newState) {
-        mModel.set(PlayerProperties.MINI_PLAYER_VISIBILITY, newState);
+        mModel.set(Properties.VISIBILITY, newState);
     }
 }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediatorUnitTest.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediatorUnitTest.java
index 61cb84d..b85cc38 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediatorUnitTest.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediatorUnitTest.java
@@ -5,6 +5,9 @@
 package org.chromium.chrome.browser.readaloud.player.mini;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import android.view.View;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -15,7 +18,6 @@
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsSizer;
-import org.chromium.chrome.browser.readaloud.player.PlayerProperties;
 import org.chromium.chrome.browser.readaloud.player.VisibilityState;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -31,30 +33,29 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mModel = new PropertyModel.Builder(PlayerProperties.ALL_KEYS).build();
-        mMediator = new MiniPlayerMediator(mModel, mBrowserControlsSizer);
+        mMediator = new MiniPlayerMediator(mBrowserControlsSizer);
+        mModel = mMediator.getModel();
     }
 
     @Test
-    public void testPlaceSelfInModel() {
-        assertEquals(mMediator, mModel.get(PlayerProperties.MINI_PLAYER_MEDIATOR));
+    public void testInitialModelState() {
+        assertEquals(VisibilityState.GONE, mModel.get(Properties.VISIBILITY));
+        assertEquals(View.GONE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY));
+        assertFalse(mModel.get(Properties.COMPOSITED_VIEW_VISIBLE));
+        assertEquals(mMediator, mModel.get(Properties.MEDIATOR));
     }
 
     @Test
     public void testShow() {
         mMediator.show(/* animate= */ false);
-        assertEquals(
-                false,
-                (boolean) mModel.get(PlayerProperties.MINI_PLAYER_ANIMATE_VISIBILITY_CHANGES));
+        assertFalse(mModel.get(Properties.ANIMATE_VISIBILITY_CHANGES));
         assertEquals(VisibilityState.SHOWING, mMediator.getVisibility());
     }
 
     @Test
     public void testDismiss() {
         mMediator.dismiss(/* animate= */ false);
-        assertEquals(
-                false,
-                (boolean) mModel.get(PlayerProperties.MINI_PLAYER_ANIMATE_VISIBILITY_CHANGES));
+        assertFalse(mModel.get(Properties.ANIMATE_VISIBILITY_CHANGES));
         assertEquals(VisibilityState.HIDING, mMediator.getVisibility());
     }
 }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerViewBinder.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerViewBinder.java
index 789d230..1c13522ec 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerViewBinder.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerViewBinder.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.readaloud.player.mini;
 
+import org.chromium.chrome.browser.readaloud.ReadAloudMiniPlayerSceneLayer;
 import org.chromium.chrome.browser.readaloud.player.PlayerProperties;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -13,22 +14,23 @@
  * based on model state.
  */
 public class MiniPlayerViewBinder {
+    static class ViewHolder {
+        public MiniPlayerLayout view;
+        public ReadAloudMiniPlayerSceneLayer sceneLayer;
+
+        ViewHolder(MiniPlayerLayout view, ReadAloudMiniPlayerSceneLayer sceneLayer) {
+            this.view = view;
+            this.sceneLayer = sceneLayer;
+        }
+    }
+
     /**
-     * Called by {@link PropertyModelChangeProcessor} on creation and each time the
-     * model is updated.
+     * Called by {@link PropertyModelChangeProcessor} on creation and each time the model is
+     * updated.
      */
-    public static void bind(PropertyModel model, MiniPlayerLayout view, PropertyKey key) {
-        if (key == PlayerProperties.MINI_PLAYER_VISIBILITY) {
-            view.updateVisibility(model.get(PlayerProperties.MINI_PLAYER_VISIBILITY));
-
-        } else if (key == PlayerProperties.MINI_PLAYER_ANIMATE_VISIBILITY_CHANGES) {
-            view.enableAnimations(
-                    model.get(PlayerProperties.MINI_PLAYER_ANIMATE_VISIBILITY_CHANGES));
-
-        } else if (key == PlayerProperties.MINI_PLAYER_MEDIATOR) {
-            view.setMediator(model.get(PlayerProperties.MINI_PLAYER_MEDIATOR));
-
-        } else if (key == PlayerProperties.TITLE) {
+    public static void bindPlayerProperties(
+            PropertyModel model, MiniPlayerLayout view, PropertyKey key) {
+        if (key == PlayerProperties.TITLE) {
             view.setTitle(model.get(PlayerProperties.TITLE));
 
         } else if (key == PlayerProperties.PUBLISHER) {
@@ -44,4 +46,23 @@
             view.setInteractionHandler(model.get(PlayerProperties.INTERACTION_HANDLER));
         }
     }
+
+    public static void bindMiniPlayerProperties(
+            PropertyModel model, ViewHolder viewHolder, PropertyKey key) {
+        if (key == Properties.VISIBILITY) {
+            viewHolder.view.updateVisibility(model.get(Properties.VISIBILITY));
+
+        } else if (key == Properties.ANIMATE_VISIBILITY_CHANGES) {
+            viewHolder.view.enableAnimations(model.get(Properties.ANIMATE_VISIBILITY_CHANGES));
+
+        } else if (key == Properties.MEDIATOR) {
+            viewHolder.view.setMediator(model.get(Properties.MEDIATOR));
+
+        } else if (key == Properties.ANDROID_VIEW_VISIBILITY) {
+            viewHolder.view.setVisibility(model.get(Properties.ANDROID_VIEW_VISIBILITY));
+
+        } else if (key == Properties.COMPOSITED_VIEW_VISIBLE) {
+            viewHolder.sceneLayer.setIsVisible(model.get(Properties.COMPOSITED_VIEW_VISIBLE));
+        }
+    }
 }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/Properties.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/Properties.java
new file mode 100644
index 0000000..fda7fa0
--- /dev/null
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/Properties.java
@@ -0,0 +1,36 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.readaloud.player.mini;
+
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
+import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
+import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
+
+/** UI property keys specific to the mini player. */
+class Properties {
+    // VisibilityState for signaling the progress of transitions for the player as a whole.
+    public static final WritableIntPropertyKey VISIBILITY = new WritableIntPropertyKey();
+    public static final WritableBooleanPropertyKey ANIMATE_VISIBILITY_CHANGES =
+            new WritableBooleanPropertyKey();
+    public static final WritableObjectPropertyKey<MiniPlayerMediator> MEDIATOR =
+            new WritableObjectPropertyKey<>();
+    // View visibility of the mini player Android view.
+    public static final WritableIntPropertyKey ANDROID_VIEW_VISIBILITY =
+            new WritableIntPropertyKey();
+    // Whether to draw the composited view.
+    public static final WritableBooleanPropertyKey COMPOSITED_VIEW_VISIBLE =
+            new WritableBooleanPropertyKey();
+    public static final WritableBooleanPropertyKey CONTENTS_OPAQUE =
+            new WritableBooleanPropertyKey();
+    public static final PropertyKey[] ALL_KEYS = {
+        VISIBILITY,
+        ANIMATE_VISIBILITY_CHANGES,
+        MEDIATOR,
+        ANDROID_VIEW_VISIBILITY,
+        COMPOSITED_VIEW_VISIBLE,
+        CONTENTS_OPAQUE,
+    };
+}
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
index 61dfeca..e5edccd 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
@@ -306,6 +306,23 @@
   }
 }
 
+bool HasDecryptionFailedResult(
+    enterprise_connectors::ContentAnalysisResponse response) {
+  for (const auto& result : response.results()) {
+    if (result.tag() != "malware") {
+      continue;
+    }
+
+    if (result.status_error_message() ==
+        enterprise_connectors::ContentAnalysisResponse::Result::
+            DECRYPTION_FAILED) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 }  // namespace
 
 /* static */
@@ -598,9 +615,16 @@
     const base::FilePath& current_path,
     BinaryUploadService::Result result,
     enterprise_connectors::ContentAnalysisResponse response) {
+  bool is_invalid_password =
+      result == BinaryUploadService::Result::FILE_ENCRYPTED ||
+      (result == BinaryUploadService::Result::SUCCESS &&
+       DownloadItemWarningData::IsEncryptedArchive(item_) &&
+       HasDecryptionFailedResult(response));
+  bool is_success =
+      result == BinaryUploadService::Result::SUCCESS && !is_invalid_password;
   CHECK_EQ(trigger_, DeepScanTrigger::TRIGGER_CONSUMER_PROMPT);
   DownloadCheckResult download_result = DownloadCheckResult::UNKNOWN;
-  if (result == BinaryUploadService::Result::SUCCESS) {
+  if (is_success) {
     request_tokens_.push_back(response.request_token());
     ResponseToDownloadCheckResult(response, &download_result);
     LogDeepScanEvent(item_, DeepScanEvent::kScanCompleted);
@@ -609,7 +633,7 @@
     LogDeepScanEvent(item_, DeepScanEvent::kScanFailed);
 
     if (base::FeatureList::IsEnabled(kDeepScanningEncryptedArchives) &&
-        result == BinaryUploadService::Result::FILE_ENCRYPTED) {
+        is_invalid_password) {
       // Since we now prompt the user for a password, FILE_ENCRYPTED indicates
       // the password was not correct. Instead of failing, ask the user to
       // correct the issue.
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
index fdb7c571..29a6f3c 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
 #include "chrome/browser/download/download_core_service.h"
 #include "chrome/browser/download/download_core_service_factory.h"
+#include "chrome/browser/download/download_item_warning_data.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/enterprise/connectors/common.h"
 #include "chrome/browser/enterprise/connectors/connectors_prefs.h"
@@ -1156,6 +1157,141 @@
   }
 }
 
+TEST_F(DeepScanningReportingTest, ConsumerEncryptedArchiveSuccess) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(kDeepScanningEncryptedArchives);
+
+  base::RunLoop run_loop;
+  DeepScanningRequest request(
+      &item_, DeepScanningRequest::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT,
+      DownloadCheckResult::SAFE,
+      base::BindRepeating(
+          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
+             DownloadCheckResult result) {
+            test->SetLastResult(result);
+            if (result != DownloadCheckResult::ASYNC_SCANNING) {
+              quit_closure.Run();
+            }
+          },
+          base::Unretained(this), run_loop.QuitClosure()),
+      &download_protection_service_, settings().value(),
+      /*password=*/absl::nullopt);
+
+  enterprise_connectors::ContentAnalysisResponse response;
+  response.set_request_token(kScanId);
+
+  auto* malware_result = response.add_results();
+  malware_result->set_tag("malware");
+  malware_result->set_status(
+      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
+
+  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
+      download_path_, BinaryUploadService::Result::SUCCESS, response);
+  download_protection_service_.GetFakeBinaryUploadService()
+      ->SetExpectedFinalAction(
+          enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);
+
+  DownloadItemWarningData::SetIsEncryptedArchive(&item_, true);
+  EXPECT_FALSE(DownloadItemWarningData::HasIncorrectPassword(&item_));
+
+  request.Start();
+
+  run_loop.Run();
+
+  EXPECT_FALSE(DownloadItemWarningData::HasIncorrectPassword(&item_));
+}
+
+TEST_F(DeepScanningReportingTest, ConsumerEncryptedArchiveFailed) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(kDeepScanningEncryptedArchives);
+
+  base::RunLoop run_loop;
+  DeepScanningRequest request(
+      &item_, DeepScanningRequest::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT,
+      DownloadCheckResult::SAFE,
+      base::BindRepeating(
+          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
+             DownloadCheckResult result) {
+            test->SetLastResult(result);
+            if (result != DownloadCheckResult::ASYNC_SCANNING) {
+              quit_closure.Run();
+            }
+          },
+          base::Unretained(this), run_loop.QuitClosure()),
+      &download_protection_service_, settings().value(),
+      /*password=*/absl::nullopt);
+
+  enterprise_connectors::ContentAnalysisResponse response;
+  response.set_request_token(kScanId);
+
+  auto* malware_result = response.add_results();
+  malware_result->set_tag("malware");
+  malware_result->set_status(
+      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
+  malware_result->set_status_error_message(
+      enterprise_connectors::ContentAnalysisResponse::Result::
+          DECRYPTION_FAILED);
+
+  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
+      download_path_, BinaryUploadService::Result::SUCCESS, response);
+  download_protection_service_.GetFakeBinaryUploadService()
+      ->SetExpectedFinalAction(
+          enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);
+
+  DownloadItemWarningData::SetIsEncryptedArchive(&item_, true);
+  EXPECT_FALSE(DownloadItemWarningData::HasIncorrectPassword(&item_));
+
+  request.Start();
+
+  run_loop.Run();
+
+  EXPECT_TRUE(DownloadItemWarningData::HasIncorrectPassword(&item_));
+}
+
+TEST_F(DeepScanningReportingTest, ConsumerUnencryptedArchive) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(kDeepScanningEncryptedArchives);
+
+  base::RunLoop run_loop;
+  DeepScanningRequest request(
+      &item_, DeepScanningRequest::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT,
+      DownloadCheckResult::SAFE,
+      base::BindRepeating(
+          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
+             DownloadCheckResult result) {
+            test->SetLastResult(result);
+            if (result != DownloadCheckResult::ASYNC_SCANNING) {
+              quit_closure.Run();
+            }
+          },
+          base::Unretained(this), run_loop.QuitClosure()),
+      &download_protection_service_, settings().value(),
+      /*password=*/absl::nullopt);
+
+  enterprise_connectors::ContentAnalysisResponse response;
+  response.set_request_token(kScanId);
+
+  auto* malware_result = response.add_results();
+  malware_result->set_tag("malware");
+  malware_result->set_status(
+      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
+
+  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
+      download_path_, BinaryUploadService::Result::SUCCESS, response);
+  download_protection_service_.GetFakeBinaryUploadService()
+      ->SetExpectedFinalAction(
+          enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);
+
+  DownloadItemWarningData::SetIsEncryptedArchive(&item_, false);
+  EXPECT_FALSE(DownloadItemWarningData::HasIncorrectPassword(&item_));
+
+  request.Start();
+
+  run_loop.Run();
+
+  EXPECT_FALSE(DownloadItemWarningData::HasIncorrectPassword(&item_));
+}
+
 TEST_F(DeepScanningReportingTest, MultipleFiles) {
   {
     enterprise_connectors::ContentAnalysisResponse response;
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc
index c373374..73942c3 100644
--- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc
+++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc
@@ -231,6 +231,50 @@
   }
 }
 
+// Checks for extensions specified in the -load-extension commandline switch.
+// Creates and returns a set of extension objects for such extensions.
+// NOTE: These extensions are not installed - the information is only collected
+// for telemetry purposes.
+// This function is executed on a separate thread from the UI thread since it
+// involves reading the manifest files from disk.
+extensions::ExtensionSet CollectCommandLineExtensionInfo() {
+  extensions::ExtensionSet commandline_extensions;
+
+  // If there are no commandline extensions, return an empty set.
+  base::CommandLine* cmdline(base::CommandLine::ForCurrentProcess());
+  if (!cmdline || !cmdline->HasSwitch(extensions::switches::kLoadExtension)) {
+    return commandline_extensions;
+  }
+
+  // Otherwise, create an extension object for each extension specified in the
+  // commandline. Note that the extension is not installed.
+  base::CommandLine::StringType path_list =
+      cmdline->GetSwitchValueNative(extensions::switches::kLoadExtension);
+  base::StringTokenizerT<base::CommandLine::StringType,
+                         base::CommandLine::StringType::const_iterator>
+      t(path_list, FILE_PATH_LITERAL(","));
+
+  while (t.GetNext()) {
+    auto tmp_path = extensions::path_util::ResolveHomeDirectory(
+        base::FilePath(t.token_piece()));
+    auto extension_path = base::MakeAbsoluteFilePath(tmp_path);
+    std::string error;
+    // Use default creation flags. Since we are not installing the extension,
+    // it doesn't really mattter.
+    int flags = extensions::Extension::FOLLOW_SYMLINKS_ANYWHERE |
+                extensions::Extension::ALLOW_FILE_ACCESS |
+                extensions::Extension::REQUIRE_MODERN_MANIFEST_VERSION;
+    scoped_refptr<extensions::Extension> extension =
+        extensions::file_util::LoadExtension(
+            extension_path, ManifestLocation::kCommandLine, flags, &error);
+    if (error.empty()) {
+      commandline_extensions.Insert(extension);
+    }
+  }
+
+  return commandline_extensions;
+}
+
 }  // namespace
 
 ExtensionTelemetryService::~ExtensionTelemetryService() = default;
@@ -364,6 +408,15 @@
           FROM_HERE,
           base::Seconds(kExtensionTelemetryFileDataStartupDelaySeconds.Get()),
           this, &ExtensionTelemetryService::StartOffstoreFileDataCollection);
+      if (base::FeatureList::IsEnabled(
+              kExtensionTelemetryFileDataForCommandLineExtensions)) {
+        base::ThreadPool::PostTaskAndReplyWithResult(
+            FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+            base::BindOnce(CollectCommandLineExtensionInfo),
+            base::BindOnce(&ExtensionTelemetryService::
+                               OnCommandLineExtensionsInfoCollected,
+                           weak_factory_.GetWeakPtr()));
+      }
     }
 
     if (current_reporting_interval_.is_positive()) {
@@ -1054,47 +1107,11 @@
   CollectOffstoreFileData();
 }
 
-void ExtensionTelemetryService::CollectCommandLineExtensionInfo() {
-  if (!base::FeatureList::IsEnabled(
-          kExtensionTelemetryFileDataForCommandLineExtensions)) {
-    return;
-  }
-
-  // Only collect commandline extension information once.
-  if (collected_commandline_extension_info_) {
-    return;
-  }
-  collected_commandline_extension_info_ = true;
-
-  // If there are no commandline extensions, do nothing.
-  base::CommandLine* cmdline(base::CommandLine::ForCurrentProcess());
-  if (!cmdline || !cmdline->HasSwitch(extensions::switches::kLoadExtension)) {
-    return;
-  }
-
-  // Otherwise, store an extension object for each extension specified in the
-  // commandline. Note that the extension is not installed.
-  base::CommandLine::StringType path_list =
-      cmdline->GetSwitchValueNative(extensions::switches::kLoadExtension);
-  base::StringTokenizerT<base::CommandLine::StringType,
-                         base::CommandLine::StringType::const_iterator>
-      t(path_list, FILE_PATH_LITERAL(","));
-  while (t.GetNext()) {
-    auto tmp_path = extensions::path_util::ResolveHomeDirectory(
-        base::FilePath(t.token_piece()));
-    auto extension_path = base::MakeAbsoluteFilePath(tmp_path);
-    std::string error;
-    // Use default creation flags. Since we are not installing the extension,
-    // it doesn't really mattter.
-    int flags = extensions::Extension::FOLLOW_SYMLINKS_ANYWHERE |
-                extensions::Extension::ALLOW_FILE_ACCESS |
-                extensions::Extension::REQUIRE_MODERN_MANIFEST_VERSION;
-    scoped_refptr<extensions::Extension> extension =
-        extensions::file_util::LoadExtension(
-            extension_path, ManifestLocation::kCommandLine, flags, &error);
-    if (error.empty()) {
-      commandline_extensions_.Insert(extension);
-    }
+void ExtensionTelemetryService::OnCommandLineExtensionsInfoCollected(
+    extensions::ExtensionSet commandline_extensions) {
+  if (enabled_) {
+    // Only store this information if the telemetry service is enabled.
+    commandline_extensions_ = std::move(commandline_extensions);
   }
 }
 
@@ -1110,8 +1127,9 @@
   }
 
   // Also add any extensions that were part of the --load-extension commandline
-  // switch if applicable.
-  CollectCommandLineExtensionInfo();
+  // switch if applicable. The information about these extensions is collected
+  // (only one time) off-thread using `CollectCommandLineExtensionsInfo` when
+  // the extension telemetry service is enabled.
   for (const auto& extension : commandline_extensions_) {
     offstore_extension_dirs_[extension->id()] = extension->path();
   }
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h
index bbfc48a..33677132 100644
--- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h
+++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h
@@ -155,10 +155,15 @@
   // uploads telemetry data. Runs on a delayed post task on startup.
   void StartUploadCheck();
 
-  // Collects information about any extensions present in the Chrome command
-  // line switch, --load-extension. Only creates an extension object to store
-  // this information without actually installing the extension.
-  void CollectCommandLineExtensionInfo();
+  // Callback used to receive information about any extensions present in
+  // the Chrome command line switch, --load-extension. The information is
+  // collected off the UI thread since it involves reading the manifest file of
+  // the extension. The callback stores the received information, a set of
+  // extension objects, in `commandline_extensions_`.
+  // NOTE: The extension objects are created without actually installing the
+  // extensions.
+  void OnCommandLineExtensionsInfoCollected(
+      extensions::ExtensionSet commandline_extensions);
 
   // Searches for offstore extensions, collects file data such as
   // hashes/manifest content, and saves the data to PrefService. Repeats every 2
diff --git a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
index 110dc6bb..2d91a8c 100644
--- a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
+++ b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
@@ -435,6 +435,10 @@
       false /* expect cert status error */);
 }
 
+// TODO(https://crbug.com/1477317): Add an end-to-end test for
+// security_state::SECURE_WITH_POLICY_INSTALLED_CERT (currently that depends on
+// a cros-specific policy/service).
+
 IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTest, DevToolsPage) {
   GURL devtools_url("devtools://devtools/bundled/");
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), devtools_url));
diff --git a/chrome/browser/ui/ash/game_dashboard/chrome_game_dashboard_delegate.cc b/chrome/browser/ui/ash/game_dashboard/chrome_game_dashboard_delegate.cc
index 2134373..6b9be13 100644
--- a/chrome/browser/ui/ash/game_dashboard/chrome_game_dashboard_delegate.cc
+++ b/chrome/browser/ui/ash/game_dashboard/chrome_game_dashboard_delegate.cc
@@ -5,8 +5,13 @@
 #include "chrome/browser/ui/ash/game_dashboard/chrome_game_dashboard_delegate.h"
 
 #include "ash/components/arc/session/connection_holder.h"
+#include "ash/public/cpp/multi_user_window_manager.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/scalable_iph/scalable_iph_factory.h"
+#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h"
+#include "chromeos/ash/components/scalable_iph/scalable_iph.h"
+#include "components/user_manager/user_manager.h"
 
 ChromeGameDashboardDelegate::ChromeGameDashboardDelegate() {}
 
@@ -54,6 +59,38 @@
   return app_info->name;
 }
 
+void ChromeGameDashboardDelegate::RecordGameWindowOpenedEvent(
+    aura::Window* window) {
+  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
+  CHECK(user_manager);
+  if (user_manager->GetActiveUser() != user_manager->GetPrimaryUser()) {
+    return;
+  }
+
+  ash::MultiUserWindowManager* multi_user_window_manager =
+      MultiUserWindowManagerHelper::GetWindowManager();
+  if (multi_user_window_manager) {
+    // If multi user is not enabled, `MultiUserWindowManagerStub` is set. It
+    // returns an invalid account id.
+    const AccountId& account_id =
+        multi_user_window_manager->GetWindowOwner(window);
+    if (account_id.is_valid() &&
+        user_manager->GetPrimaryUser()->GetAccountId() != account_id) {
+      return;
+    }
+  }
+
+  Profile* profile = ProfileManager::GetPrimaryUserProfile();
+  CHECK(profile);
+
+  scalable_iph::ScalableIph* scalable_iph =
+      ScalableIphFactory::GetForBrowserContext(profile);
+  if (scalable_iph) {
+    scalable_iph->RecordEvent(
+        scalable_iph::ScalableIph::Event::kGameWindowOpened);
+  }
+}
+
 void ChromeGameDashboardDelegate::OnReceiveAppCategory(
     IsGameCallback callback,
     arc::mojom::AppCategory category) {
diff --git a/chrome/browser/ui/ash/game_dashboard/chrome_game_dashboard_delegate.h b/chrome/browser/ui/ash/game_dashboard/chrome_game_dashboard_delegate.h
index 47d9b68..8e916af6 100644
--- a/chrome/browser/ui/ash/game_dashboard/chrome_game_dashboard_delegate.h
+++ b/chrome/browser/ui/ash/game_dashboard/chrome_game_dashboard_delegate.h
@@ -8,6 +8,7 @@
 #include "ash/components/arc/mojom/app.mojom-shared.h"
 #include "ash/game_dashboard/game_dashboard_delegate.h"
 #include "base/memory/weak_ptr.h"
+#include "ui/aura/window.h"
 
 class ChromeGameDashboardDelegate : public ash::GameDashboardDelegate {
  public:
@@ -20,6 +21,7 @@
   // ash::GameDashboardDelegate:
   void GetIsGame(const std::string& app_id, IsGameCallback callback) override;
   std::string GetArcAppName(const std::string& app_id) const override;
+  void RecordGameWindowOpenedEvent(aura::Window* window) override;
 
  private:
   // Callback when `IsGame` queries ARC to get the app category.
diff --git a/chrome/browser/ui/cocoa/accelerators_cocoa.mm b/chrome/browser/ui/cocoa/accelerators_cocoa.mm
index 243f90e6..a02d8ae 100644
--- a/chrome/browser/ui/cocoa/accelerators_cocoa.mm
+++ b/chrome/browser/ui/cocoa/accelerators_cocoa.mm
@@ -69,7 +69,7 @@
     // The key combinations for IDC_CLOSE_WINDOW and IDC_CLOSE_TAB are context
     // dependent. A static mapping doesn't make sense. :(
     {IDC_CLOSE_TAB, ui::EF_COMMAND_DOWN, ui::VKEY_W},
-    {IDC_CLOSE_WINDOW, ui::EF_COMMAND_DOWN, ui::VKEY_W},
+    {IDC_CLOSE_WINDOW, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN, ui::VKEY_W},
 
     {IDC_EMAIL_PAGE_LOCATION, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN,
      ui::VKEY_I},
diff --git a/chrome/browser/ui/tabs/organization/request_factory.cc b/chrome/browser/ui/tabs/organization/request_factory.cc
index aa0d5fe..b3441a2 100644
--- a/chrome/browser/ui/tabs/organization/request_factory.cc
+++ b/chrome/browser/ui/tabs/organization/request_factory.cc
@@ -26,6 +26,13 @@
 
 namespace {
 
+bool CanUseOptimizationGuide(Profile* profile) {
+  return OptimizationGuideKeyedServiceFactory::GetForProfile(profile) &&
+         profile->IsOffTheRecord() &&
+         base::FeatureList::IsEnabled(
+             optimization_guide::features::kOptimizationGuideModelExecution);
+}
+
 void OnTabOrganizationModelExecutionResult(
     TabOrganizationRequest::BackendCompletionCallback on_completion,
     TabOrganizationRequest::BackendFailureCallback on_failure,
@@ -69,11 +76,8 @@
     const TabOrganizationRequest* request,
     TabOrganizationRequest::BackendCompletionCallback on_completion,
     TabOrganizationRequest::BackendFailureCallback on_failure) {
-  OptimizationGuideKeyedService* optimization_guide_keyed_service =
-      OptimizationGuideKeyedServiceFactory::GetForProfile(profile);
-  if (!optimization_guide_keyed_service || profile->IsOffTheRecord() ||
-      !base::FeatureList::IsEnabled(
-          optimization_guide::features::kOptimizationGuideModelExecution)) {
+  if (!CanUseOptimizationGuide(profile)) {
+    std::move(on_failure).Run();
     return;
   }
 
@@ -89,6 +93,8 @@
     tab->set_url(tab_data->original_url().spec());
   }
 
+  OptimizationGuideKeyedService* optimization_guide_keyed_service =
+      OptimizationGuideKeyedServiceFactory::GetForProfile(profile);
   optimization_guide_keyed_service->ExecuteModel(
       optimization_guide::proto::ModelExecutionFeature::
           MODEL_EXECUTION_FEATURE_TAB_ORGANIZATION,
@@ -103,11 +109,8 @@
 
 // static
 std::unique_ptr<TabOrganizationRequestFactory>
-TabOrganizationRequestFactory::Get() {
-  const base::CommandLine* const command_line =
-      base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(optimization_guide::switches::
-                                  kOptimizationGuideServiceModelExecutionURL)) {
+TabOrganizationRequestFactory::GetForProfile(Profile* profile) {
+  if (CanUseOptimizationGuide(profile)) {
     return std::make_unique<OptimizationGuideTabOrganizationRequestFactory>();
   }
   return std::make_unique<TwoTabsRequestFactory>();
diff --git a/chrome/browser/ui/tabs/organization/request_factory.h b/chrome/browser/ui/tabs/organization/request_factory.h
index c4e0057c..ed63197 100644
--- a/chrome/browser/ui/tabs/organization/request_factory.h
+++ b/chrome/browser/ui/tabs/organization/request_factory.h
@@ -16,7 +16,8 @@
   virtual std::unique_ptr<TabOrganizationRequest> CreateRequest(
       Profile* profile) = 0;
 
-  static std::unique_ptr<TabOrganizationRequestFactory> Get();
+  static std::unique_ptr<TabOrganizationRequestFactory> GetForProfile(
+      Profile* profile);
 };
 
 class TwoTabsRequestFactory : public TabOrganizationRequestFactory {
diff --git a/chrome/browser/ui/tabs/organization/tab_organization_session.cc b/chrome/browser/ui/tabs/organization/tab_organization_session.cc
index 439d21c..4b1b440 100644
--- a/chrome/browser/ui/tabs/organization/tab_organization_session.cc
+++ b/chrome/browser/ui/tabs/organization/tab_organization_session.cc
@@ -44,7 +44,8 @@
     const Browser* browser,
     const TabOrganizationService* service) {
   std::unique_ptr<TabOrganizationRequest> request =
-      TabOrganizationRequestFactory::Get()->CreateRequest(browser->profile());
+      TabOrganizationRequestFactory::GetForProfile(browser->profile())
+          ->CreateRequest(browser->profile());
 
   // iterate through the tabstripmodel building the tab data.
   std::vector<std::unique_ptr<TabData>> tab_datas;
diff --git a/chrome/browser/ui/tabs/tab_menu_model.cc b/chrome/browser/ui/tabs/tab_menu_model.cc
index 0df4322..26c1bd9 100644
--- a/chrome/browser/ui/tabs/tab_menu_model.cc
+++ b/chrome/browser/ui/tabs/tab_menu_model.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h"
 #include "chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h"
 #include "chrome/browser/ui/tabs/existing_window_sub_menu_model.h"
+#include "chrome/browser/ui/tabs/organization/tab_organization_service_factory.h"
 #include "chrome/browser/ui/tabs/tab_menu_model_delegate.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
@@ -147,9 +148,13 @@
   }
 
   if (features::IsTabOrganization()) {
-    AddItemWithStringId(TabStripModel::CommandOrganizeTabs,
-                        IDS_TAB_CXMENU_ORGANIZE_TABS);
-    SetIsNewFeatureAt(GetItemCount() - 1, true);
+    auto* const tab_organization_service =
+        TabOrganizationServiceFactory::GetForProfile(tab_strip->profile());
+    if (tab_organization_service) {
+      AddItemWithStringId(TabStripModel::CommandOrganizeTabs,
+                          IDS_TAB_CXMENU_ORGANIZE_TABS);
+      SetIsNewFeatureAt(GetItemCount() - 1, true);
+    }
   }
 
   AddSeparator(ui::NORMAL_SEPARATOR);
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index 63719d2..38d95115 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -55,6 +55,7 @@
 #include "chrome/browser/ui/profiles/profile_view_utils.h"
 #include "chrome/browser/ui/safety_hub/menu_notification_service_factory.h"
 #include "chrome/browser/ui/side_panel/companion/companion_utils.h"
+#include "chrome/browser/ui/tabs/organization/tab_organization_service_factory.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/toolbar/app_menu_icon_controller.h"
 #include "chrome/browser/ui/toolbar/bookmark_sub_menu_model.h"
@@ -1632,8 +1633,12 @@
     }
 #endif
     if (features::IsTabOrganization()) {
-      AddItemWithStringId(IDC_ORGANIZE_TABS, IDS_TAB_ORGANIZE_MENU);
-      SetIsNewFeatureAt(GetIndexOfCommandId(IDC_ORGANIZE_TABS).value(), true);
+      auto* const tab_organization_service =
+          TabOrganizationServiceFactory::GetForProfile(browser_->profile());
+      if (tab_organization_service) {
+        AddItemWithStringId(IDC_ORGANIZE_TABS, IDS_TAB_ORGANIZE_MENU);
+        SetIsNewFeatureAt(GetIndexOfCommandId(IDC_ORGANIZE_TABS).value(), true);
+      }
     }
 
     AddItemWithStringId(IDC_SHOW_TRANSLATE, IDS_SHOW_TRANSLATE);
diff --git a/chrome/browser/ui/views/autofill/popup/popup_cell_view.cc b/chrome/browser/ui/views/autofill/popup/popup_cell_view.cc
index d7031a8..92c8b91 100644
--- a/chrome/browser/ui/views/autofill/popup/popup_cell_view.cc
+++ b/chrome/browser/ui/views/autofill/popup/popup_cell_view.cc
@@ -35,12 +35,6 @@
 
 PopupCellView::~PopupCellView() = default;
 
-bool PopupCellView::HandleKeyPressEvent(
-    const content::NativeWebKeyboardEvent& event) {
-  // TODO(1491373): Remove when PopupCellWithButtonView gets reworked as a row.
-  return false;
-}
-
 void PopupCellView::SetSelected(bool selected) {
   if (selected_ == selected) {
     return;
diff --git a/chrome/browser/ui/views/autofill/popup/popup_cell_view.h b/chrome/browser/ui/views/autofill/popup/popup_cell_view.h
index 13c84f2..12aa95e 100644
--- a/chrome/browser/ui/views/autofill/popup/popup_cell_view.h
+++ b/chrome/browser/ui/views/autofill/popup/popup_cell_view.h
@@ -20,10 +20,6 @@
 #include "ui/views/metadata/view_factory.h"
 #include "ui/views/view.h"
 
-namespace content {
-struct NativeWebKeyboardEvent;
-}  // namespace content
-
 namespace views {
 class Label;
 }  // namespace views
@@ -55,11 +51,6 @@
   // labels contained in it based on the selection status of the view.
   void RefreshStyle();
 
-  // Attempts to process a key press `event`. Returns true if it did (and the
-  // parent no longer needs to handle it).
-  virtual bool HandleKeyPressEvent(
-      const content::NativeWebKeyboardEvent& event);
-
  protected:
   // The selection state.
   bool selected_ = false;
diff --git a/chrome/browser/ui/views/autofill/popup/popup_row_strategy_unittest.cc b/chrome/browser/ui/views/autofill/popup/popup_row_strategy_unittest.cc
index b81b404..6e63e55f 100644
--- a/chrome/browser/ui/views/autofill/popup/popup_row_strategy_unittest.cc
+++ b/chrome/browser/ui/views/autofill/popup/popup_row_strategy_unittest.cc
@@ -157,14 +157,6 @@
     ChromeViewsTestBase::TearDown();
   }
 
-  void SimulateKeyPress(int windows_key_code) {
-    content::NativeWebKeyboardEvent event(
-        blink::WebKeyboardEvent::Type::kRawKeyDown,
-        blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
-    event.windows_key_code = windows_key_code;
-    view().HandleKeyPressEvent(event);
-  }
-
   void ShowSuggestion(Suggestion suggestion) {
     // Show the button.
     controller().set_suggestions({std::move(suggestion)});
diff --git a/chrome/browser/ui/views/autofill/popup/popup_row_view_unittest.cc b/chrome/browser/ui/views/autofill/popup/popup_row_view_unittest.cc
index 72a7b05a..008f1a3 100644
--- a/chrome/browser/ui/views/autofill/popup/popup_row_view_unittest.cc
+++ b/chrome/browser/ui/views/autofill/popup/popup_row_view_unittest.cc
@@ -52,14 +52,6 @@
 
 constexpr gfx::Point kOutOfBounds{1000, 1000};
 
-class MockPopupCellView : public PopupCellView {
- public:
-  MOCK_METHOD(bool,
-              HandleKeyPressEvent,
-              (const content::NativeWebKeyboardEvent& event),
-              (override));
-};
-
 class MockingTestPopupRowStrategy : public TestPopupRowStrategy {
  public:
   explicit MockingTestPopupRowStrategy(int line_number)
@@ -67,17 +59,8 @@
   ~MockingTestPopupRowStrategy() override = default;
 
   std::unique_ptr<PopupCellView> CreateContent() override {
-    auto content_cell = std::make_unique<NiceMock<MockPopupCellView>>();
-    last_created_mock_content_cell_ = content_cell.get();
-    return content_cell;
+    return std::make_unique<PopupCellView>();
   }
-
-  MockPopupCellView* last_created_content_cell() {
-    return last_created_mock_content_cell_;
-  }
-
- private:
-  raw_ptr<MockPopupCellView> last_created_mock_content_cell_ = nullptr;
 };
 
 }  // namespace
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 66303a1b..f622760 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -896,33 +896,10 @@
 
   SetProperty(views::kElementIdentifierKey, kBrowserViewElementId);
 
-  // In order to do feature promos, the browser must have a UI and not be an
-  // "off-the-record" or in a demo or guest mode.
-  bool is_profile_type_without_iph =
-      GetIncognito() || GetGuestSession() || IsManagedGuestSession() ||
-      profiles::IsDemoSession() || profiles::IsChromeAppKioskSession();
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  is_profile_type_without_iph |= profiles::IsWebKioskSession();
-#endif
-  if (!headless::IsHeadlessMode() && !is_profile_type_without_iph) {
-    if (UserEducationService* const user_education_service =
-            UserEducationServiceFactory::GetForBrowserContext(GetProfile())) {
-      RegisterChromeHelpBubbleFactories(
-          user_education_service->help_bubble_factory_registry());
-      MaybeRegisterChromeFeaturePromos(
-          user_education_service->feature_promo_registry());
-      MaybeRegisterChromeTutorials(user_education_service->tutorial_registry());
-      feature_promo_controller_ =
-          std::make_unique<BrowserFeaturePromoController>(
-              this,
-              feature_engagement::TrackerFactory::GetForBrowserContext(
-                  GetProfile()),
-              &user_education_service->feature_promo_registry(),
-              &user_education_service->help_bubble_factory_registry(),
-              &user_education_service->feature_promo_storage_service(),
-              &user_education_service->tutorial_service());
-    }
-  }
+  // Not all browsers do feature promos. Conditionally create one (or don't) for
+  // this browser window.
+  feature_promo_controller_ =
+      BrowserFeaturePromoController::MaybeCreateForBrowserView(this);
 
   browser_->tab_strip_model()->AddObserver(this);
   immersive_mode_controller_ = chrome::CreateImmersiveModeController(this);
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
index 7b4ffde1..f4a7ccdb 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
@@ -386,6 +386,8 @@
         media_router::ChromeMediaRouterFactory::GetInstance()
             ->SetTestingFactoryAndUse(
                 context, base::BindRepeating(&TestMediaRouter::Create)));
+    ON_CALL(*media_router_, RegisterMediaSinksObserver)
+        .WillByDefault(testing::Return(true));
   }
 
   void OpenTestURL() {
diff --git a/chrome/browser/ui/views/tab_search_bubble_host.cc b/chrome/browser/ui/views/tab_search_bubble_host.cc
index cad9af2c..c1d866b 100644
--- a/chrome/browser/ui/views/tab_search_bubble_host.cc
+++ b/chrome/browser/ui/views/tab_search_bubble_host.cc
@@ -87,7 +87,9 @@
   if (features::IsTabOrganization()) {
     auto* const tab_organization_service =
         TabOrganizationServiceFactory::GetForProfile(profile_);
-    tab_organization_service->RemoveObserver(this);
+    if (tab_organization_service) {
+      tab_organization_service->RemoveObserver(this);
+    }
   }
 }
 
diff --git a/chrome/browser/ui/views/tabs/tab_search_container.cc b/chrome/browser/ui/views/tabs/tab_search_container.cc
index 8dec8d0..20a1f1f6 100644
--- a/chrome/browser/ui/views/tabs/tab_search_container.cc
+++ b/chrome/browser/ui/views/tabs/tab_search_container.cc
@@ -54,6 +54,9 @@
   if (features::IsTabOrganization()) {
     tab_organization_service_ = TabOrganizationServiceFactory::GetForProfile(
         tab_strip_controller->GetProfile());
+  }
+
+  if (tab_organization_service_) {
     tab_organization_service_->AddObserver(this);
     // TODO(1469126): Consider hiding the button when the request has started,
     // vs. when the button as clicked.
diff --git a/chrome/browser/ui/views/user_education/browser_feature_promo_controller.cc b/chrome/browser/ui/views/user_education/browser_feature_promo_controller.cc
index f225a30..e048492 100644
--- a/chrome/browser/ui/views/user_education/browser_feature_promo_controller.cc
+++ b/chrome/browser/ui/views/user_education/browser_feature_promo_controller.cc
@@ -8,13 +8,18 @@
 
 #include "base/feature_list.h"
 #include "build/build_config.h"
+#include "build/chromecast_buildflags.h"
 #include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/feature_engagement/tracker_factory.h"
+#include "chrome/browser/headless/headless_mode_util.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"
+#include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/search_engine_choice/search_engine_choice_service.h"
 #include "chrome/browser/search_engine_choice/search_engine_choice_service_factory.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/user_education/browser_user_education_service.h"
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/user_education/user_education_service.h"
 #include "chrome/browser/user_education/user_education_service_factory.h"
@@ -29,6 +34,10 @@
 #include "ui/views/view.h"
 #include "ui/views/view_utils.h"
 
+#if BUILDFLAG(IS_CHROMEOS)
+#include "chromeos/components/mgs/managed_guest_session_utils.h"
+#endif
+
 BrowserFeaturePromoController::BrowserFeaturePromoController(
     BrowserView* browser_view,
     feature_engagement::Tracker* feature_engagement_tracker,
@@ -46,6 +55,53 @@
 BrowserFeaturePromoController::~BrowserFeaturePromoController() = default;
 
 // static
+std::unique_ptr<BrowserFeaturePromoController>
+BrowserFeaturePromoController::MaybeCreateForBrowserView(
+    BrowserView* browser_view) {
+  // In order to do feature promos, the browser must have a UI and not be an
+  // "off-the-record" or in a demo or guest mode.
+  if (browser_view->GetIncognito() || browser_view->GetGuestSession() ||
+      profiles::IsDemoSession() || profiles::IsChromeAppKioskSession()) {
+    return nullptr;
+  }
+#if BUILDFLAG(IS_CHROMEOS)
+  if (chromeos::IsManagedGuestSession()) {
+    return nullptr;
+  }
+#endif
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (profiles::IsWebKioskSession()) {
+    return nullptr;
+  }
+#endif
+  if (headless::IsHeadlessMode()) {
+    return nullptr;
+  }
+
+  // Get the user education service.
+  Profile* const profile = browser_view->GetProfile();
+  UserEducationService* const user_education_service =
+      UserEducationServiceFactory::GetForBrowserContext(profile);
+  if (!user_education_service) {
+    return nullptr;
+  }
+
+  // Consider registering factories, etc.
+  RegisterChromeHelpBubbleFactories(
+      user_education_service->help_bubble_factory_registry());
+  MaybeRegisterChromeFeaturePromos(
+      user_education_service->feature_promo_registry());
+  MaybeRegisterChromeTutorials(user_education_service->tutorial_registry());
+  return std::make_unique<BrowserFeaturePromoController>(
+      browser_view,
+      feature_engagement::TrackerFactory::GetForBrowserContext(profile),
+      &user_education_service->feature_promo_registry(),
+      &user_education_service->help_bubble_factory_registry(),
+      &user_education_service->feature_promo_storage_service(),
+      &user_education_service->tutorial_service());
+}
+
+// static
 BrowserFeaturePromoController* BrowserFeaturePromoController::GetForView(
     views::View* view) {
   if (!view)
diff --git a/chrome/browser/ui/views/user_education/browser_feature_promo_controller.h b/chrome/browser/ui/views/user_education/browser_feature_promo_controller.h
index dbd648f..d09e7ea 100644
--- a/chrome/browser/ui/views/user_education/browser_feature_promo_controller.h
+++ b/chrome/browser/ui/views/user_education/browser_feature_promo_controller.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_USER_EDUCATION_BROWSER_FEATURE_PROMO_CONTROLLER_H_
 #define CHROME_BROWSER_UI_VIEWS_USER_EDUCATION_BROWSER_FEATURE_PROMO_CONTROLLER_H_
 
+#include <memory>
 #include <string>
 #include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
@@ -43,7 +44,8 @@
 class BrowserFeaturePromoController
     : public user_education::FeaturePromoControllerCommon {
  public:
-  // Create the instance for the given |browser_view|.
+  // Create the instance for the given |browser_view|. Prefer to call
+  // `MaybeCreateForBrowserView()` instead.
   BrowserFeaturePromoController(
       BrowserView* browser_view,
       feature_engagement::Tracker* feature_engagement_tracker,
@@ -53,6 +55,13 @@
       user_education::TutorialService* tutorial_service);
   ~BrowserFeaturePromoController() override;
 
+  // Creates (or doesn't create) a FeaturePromoController for the specified
+  // `browser_view`. Not all browser windows can do promos; specifically,
+  // headless, kiosk, guest, incognito, and other off-the-record browsers do
+  // _not_ show IPH.
+  static std::unique_ptr<BrowserFeaturePromoController>
+  MaybeCreateForBrowserView(BrowserView* browser_view);
+
   // Get the appropriate instance for |view|. This finds the BrowserView
   // that contains |view| and returns its instance. May return nullptr,
   // but if |view| is in a BrowserView's hierarchy it shouldn't.
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
index 22c34e8..a4bd5e3 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
@@ -10,6 +10,7 @@
 #include "base/trace_event/trace_event.h"
 #include "build/branding_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/tabs/organization/tab_organization_service_factory.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/webui/favicon_source.h"
 #include "chrome/browser/ui/webui/tab_search/tab_search_prefs.h"
@@ -132,7 +133,16 @@
       "recentlyClosedDefaultItemDisplayCount",
       features::kTabSearchRecentlyClosedDefaultItemDisplayCount.Get());
 
-  source->AddBoolean("tabOrganizationEnabled", features::IsTabOrganization());
+  bool tab_organization_enabled = false;
+  if (features::IsTabOrganization()) {
+    const auto* const tab_organization_service =
+        TabOrganizationServiceFactory::GetForProfile(profile);
+    if (tab_organization_service) {
+      tab_organization_enabled = true;
+    }
+  }
+  source->AddBoolean("tabOrganizationEnabled", tab_organization_enabled);
+
   source->AddInteger("tabIndex", TabIndex());
   source->AddBoolean("showTabOrganizationFRE", ShowTabOrganizationFRE());
 
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index bf5a715..3b0da32 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1699444736-60926cccf701d9187a814302e73b359199986ff5.profdata
+chrome-android64-main-1699465564-3513bf1d51d615a7f87cbd98d67882726dcfb373.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 72e8ba1..e7a97ac 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1699444736-9467b46c437631398d51080bb0afe0bc7937c78c.profdata
+chrome-linux-main-1699465564-fd832a282a2ad9f7f89d22dc3a2cfc626afe0460.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 59087c8..bc21fde 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1699427989-669249ef4c5d2522241eb5c707a26036441c8bba.profdata
+chrome-win32-main-1699444736-7aa0ca73583e44135205f13c9be4737444986fdd.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 0583b92..8d3d395 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1699427989-7e4b472fd0ab4e4d5bed1b115b4f444368ab1290.profdata
+chrome-win64-main-1699444736-975775f6da95501919e9b9fbfab7069219f51c69.profdata
diff --git a/chrome/credential_provider/gaiacp/credential_provider_broker_win.cc b/chrome/credential_provider/gaiacp/credential_provider_broker_win.cc
index f8472cc..fe2eedef 100644
--- a/chrome/credential_provider/gaiacp/credential_provider_broker_win.cc
+++ b/chrome/credential_provider/gaiacp/credential_provider_broker_win.cc
@@ -122,7 +122,7 @@
 
       DCHECK(base::IsStringASCII(device_path.value()));
       if (!base::EqualsCaseInsensitiveASCII(
-              device_path.value(), base::AsWStringPiece(input_device_path))) {
+              device_path.value(), base::AsWStringView(input_device_path))) {
         continue;
       }
 
diff --git a/chrome/test/data/webui/settings/privacy_guide_page_test.ts b/chrome/test/data/webui/settings/privacy_guide_page_test.ts
index 69a944c1..663eb86 100644
--- a/chrome/test/data/webui/settings/privacy_guide_page_test.ts
+++ b/chrome/test/data/webui/settings/privacy_guide_page_test.ts
@@ -196,7 +196,7 @@
     isBackButtonVisibleExpected: true,
     isCookiesFragmentVisibleExpected: true,
   });
-  // TODO(crbug.com/1215630): Remove this once PrivacyGuide3 is launched.
+  // TODO(crbug.com/1215630): Remove once PrivacyGuide3 launched.
   if (!loadTimeData.getBoolean('enablePrivacyGuide3')) {
     let activeIndex = 3;
     if (!shouldShowHistorySyncCard(syncBrowserProxy)) {
@@ -303,9 +303,6 @@
   let testMetricsBrowserProxy: TestMetricsBrowserProxy;
 
   suiteSetup(function() {
-    // TODO(b:306414714): Remove once 3pcd launched.
-    loadTimeData.overrideValues({is3pcdCookieSettingsRedesignEnabled: true});
-
     settingsPrefs = document.createElement('settings-prefs');
     return CrSettingsPrefs.initialized;
   });
@@ -503,16 +500,13 @@
   });
 });
 
-suite('SettingsFlowLength', function() {
+suite('FlowLength', function() {
   let page: SettingsPrivacyGuidePageElement;
   let settingsPrefs: SettingsPrefsElement;
   let syncBrowserProxy: TestSyncBrowserProxy;
   let testMetricsBrowserProxy: TestMetricsBrowserProxy;
 
   suiteSetup(function() {
-    // TODO(b:306414714): Remove once 3pcd launched.
-    loadTimeData.overrideValues({is3pcdCookieSettingsRedesignEnabled: true});
-
     settingsPrefs = document.createElement('settings-prefs');
     return CrSettingsPrefs.initialized;
   });
@@ -541,7 +535,7 @@
     return flushTasks();
   });
 
-  test('settingsFlowLength_MSBB_SearchSuggestions', async function() {
+  test('MSBB_SearchSuggestions', async function() {
     Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
     await flushTasks();
 
@@ -555,57 +549,50 @@
     assertEquals(2, result);
   });
 
-  test(
-      'settingsFlowLength_MSBB_HistorySync_SearchSuggestions',
-      async function() {
-        Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
-        await flushTasks();
+  test('MSBB_HistorySync_SearchSuggestions', async function() {
+    Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
+    await flushTasks();
 
-        setParametersForHistorySyncStep(syncBrowserProxy, true);
-        setParametersForSafeBrowsingStep(page, false);
+    setParametersForHistorySyncStep(syncBrowserProxy, true);
+    setParametersForSafeBrowsingStep(page, false);
 
-        await clickNextOnWelcomeStep(page);
+    await clickNextOnWelcomeStep(page);
 
-        const result = await testMetricsBrowserProxy.whenCalled(
-            'recordPrivacyGuideFlowLengthHistogram');
-        assertEquals(3, result);
-      });
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideFlowLengthHistogram');
+    assertEquals(3, result);
+  });
 
-  test(
-      'settingsFlowLength_MSBB_SafeBrowsing_SearchSuggestions',
-      async function() {
-        Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
-        await flushTasks();
+  test('MSBB_SafeBrowsing_SearchSuggestions', async function() {
+    Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
+    await flushTasks();
 
-        setParametersForHistorySyncStep(syncBrowserProxy, false);
-        setParametersForSafeBrowsingStep(page, true);
+    setParametersForHistorySyncStep(syncBrowserProxy, false);
+    setParametersForSafeBrowsingStep(page, true);
 
-        await clickNextOnWelcomeStep(page);
+    await clickNextOnWelcomeStep(page);
 
-        const result = await testMetricsBrowserProxy.whenCalled(
-            'recordPrivacyGuideFlowLengthHistogram');
-        assertEquals(3, result);
-      });
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideFlowLengthHistogram');
+    assertEquals(3, result);
+  });
 
-  test(
-      'settingsFlowLength_MSBB_HistorySync_SafeBrowsing_SearchSuggestions',
-      async function() {
-        Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
-        await flushTasks();
+  test('MSBB_HistorySync_SafeBrowsing_SearchSuggestions', async function() {
+    Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
+    await flushTasks();
 
-        setParametersForHistorySyncStep(syncBrowserProxy, true);
-        setParametersForSafeBrowsingStep(page, true);
+    setParametersForHistorySyncStep(syncBrowserProxy, true);
+    setParametersForSafeBrowsingStep(page, true);
 
-        await clickNextOnWelcomeStep(page);
+    await clickNextOnWelcomeStep(page);
 
-        const result = await testMetricsBrowserProxy.whenCalled(
-            'recordPrivacyGuideFlowLengthHistogram');
-        assertEquals(4, result);
-      });
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideFlowLengthHistogram');
+    assertEquals(4, result);
+  });
 });
 
-// TODO(crbug.com/1215630): Remove PrivacyGuidePagePG3Off once PrivacyGuide3
-// is launched.
+// TODO(crbug.com/1215630): Remove once PrivacyGuide3 launched.
 suite('PrivacyGuidePagePG3Off', function() {
   let page: SettingsPrivacyGuidePageElement;
   let settingsPrefs: SettingsPrefsElement;
@@ -613,11 +600,7 @@
   let testMetricsBrowserProxy: TestMetricsBrowserProxy;
 
   suiteSetup(function() {
-    loadTimeData.overrideValues({
-      enablePrivacyGuide3: false,
-      // TODO(b:306414714): Remove once 3pcd launched.
-      is3pcdCookieSettingsRedesignEnabled: true,
-    });
+    loadTimeData.overrideValues({enablePrivacyGuide3: false});
 
     settingsPrefs = document.createElement('settings-prefs');
     return CrSettingsPrefs.initialized;
@@ -727,20 +710,15 @@
   });
 });
 
-// TODO(crbug.com/1215630): Remove SettingsFlowLengthPG3Off once PrivacyGuide3
-// is launched.
-suite('SettingsFlowLengthPG3Off', function() {
+// TODO(crbug.com/1215630): Remove once PrivacyGuide3 launched.
+suite('FlowLengthPG3Off', function() {
   let page: SettingsPrivacyGuidePageElement;
   let settingsPrefs: SettingsPrefsElement;
   let syncBrowserProxy: TestSyncBrowserProxy;
   let testMetricsBrowserProxy: TestMetricsBrowserProxy;
 
   suiteSetup(function() {
-    loadTimeData.overrideValues({
-      enablePrivacyGuide3: false,
-      // TODO(b:306414714): Remove once 3pcd launched.
-      is3pcdCookieSettingsRedesignEnabled: true,
-    });
+    loadTimeData.overrideValues({enablePrivacyGuide3: false});
 
     settingsPrefs = document.createElement('settings-prefs');
     return CrSettingsPrefs.initialized;
@@ -770,7 +748,7 @@
     Router.getInstance().navigateTo(routes.BASIC);
   });
 
-  test('settingsFlowLength_MSBB', async function() {
+  test('MSBB', async function() {
     Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
     await flushTasks();
 
@@ -784,7 +762,7 @@
     assertEquals(1, result);
   });
 
-  test('settingsFlowLength_MSBB_HistorySync', async function() {
+  test('MSBB_HistorySync', async function() {
     Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
     await flushTasks();
 
@@ -798,35 +776,33 @@
     assertEquals(2, result);
   });
 
-  test(
-      'settingsFlowLength_MSBB_SafeBrowsing', async function() {
-        Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
-        await flushTasks();
+  test('MSBB_SafeBrowsing', async function() {
+    Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
+    await flushTasks();
 
-        setParametersForHistorySyncStep(syncBrowserProxy, false);
-        setParametersForSafeBrowsingStep(page, true);
+    setParametersForHistorySyncStep(syncBrowserProxy, false);
+    setParametersForSafeBrowsingStep(page, true);
 
-        await clickNextOnWelcomeStep(page);
+    await clickNextOnWelcomeStep(page);
 
-        const result = await testMetricsBrowserProxy.whenCalled(
-            'recordPrivacyGuideFlowLengthHistogram');
-        assertEquals(2, result);
-      });
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideFlowLengthHistogram');
+    assertEquals(2, result);
+  });
 
-  test(
-      'settingsFlowLength_MSBB_HistorySync_SafeBrowsing', async function() {
-        Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
-        await flushTasks();
+  test('MSBB_HistorySync_SafeBrowsing', async function() {
+    Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
+    await flushTasks();
 
-        setParametersForHistorySyncStep(syncBrowserProxy, true);
-        setParametersForSafeBrowsingStep(page, true);
+    setParametersForHistorySyncStep(syncBrowserProxy, true);
+    setParametersForSafeBrowsingStep(page, true);
 
-        await clickNextOnWelcomeStep(page);
+    await clickNextOnWelcomeStep(page);
 
-        const result = await testMetricsBrowserProxy.whenCalled(
-            'recordPrivacyGuideFlowLengthHistogram');
-        assertEquals(3, result);
-      });
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideFlowLengthHistogram');
+    assertEquals(3, result);
+  });
 });
 
 suite('MsbbCardNavigations', function() {
@@ -836,9 +812,6 @@
   let testMetricsBrowserProxy: TestMetricsBrowserProxy;
 
   suiteSetup(function() {
-    // TODO(b:306414714): Remove once 3pcd launched.
-    loadTimeData.overrideValues({is3pcdCookieSettingsRedesignEnabled: true});
-
     settingsPrefs = document.createElement('settings-prefs');
     return CrSettingsPrefs.initialized;
   });
@@ -863,7 +836,7 @@
     Router.getInstance().navigateTo(routes.BASIC);
   });
 
-  test('msbbBackNavigation', async function() {
+  test('BackNavigation', async function() {
     await navigateToStep(PrivacyGuideStep.MSBB);
     assertMsbbCardVisible(page, syncBrowserProxy);
 
@@ -876,7 +849,7 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickMSBB');
   });
 
-  test('msbbForwardNavigationSyncOn', async function() {
+  test('ForwardNavigationSyncOn', async function() {
     await navigateToStep(PrivacyGuideStep.MSBB);
     assertMsbbCardVisible(page, syncBrowserProxy);
 
@@ -892,7 +865,7 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.NextClickMSBB');
   });
 
-  test('msbbForwardNavigationSyncOff', async function() {
+  test('ForwardNavigationSyncOff', async function() {
     setupSync({
       syncBrowserProxy: syncBrowserProxy,
       syncOn: false,
@@ -907,8 +880,7 @@
   });
 });
 
-// TODO(crbug.com/1215630): Remove MsbbCardNavigationsPG3Off once PrivacyGuide3
-// is launched.
+// TODO(crbug.com/1215630): Remove once PrivacyGuide3 launched.
 suite('MsbbCardNavigationsPG3Off', function() {
   let page: SettingsPrivacyGuidePageElement;
   let settingsPrefs: SettingsPrefsElement;
@@ -916,11 +888,7 @@
   let testMetricsBrowserProxy: TestMetricsBrowserProxy;
 
   suiteSetup(function() {
-    loadTimeData.overrideValues({
-      enablePrivacyGuide3: false,
-      // TODO(b:306414714): Remove once 3pcd launched.
-      is3pcdCookieSettingsRedesignEnabled: true,
-    });
+    loadTimeData.overrideValues({enablePrivacyGuide3: false});
 
     settingsPrefs = document.createElement('settings-prefs');
     return CrSettingsPrefs.initialized;
@@ -946,7 +914,7 @@
     Router.getInstance().navigateTo(routes.BASIC);
   });
 
-  test('msbbForwardNavigationSyncOff', async function() {
+  test('ForwardNavigationSyncOff', async function() {
     setupSync({
       syncBrowserProxy: syncBrowserProxy,
       syncOn: false,
@@ -968,9 +936,6 @@
   let testMetricsBrowserProxy: TestMetricsBrowserProxy;
 
   suiteSetup(function() {
-    // TODO(b:306414714): Remove once 3pcd launched.
-    loadTimeData.overrideValues({is3pcdCookieSettingsRedesignEnabled: true});
-
     settingsPrefs = document.createElement('settings-prefs');
     return CrSettingsPrefs.initialized;
   });
@@ -995,7 +960,7 @@
     Router.getInstance().navigateTo(routes.BASIC);
   });
 
-  test('historySyncBackNavigation', async function() {
+  test('BackNavigation', async function() {
     await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
     assertHistorySyncCardVisible(page, syncBrowserProxy);
 
@@ -1007,7 +972,7 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickHistorySync');
   });
 
-  test('historySyncNavigatesAwayOnSyncOff', async function() {
+  test('NavigatesAwayOnSyncOff', async function() {
     await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
     assertHistorySyncCardVisible(page, syncBrowserProxy);
 
@@ -1021,7 +986,7 @@
     assertSafeBrowsingCardVisible(page, syncBrowserProxy);
   });
 
-  test('historySyncNotReachableWhenSyncOff', async function() {
+  test('NotReachableWhenSyncOff', async function() {
     await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
     setupSync({
       syncBrowserProxy: syncBrowserProxy,
@@ -1032,39 +997,33 @@
     assertSafeBrowsingCardVisible(page, syncBrowserProxy);
   });
 
-  test(
-      'historySyncCardForwardNavigationShouldShowSafeBrowsingCard',
-      async function() {
-        await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
-        assertHistorySyncCardVisible(page, syncBrowserProxy);
+  test('ForwardNavigationShouldShowSafeBrowsingCard', async function() {
+    await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
+    assertHistorySyncCardVisible(page, syncBrowserProxy);
 
-        page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
-        assertSafeBrowsingCardVisible(page, syncBrowserProxy);
+    page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
+    assertSafeBrowsingCardVisible(page, syncBrowserProxy);
 
-        const result = await testMetricsBrowserProxy.whenCalled(
-            'recordPrivacyGuideNextNavigationHistogram');
-        assertEquals(PrivacyGuideInteractions.HISTORY_SYNC_NEXT_BUTTON, result);
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideNextNavigationHistogram');
+    assertEquals(PrivacyGuideInteractions.HISTORY_SYNC_NEXT_BUTTON, result);
 
-        const actionResult =
-            await testMetricsBrowserProxy.whenCalled('recordAction');
-        assertEquals(
-            actionResult, 'Settings.PrivacyGuide.NextClickHistorySync');
-      });
+    const actionResult =
+        await testMetricsBrowserProxy.whenCalled('recordAction');
+    assertEquals(actionResult, 'Settings.PrivacyGuide.NextClickHistorySync');
+  });
 
-  test(
-      'historySyncCardForwardNavigationShouldHideSafeBrowsingCard',
-      async function() {
-        setSafeBrowsingSetting(page, SafeBrowsingSetting.DISABLED);
-        await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
-        assertHistorySyncCardVisible(page, syncBrowserProxy);
+  test('ForwardNavigationShouldHideSafeBrowsingCard', async function() {
+    setSafeBrowsingSetting(page, SafeBrowsingSetting.DISABLED);
+    await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
+    assertHistorySyncCardVisible(page, syncBrowserProxy);
 
-        page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
-        assertSearchSuggestionsCardVisible(page, syncBrowserProxy);
-      });
+    page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
+    assertSearchSuggestionsCardVisible(page, syncBrowserProxy);
+  });
 });
 
-// TODO(crbug.com/1215630): Remove HistorySyncCardNavigationsPG3Off once
-// PrivacyGuide3 is launched.
+// TODO(crbug.com/1215630): Remove once PrivacyGuide3 launched.
 suite('HistorySyncCardNavigationsPG3Off', function() {
   let page: SettingsPrivacyGuidePageElement;
   let settingsPrefs: SettingsPrefsElement;
@@ -1072,11 +1031,7 @@
   let testMetricsBrowserProxy: TestMetricsBrowserProxy;
 
   suiteSetup(function() {
-    loadTimeData.overrideValues({
-      enablePrivacyGuide3: false,
-      // TODO(b:306414714): Remove once 3pcd launched.
-      is3pcdCookieSettingsRedesignEnabled: true,
-    });
+    loadTimeData.overrideValues({enablePrivacyGuide3: false});
 
     settingsPrefs = document.createElement('settings-prefs');
     return CrSettingsPrefs.initialized;
@@ -1102,7 +1057,7 @@
     Router.getInstance().navigateTo(routes.BASIC);
   });
 
-  test('historySyncNavigatesAwayOnSyncOff', async function() {
+  test('NavigatesAwayOnSyncOff', async function() {
     await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
     assertHistorySyncCardVisible(page, syncBrowserProxy);
 
@@ -1116,7 +1071,7 @@
     assertSafeBrowsingCardVisible(page, syncBrowserProxy);
   });
 
-  test('historySyncNotReachableWhenSyncOff', async function() {
+  test('NotReachableWhenSyncOff', async function() {
     await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
     setupSync({
       syncBrowserProxy: syncBrowserProxy,
@@ -1127,36 +1082,31 @@
     assertSafeBrowsingCardVisible(page, syncBrowserProxy);
   });
 
-  test(
-      'historySyncCardForwardNavigationShouldShowSafeBrowsingCard',
-      async function() {
-        await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
-        assertHistorySyncCardVisible(page, syncBrowserProxy);
+  test('ForwardNavigationShouldShowSafeBrowsingCard', async function() {
+    await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
+    assertHistorySyncCardVisible(page, syncBrowserProxy);
 
-        page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
-        assertSafeBrowsingCardVisible(page, syncBrowserProxy);
+    page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
+    assertSafeBrowsingCardVisible(page, syncBrowserProxy);
 
-        const result = await testMetricsBrowserProxy.whenCalled(
-            'recordPrivacyGuideNextNavigationHistogram');
-        assertEquals(PrivacyGuideInteractions.HISTORY_SYNC_NEXT_BUTTON, result);
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideNextNavigationHistogram');
+    assertEquals(PrivacyGuideInteractions.HISTORY_SYNC_NEXT_BUTTON, result);
 
-        const actionResult =
-            await testMetricsBrowserProxy.whenCalled('recordAction');
-        assertEquals(
-            actionResult, 'Settings.PrivacyGuide.NextClickHistorySync');
-      });
+    const actionResult =
+        await testMetricsBrowserProxy.whenCalled('recordAction');
+    assertEquals(actionResult, 'Settings.PrivacyGuide.NextClickHistorySync');
+  });
 
-  test(
-      'historySyncCardForwardNavigationShouldHideSafeBrowsingCard',
-      async function() {
-        setSafeBrowsingSetting(page, SafeBrowsingSetting.DISABLED);
-        await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
-        assertHistorySyncCardVisible(page, syncBrowserProxy);
+  test('ForwardNavigationShouldHideSafeBrowsingCard', async function() {
+    setSafeBrowsingSetting(page, SafeBrowsingSetting.DISABLED);
+    await navigateToStep(PrivacyGuideStep.HISTORY_SYNC);
+    assertHistorySyncCardVisible(page, syncBrowserProxy);
 
-        page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
-        flush();
-        assertCompletionCardVisible(page);
-      });
+    page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
+    flush();
+    assertCompletionCardVisible(page);
+  });
 });
 
 suite('SafeBrowsingCardNavigations', function() {
@@ -1166,9 +1116,6 @@
   let testMetricsBrowserProxy: TestMetricsBrowserProxy;
 
   suiteSetup(function() {
-    // TODO(b:306414714): Remove once 3pcd launched.
-    loadTimeData.overrideValues({is3pcdCookieSettingsRedesignEnabled: true});
-
     settingsPrefs = document.createElement('settings-prefs');
     return CrSettingsPrefs.initialized;
   });
@@ -1193,7 +1140,7 @@
     Router.getInstance().navigateTo(routes.BASIC);
   });
 
-  test('safeBrowsingCardBackNavigationSyncOn', async function() {
+  test('BackNavigationSyncOn', async function() {
     await navigateToStep(PrivacyGuideStep.SAFE_BROWSING);
     assertSafeBrowsingCardVisible(page, syncBrowserProxy);
 
@@ -1205,7 +1152,7 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickSafeBrowsing');
   });
 
-  test('safeBrowsingCardBackNavigationSyncOff', async function() {
+  test('BackNavigationSyncOff', async function() {
     setupSync({
       syncBrowserProxy: syncBrowserProxy,
       syncOn: false,
@@ -1219,26 +1166,22 @@
     assertMsbbCardVisible(page, syncBrowserProxy);
   });
 
-  test(
-      'safeBrowsingCardForwardNavigationShouldShowSearchSuggestionsCard',
-      async function() {
-        await navigateToStep(PrivacyGuideStep.SAFE_BROWSING);
-        assertSafeBrowsingCardVisible(page, syncBrowserProxy);
+  test('ForwardNavigationShouldShowSearchSuggestionsCard', async function() {
+    await navigateToStep(PrivacyGuideStep.SAFE_BROWSING);
+    assertSafeBrowsingCardVisible(page, syncBrowserProxy);
 
-        page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
-        flush();
-        assertSearchSuggestionsCardVisible(page, syncBrowserProxy);
+    page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
+    flush();
+    assertSearchSuggestionsCardVisible(page, syncBrowserProxy);
 
-        const result = await testMetricsBrowserProxy.whenCalled(
-            'recordPrivacyGuideNextNavigationHistogram');
-        assertEquals(
-            PrivacyGuideInteractions.SAFE_BROWSING_NEXT_BUTTON, result);
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideNextNavigationHistogram');
+    assertEquals(PrivacyGuideInteractions.SAFE_BROWSING_NEXT_BUTTON, result);
 
-        const actionResult =
-            await testMetricsBrowserProxy.whenCalled('recordAction');
-        assertEquals(
-            actionResult, 'Settings.PrivacyGuide.NextClickSafeBrowsing');
-      });
+    const actionResult =
+        await testMetricsBrowserProxy.whenCalled('recordAction');
+    assertEquals(actionResult, 'Settings.PrivacyGuide.NextClickSafeBrowsing');
+  });
 
   test('safeBrowsingOffNavigatesAway', async function() {
     await navigateToStep(PrivacyGuideStep.SAFE_BROWSING);
@@ -1251,8 +1194,7 @@
   });
 });
 
-// TODO(crbug.com/1215630): Remove SafeBrowsingCardNavigationsPG3Off once
-// PrivacyGuide3 is launched.
+// TODO(crbug.com/1215630): Remove once PrivacyGuide3 launched.
 suite('SafeBrowsingCardNavigationsPG3Off', function() {
   let page: SettingsPrivacyGuidePageElement;
   let settingsPrefs: SettingsPrefsElement;
@@ -1260,11 +1202,7 @@
   let testMetricsBrowserProxy: TestMetricsBrowserProxy;
 
   suiteSetup(function() {
-    loadTimeData.overrideValues({
-      enablePrivacyGuide3: false,
-      // TODO(b:306414714): Remove once 3pcd launched.
-      is3pcdCookieSettingsRedesignEnabled: true,
-    });
+    loadTimeData.overrideValues({enablePrivacyGuide3: false});
 
     settingsPrefs = document.createElement('settings-prefs');
     return CrSettingsPrefs.initialized;
@@ -1290,7 +1228,7 @@
     Router.getInstance().navigateTo(routes.BASIC);
   });
 
-  test('safeBrowsingCardBackNavigationSyncOn', async function() {
+  test('BackNavigationSyncOn', async function() {
     await navigateToStep(PrivacyGuideStep.SAFE_BROWSING);
     assertSafeBrowsingCardVisible(page, syncBrowserProxy);
 
@@ -1302,7 +1240,7 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickSafeBrowsing');
   });
 
-  test('safeBrowsingCardBackNavigationSyncOff', async function() {
+  test('BackNavigationSyncOff', async function() {
     setupSync({
       syncBrowserProxy: syncBrowserProxy,
       syncOn: false,
@@ -1316,7 +1254,7 @@
     assertMsbbCardVisible(page, syncBrowserProxy);
   });
 
-  test('safeBrowsingCardForwardNavigation', async function() {
+  test('ForwardNavigation', async function() {
     await navigateToStep(PrivacyGuideStep.SAFE_BROWSING);
     assertSafeBrowsingCardVisible(page, syncBrowserProxy);
 
@@ -1377,7 +1315,7 @@
     Router.getInstance().navigateTo(routes.BASIC);
   });
 
-  test('cookiesCardBackNavigationShouldShowSync', async function() {
+  test('BackNavigationShouldShowSync', async function() {
     await navigateToStep(PrivacyGuideStep.COOKIES);
     assertCookiesCardVisible(page, syncBrowserProxy);
 
@@ -1390,7 +1328,7 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickCookies');
   });
 
-  test('cookiesCardBackNavigationShouldHideSync', async function() {
+  test('BackNavigationShouldHideSync', async function() {
     setupSync({
       syncBrowserProxy: syncBrowserProxy,
       syncOn: false,
@@ -1405,7 +1343,7 @@
     assertMsbbCardVisible(page, syncBrowserProxy);
   });
 
-  test('cookiesCardForwardNavigationShouldShowSafeBrowsing', async function() {
+  test('ForwardNavigationShouldShowSafeBrowsing', async function() {
     await navigateToStep(PrivacyGuideStep.COOKIES);
     assertCookiesCardVisible(page, syncBrowserProxy);
 
@@ -1422,7 +1360,7 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.NextClickCookies');
   });
 
-  test('cookiesCardForwardNavigationShouldHideSafeBrowsing', async function() {
+  test('ForwardNavigationShouldHideSafeBrowsing', async function() {
     setSafeBrowsingSetting(page, SafeBrowsingSetting.DISABLED);
     await navigateToStep(PrivacyGuideStep.COOKIES);
     assertCookiesCardVisible(page, syncBrowserProxy);
@@ -1455,8 +1393,7 @@
   });
 });
 
-// TODO(crbug.com/1215630): Remove CookiesCardNavigationsPG3Off once
-// PrivacyGuide3 is launched.
+// TODO(crbug.com/1215630): Remove once PrivacyGuide3 launched.
 suite('CookiesCardNavigationsPG3Off', function() {
   let page: SettingsPrivacyGuidePageElement;
   let settingsPrefs: SettingsPrefsElement;
@@ -1496,7 +1433,7 @@
     Router.getInstance().navigateTo(routes.BASIC);
   });
 
-  test('cookiesCardBackNavigationShouldShowSafeBrowsingCard', async function() {
+  test('NavigationShouldShowSafeBrowsingCard', async function() {
     await navigateToStep(PrivacyGuideStep.COOKIES);
     assertCookiesCardVisible(page, syncBrowserProxy);
 
@@ -1509,7 +1446,7 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickCookies');
   });
 
-  test('cookiesCardBackNavigationShouldHideSafeBrowsingCard', async function() {
+  test('NavigationShouldHideSafeBrowsingCard', async function() {
     setSafeBrowsingSetting(page, SafeBrowsingSetting.DISABLED);
     await navigateToStep(PrivacyGuideStep.COOKIES);
     assertCookiesCardVisible(page, syncBrowserProxy);
@@ -1519,7 +1456,7 @@
     assertHistorySyncCardVisible(page, syncBrowserProxy);
   });
 
-  test('cookiesCardForwardNavigation', async function() {
+  test('ForwardNavigation', async function() {
     await navigateToStep(PrivacyGuideStep.COOKIES);
     assertCookiesCardVisible(page, syncBrowserProxy);
 
@@ -1597,7 +1534,7 @@
     Router.getInstance().navigateTo(routes.BASIC);
   });
 
-  test('searchSuggestionsCardBackNavigationSafeBrowsingOn', async function() {
+  test('BackNavigationSafeBrowsingOn', async function() {
     await navigateToStep(PrivacyGuideStep.SEARCH_SUGGESTIONS);
     assertSearchSuggestionsCardVisible(page, syncBrowserProxy);
 
@@ -1610,7 +1547,7 @@
         actionResult, 'Settings.PrivacyGuide.BackClickSearchSuggestions');
   });
 
-  test('searchSuggestionsCardBackNavigationSafeBrowsingOff', async function() {
+  test('BackNavigationSafeBrowsingOff', async function() {
     setSafeBrowsingSetting(page, SafeBrowsingSetting.DISABLED);
     await navigateToStep(PrivacyGuideStep.SEARCH_SUGGESTIONS);
     assertSearchSuggestionsCardVisible(page, syncBrowserProxy);
@@ -1619,26 +1556,24 @@
     assertHistorySyncCardVisible(page, syncBrowserProxy);
   });
 
-  test(
-      'searchSuggestionsCardForwardNavigationShouldShowCompletion',
-      async function() {
-        await navigateToStep(PrivacyGuideStep.SEARCH_SUGGESTIONS);
-        assertSearchSuggestionsCardVisible(page, syncBrowserProxy);
+  test('ForwardNavigationShouldShowCompletion', async function() {
+    await navigateToStep(PrivacyGuideStep.SEARCH_SUGGESTIONS);
+    assertSearchSuggestionsCardVisible(page, syncBrowserProxy);
 
-        page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
-        flush();
-        assertCompletionCardVisible(page);
+    page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
+    flush();
+    assertCompletionCardVisible(page);
 
-        const result = await testMetricsBrowserProxy.whenCalled(
-            'recordPrivacyGuideNextNavigationHistogram');
-        assertEquals(
-            PrivacyGuideInteractions.SEARCH_SUGGESTIONS_NEXT_BUTTON, result);
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideNextNavigationHistogram');
+    assertEquals(
+        PrivacyGuideInteractions.SEARCH_SUGGESTIONS_NEXT_BUTTON, result);
 
-        const actionResult =
-            await testMetricsBrowserProxy.whenCalled('recordAction');
-        assertEquals(
-            actionResult, 'Settings.PrivacyGuide.NextClickSearchSuggestions');
-      });
+    const actionResult =
+        await testMetricsBrowserProxy.whenCalled('recordAction');
+    assertEquals(
+        actionResult, 'Settings.PrivacyGuide.NextClickSearchSuggestions');
+  });
 
   test('hatsInformedOnFinish', async function() {
     await navigateToStep(PrivacyGuideStep.SEARCH_SUGGESTIONS);
@@ -1690,7 +1625,7 @@
     Router.getInstance().navigateTo(routes.BASIC);
   });
 
-  test('preloadCardBackNavigation', async function() {
+  test('BackNavigation', async function() {
     setPreloadSetting(page, NetworkPredictionOptions.STANDARD);
     await navigateToStep(PrivacyGuideStep.PRELOAD);
     assertPreloadCardVisible(page, syncBrowserProxy);
@@ -1710,7 +1645,7 @@
     assertCompletionCardVisible(page);
   });
 
-  test('preloadCardForwardNavigationShouldShowCompletion', async function() {
+  test('ForwardNavigationShouldShowCompletion', async function() {
     setPreloadSetting(page, NetworkPredictionOptions.STANDARD);
     await navigateToStep(PrivacyGuideStep.PRELOAD);
     assertPreloadCardVisible(page, syncBrowserProxy);
@@ -1814,8 +1749,7 @@
   });
 
   test(
-      'settingsFlowLength_MSBB_Cookies_SafeBrowsing_SearchSuggestions',
-      async function() {
+      'length_MSBB_Cookies_SafeBrowsing_SearchSuggestions', async function() {
         Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
         await flushTasks();
 
@@ -1831,7 +1765,7 @@
       });
 
   test(
-      'settingsFlowLength_MSBB_HistorySync_Cookies_SafeBrowsing_SearchSuggestions',
+      'length_MSBB_HistorySync_Cookies_SafeBrowsing_SearchSuggestions',
       async function() {
         Router.getInstance().navigateTo(routes.PRIVACY_GUIDE);
         await flushTasks();
diff --git a/chrome/test/data/webui/settings/settings_browsertest.cc b/chrome/test/data/webui/settings/settings_browsertest.cc
index c1d391de..5e8f9cf2 100644
--- a/chrome/test/data/webui/settings/settings_browsertest.cc
+++ b/chrome/test/data/webui/settings/settings_browsertest.cc
@@ -693,8 +693,16 @@
 #endif
 
 class SettingsPrivacyGuideTest : public SettingsBrowserTest {
+ protected:
+  SettingsPrivacyGuideTest() {
+    scoped_feature_list_.InitWithFeatures(
+        {content_settings::features::kTrackingProtection3pcd,
+         features::kPrivacyGuide3},
+        {});
+  }
+
  private:
-  base::test::ScopedFeatureList scoped_feature_list_{features::kPrivacyGuide3};
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 IN_PROC_BROWSER_TEST_F(SettingsPrivacyGuideTest, PrivacyGuidePage) {
@@ -702,9 +710,8 @@
           "runMochaSuite('PrivacyGuidePage')");
 }
 
-IN_PROC_BROWSER_TEST_F(SettingsPrivacyGuideTest, SettingsFlowLength) {
-  RunTest("settings/privacy_guide_page_test.js",
-          "runMochaSuite('SettingsFlowLength')");
+IN_PROC_BROWSER_TEST_F(SettingsPrivacyGuideTest, FlowLength) {
+  RunTest("settings/privacy_guide_page_test.js", "runMochaSuite('FlowLength')");
 }
 
 IN_PROC_BROWSER_TEST_F(SettingsPrivacyGuideTest, PrivacyGuidePagePG3Off) {
@@ -712,9 +719,9 @@
           "runMochaSuite('PrivacyGuidePagePG3Off')");
 }
 
-IN_PROC_BROWSER_TEST_F(SettingsPrivacyGuideTest, SettingsFlowLengthPG3Off) {
+IN_PROC_BROWSER_TEST_F(SettingsPrivacyGuideTest, FlowLengthPG3Off) {
   RunTest("settings/privacy_guide_page_test.js",
-          "runMochaSuite('SettingsFlowLengthPG3Off')");
+          "runMochaSuite('FlowLengthPG3Off')");
 }
 
 IN_PROC_BROWSER_TEST_F(SettingsPrivacyGuideTest, MsbbCardNavigations) {
@@ -775,9 +782,14 @@
           "runMochaSuite('PrivacyGuideDialog')");
 }
 
+class SettingsPrivacyGuideIntegrationTest : public SettingsBrowserTest {
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_{features::kPrivacyGuide3};
+};
+
 // TODO(https://crbug.com/1426530): Re-enable when no longer flaky.
 #if !BUILDFLAG(IS_LINUX) || defined(NDEBUG)
-IN_PROC_BROWSER_TEST_F(SettingsPrivacyGuideTest, Integration) {
+IN_PROC_BROWSER_TEST_F(SettingsPrivacyGuideIntegrationTest, Integration) {
   RunTest("settings/privacy_guide_integration_test.js", "mocha.run()");
 }
 #endif
diff --git a/chrome/updater/test/integration_tests_win.cc b/chrome/updater/test/integration_tests_win.cc
index 90de15b..ac3cc28 100644
--- a/chrome/updater/test/integration_tests_win.cc
+++ b/chrome/updater/test/integration_tests_win.cc
@@ -783,11 +783,25 @@
     }
   }
 
-  for (const auto& [iid, interface_name] : JoinVectors(
-           GetSideBySideInterfaces(scope), GetActiveInterfaces(scope))) {
-    EXPECT_TRUE(DeleteRegKey(root, GetComIidRegistryPath(iid)));
-    EXPECT_TRUE(DeleteRegKey64(root, GetComIidRegistryPath(iid)));
-    EXPECT_TRUE(DeleteRegKeyCOM(root, GetComTypeLibRegistryPath(iid)));
+  // To avoid `TYPE_E_CANTLOADLIBRARY` errors due to a failed cleanup of a
+  // previous user test run, this code cleans up both system and user
+  // interface/typelib entries when running system tests.
+  for (const UpdaterScope interface_scope : [&]() -> std::vector<UpdaterScope> {
+         if (IsSystemInstall(scope)) {
+           return {scope, UpdaterScope::kUser};
+         } else {
+           return {scope};
+         }
+       }()) {
+    for (const auto& [iid, interface_name] :
+         JoinVectors(GetSideBySideInterfaces(interface_scope),
+                     GetActiveInterfaces(interface_scope))) {
+      const HKEY interface_root = UpdaterScopeToHKeyRoot(interface_scope);
+      EXPECT_TRUE(DeleteRegKey(interface_root, GetComIidRegistryPath(iid)));
+      EXPECT_TRUE(DeleteRegKey64(interface_root, GetComIidRegistryPath(iid)));
+      EXPECT_TRUE(
+          DeleteRegKeyCOM(interface_root, GetComTypeLibRegistryPath(iid)));
+    }
   }
 
   if (!IsSystemInstall(scope)) {
diff --git a/chromeos/ash/components/audio/audio_device_selection_unittest.cc b/chromeos/ash/components/audio/audio_device_selection_unittest.cc
index 98b6be4..07f2f94 100644
--- a/chromeos/ash/components/audio/audio_device_selection_unittest.cc
+++ b/chromeos/ash/components/audio/audio_device_selection_unittest.cc
@@ -7,15 +7,11 @@
 #include "ash/constants/ash_features.h"
 #include "base/test/metrics/user_action_tester.h"
 #include "base/test/scoped_feature_list.h"
+#include "chromeos/ash/components/audio/cras_audio_handler.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-const char* kInputSwitched = "StatusArea_Audio_SwitchInputDevice";
-const char* kOutputSwitched = "StatusArea_Audio_SwitchOutputDevice";
-const char* kInputOverridden = "StatusArea_Audio_AutoInputSelectionOverridden";
-const char* kOutputOverridden =
-    "StatusArea_Audio_AutoOutputSelectionOverridden";
-
 namespace ash {
+
 namespace {
 
 class AudioDeviceSelectionTest : public AudioDeviceSelectionTestBase {};
@@ -37,10 +33,16 @@
     ASSERT_EQ(ActiveInputNodeId(), input2.id);
     ASSERT_EQ(ActiveOutputNodeId(), output4.id);
     // Automatic switches should not generate events.
-    EXPECT_EQ(actions.GetActionCount(kInputSwitched), 0);
-    EXPECT_EQ(actions.GetActionCount(kOutputSwitched), 0);
-    EXPECT_EQ(actions.GetActionCount(kInputOverridden), 0);
-    EXPECT_EQ(actions.GetActionCount(kOutputOverridden), 0);
+    EXPECT_EQ(actions.GetActionCount(CrasAudioHandler::kUserActionSwitchInput),
+              0);
+    EXPECT_EQ(actions.GetActionCount(CrasAudioHandler::kUserActionSwitchOutput),
+              0);
+    EXPECT_EQ(actions.GetActionCount(
+                  CrasAudioHandler::kUserActionSwitchInputOverridden),
+              0);
+    EXPECT_EQ(actions.GetActionCount(
+                  CrasAudioHandler::kUserActionSwitchOutputOverridden),
+              0);
   }
 
   {
@@ -48,10 +50,16 @@
     Select(input1);
     ASSERT_EQ(ActiveInputNodeId(), input1.id);
     ASSERT_EQ(ActiveOutputNodeId(), output4.id);
-    EXPECT_EQ(actions.GetActionCount(kInputSwitched), 1);
-    EXPECT_EQ(actions.GetActionCount(kOutputSwitched), 0);
-    EXPECT_EQ(actions.GetActionCount(kInputOverridden), 1);
-    EXPECT_EQ(actions.GetActionCount(kOutputOverridden), 0);
+    EXPECT_EQ(actions.GetActionCount(CrasAudioHandler::kUserActionSwitchInput),
+              1);
+    EXPECT_EQ(actions.GetActionCount(CrasAudioHandler::kUserActionSwitchOutput),
+              0);
+    EXPECT_EQ(actions.GetActionCount(
+                  CrasAudioHandler::kUserActionSwitchInputOverridden),
+              1);
+    EXPECT_EQ(actions.GetActionCount(
+                  CrasAudioHandler::kUserActionSwitchOutputOverridden),
+              0);
   }
 
   {
@@ -59,10 +67,16 @@
     Select(output3);
     ASSERT_EQ(ActiveInputNodeId(), input1.id);
     ASSERT_EQ(ActiveOutputNodeId(), output3.id);
-    EXPECT_EQ(actions.GetActionCount(kInputSwitched), 0);
-    EXPECT_EQ(actions.GetActionCount(kOutputSwitched), 1);
-    EXPECT_EQ(actions.GetActionCount(kInputOverridden), 0);
-    EXPECT_EQ(actions.GetActionCount(kOutputOverridden), 1);
+    EXPECT_EQ(actions.GetActionCount(CrasAudioHandler::kUserActionSwitchInput),
+              0);
+    EXPECT_EQ(actions.GetActionCount(CrasAudioHandler::kUserActionSwitchOutput),
+              1);
+    EXPECT_EQ(actions.GetActionCount(
+                  CrasAudioHandler::kUserActionSwitchInputOverridden),
+              0);
+    EXPECT_EQ(actions.GetActionCount(
+                  CrasAudioHandler::kUserActionSwitchOutputOverridden),
+              1);
   }
 
   {
@@ -71,11 +85,17 @@
     Select(output4);
     ASSERT_EQ(ActiveInputNodeId(), input2.id);
     ASSERT_EQ(ActiveOutputNodeId(), output4.id);
-    EXPECT_EQ(actions.GetActionCount(kInputSwitched), 1);
-    EXPECT_EQ(actions.GetActionCount(kOutputSwitched), 1);
+    EXPECT_EQ(actions.GetActionCount(CrasAudioHandler::kUserActionSwitchInput),
+              1);
+    EXPECT_EQ(actions.GetActionCount(CrasAudioHandler::kUserActionSwitchOutput),
+              1);
     // Switching back and forth should not be counted.
-    EXPECT_EQ(actions.GetActionCount(kInputOverridden), 0);
-    EXPECT_EQ(actions.GetActionCount(kOutputOverridden), 0);
+    EXPECT_EQ(actions.GetActionCount(
+                  CrasAudioHandler::kUserActionSwitchInputOverridden),
+              0);
+    EXPECT_EQ(actions.GetActionCount(
+                  CrasAudioHandler::kUserActionSwitchOutputOverridden),
+              0);
   }
 
   {
@@ -84,9 +104,12 @@
     Plug(input1);
     ASSERT_EQ(ActiveInputNodeId(), input2.id);
     Select(input1);
-    EXPECT_EQ(actions.GetActionCount(kInputSwitched), 1);
+    EXPECT_EQ(actions.GetActionCount(CrasAudioHandler::kUserActionSwitchInput),
+              1);
     // Switching after the system decides to do nothing, should be counted.
-    EXPECT_EQ(actions.GetActionCount(kInputOverridden), 1);
+    EXPECT_EQ(actions.GetActionCount(
+                  CrasAudioHandler::kUserActionSwitchInputOverridden),
+              1);
   }
 
   {
@@ -95,9 +118,12 @@
     Plug(output3);
     ASSERT_EQ(ActiveOutputNodeId(), output4.id);
     Select(output3);
-    EXPECT_EQ(actions.GetActionCount(kOutputSwitched), 1);
+    EXPECT_EQ(actions.GetActionCount(CrasAudioHandler::kUserActionSwitchOutput),
+              1);
     // Switching after the system decides to do nothing, should be counted.
-    EXPECT_EQ(actions.GetActionCount(kOutputOverridden), 1);
+    EXPECT_EQ(actions.GetActionCount(
+                  CrasAudioHandler::kUserActionSwitchOutputOverridden),
+              1);
   }
 }
 
@@ -145,4 +171,5 @@
 }
 
 }  // namespace
+
 }  // namespace ash
diff --git a/chromeos/ash/components/audio/cras_audio_handler.cc b/chromeos/ash/components/audio/cras_audio_handler.cc
index 09f668e..7239b4a 100644
--- a/chromeos/ash/components/audio/cras_audio_handler.cc
+++ b/chromeos/ash/components/audio/cras_audio_handler.cc
@@ -1041,18 +1041,16 @@
                                        DeviceActivateType activate_by) {
   if (activate_by == ACTIVATE_BY_USER) {
     if (active_device.is_input) {
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Audio_SwitchInputDevice"));
+      base::RecordAction(base::UserMetricsAction(kUserActionSwitchInput));
       if (!input_device_selected_by_user_) {
-        base::RecordAction(base::UserMetricsAction(
-            "StatusArea_Audio_AutoInputSelectionOverridden"));
+        base::RecordAction(
+            base::UserMetricsAction(kUserActionSwitchInputOverridden));
       }
     } else {
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Audio_SwitchOutputDevice"));
+      base::RecordAction(base::UserMetricsAction(kUserActionSwitchOutput));
       if (!output_device_selected_by_user_) {
-        base::RecordAction(base::UserMetricsAction(
-            "StatusArea_Audio_AutoOutputSelectionOverridden"));
+        base::RecordAction(
+            base::UserMetricsAction(kUserActionSwitchOutputOverridden));
       }
     }
   }
diff --git a/chromeos/ash/components/audio/cras_audio_handler.h b/chromeos/ash/components/audio/cras_audio_handler.h
index 5950b5c..ba333fe3 100644
--- a/chromeos/ash/components/audio/cras_audio_handler.h
+++ b/chromeos/ash/components/audio/cras_audio_handler.h
@@ -145,6 +145,17 @@
   static constexpr char kNoiseCancellationEnabledSourceHistogramName[] =
       "Cras.NoiseCancellationEnabledSource";
 
+  // A series of user action metrics to record when user switches the
+  // input/output audio device and if this switch overrides the system decision.
+  static constexpr char kUserActionSwitchInput[] =
+      "StatusArea_Audio_SwitchInputDevice";
+  static constexpr char kUserActionSwitchOutput[] =
+      "StatusArea_Audio_SwitchOutputDevice";
+  static constexpr char kUserActionSwitchInputOverridden[] =
+      "StatusArea_Audio_AutoInputSelectionOverridden";
+  static constexpr char kUserActionSwitchOutputOverridden[] =
+      "StatusArea_Audio_AutoOutputSelectionOverridden";
+
   class AudioObserver {
    public:
     AudioObserver(const AudioObserver&) = delete;
diff --git a/chromeos/ash/components/auth_panel/BUILD.gn b/chromeos/ash/components/auth_panel/BUILD.gn
index d98eab3c..eb00991e 100644
--- a/chromeos/ash/components/auth_panel/BUILD.gn
+++ b/chromeos/ash/components/auth_panel/BUILD.gn
@@ -23,6 +23,7 @@
     "auth_panel.h",
     "auth_panel_event_dispatcher.cc",
     "auth_panel_event_dispatcher.h",
+    "factor_auth_view.cc",
     "factor_auth_view.h",
     "factor_auth_view_factory.cc",
     "factor_auth_view_factory.h",
diff --git a/chromeos/ash/components/auth_panel/factor_auth_view.cc b/chromeos/ash/components/auth_panel/factor_auth_view.cc
new file mode 100644
index 0000000..64301aa
--- /dev/null
+++ b/chromeos/ash/components/auth_panel/factor_auth_view.cc
@@ -0,0 +1,14 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/ash/components/auth_panel/factor_auth_view.h"
+
+#include "ui/base/metadata/metadata_impl_macros.h"
+
+namespace ash {
+
+BEGIN_METADATA(FactorAuthView)
+END_METADATA
+
+}  // namespace ash
diff --git a/chromeos/ash/components/auth_panel/factor_auth_view.h b/chromeos/ash/components/auth_panel/factor_auth_view.h
index c073112b..75561e9 100644
--- a/chromeos/ash/components/auth_panel/factor_auth_view.h
+++ b/chromeos/ash/components/auth_panel/factor_auth_view.h
@@ -8,6 +8,7 @@
 #include "chromeos/ash/components/auth_panel/auth_factor_store.h"
 #include "chromeos/ash/components/osauth/public/auth_factor_status_consumer.h"
 #include "chromeos/ash/components/osauth/public/common_types.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/view.h"
 
 namespace ash {
@@ -15,6 +16,8 @@
 // Interface common to all factor views, abstracts an auth factor view on the
 // login, lock screen, or in-session.
 class FactorAuthView : public views::View {
+  METADATA_HEADER(FactorAuthView, views::View)
+
  public:
   ~FactorAuthView() override = default;
 
diff --git a/chromeos/ash/components/auth_panel/views/login_textfield.cc b/chromeos/ash/components/auth_panel/views/login_textfield.cc
index 0e3c8929..e11f00c 100644
--- a/chromeos/ash/components/auth_panel/views/login_textfield.cc
+++ b/chromeos/ash/components/auth_panel/views/login_textfield.cc
@@ -9,6 +9,7 @@
 #include "chromeos/ash/components/auth_panel/auth_panel_event_dispatcher.h"
 #include "chromeos/ash/components/auth_panel/views/auth_panel_views_utils.h"
 #include "chromeos/ash/components/auth_panel/views/view_size_constants.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/font_list.h"
 #include "ui/views/border.h"
 
@@ -61,4 +62,7 @@
                        : ui::TEXT_INPUT_TYPE_PASSWORD);
 }
 
+BEGIN_METADATA(LoginTextfield)
+END_METADATA
+
 }  // namespace ash
diff --git a/chromeos/ash/components/auth_panel/views/login_textfield.h b/chromeos/ash/components/auth_panel/views/login_textfield.h
index 01df93a..63cd0dd1 100644
--- a/chromeos/ash/components/auth_panel/views/login_textfield.h
+++ b/chromeos/ash/components/auth_panel/views/login_textfield.h
@@ -8,6 +8,7 @@
 #include "ash/style/system_textfield.h"
 #include "base/memory/raw_ptr.h"
 #include "chromeos/ash/components/auth_panel/auth_factor_store.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace ash {
@@ -18,6 +19,8 @@
 // A textfield that selects all text on focus and allows to switch between
 // show/hide password modes.
 class LoginTextfield : public SystemTextfield {
+  METADATA_HEADER(LoginTextfield, SystemTextfield)
+
  public:
   explicit LoginTextfield(AuthPanelEventDispatcher* dispatcher);
   LoginTextfield(const LoginTextfield&) = delete;
diff --git a/chromeos/ash/components/auth_panel/views/password_auth_view.cc b/chromeos/ash/components/auth_panel/views/password_auth_view.cc
index 8be2d88..82149cb 100644
--- a/chromeos/ash/components/auth_panel/views/password_auth_view.cc
+++ b/chromeos/ash/components/auth_panel/views/password_auth_view.cc
@@ -20,6 +20,8 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/ime/text_input_type.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/image_model.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_provider.h"
@@ -54,6 +56,8 @@
 // The login password row contains the password textfield and different buttons
 // and indicators (easy unlock, display password, caps lock enabled).
 class PasswordAuthView::LoginPasswordRow : public views::View {
+  METADATA_HEADER(LoginPasswordRow, views::View)
+
  public:
   LoginPasswordRow() {
     if (chromeos::features::IsJellyrollEnabled()) {
@@ -84,6 +88,9 @@
   }
 };
 
+BEGIN_METADATA(PasswordAuthView, LoginPasswordRow, views::View)
+END_METADATA
+
 void PasswordAuthView::ConfigureRootLayout() {
   // Contains the password layout on the left and the submit button on the
   // right.
@@ -281,4 +288,7 @@
                                      : capslock_icon_blurred_);
 }
 
+BEGIN_METADATA(PasswordAuthView)
+END_METADATA
+
 }  // namespace ash
diff --git a/chromeos/ash/components/auth_panel/views/password_auth_view.h b/chromeos/ash/components/auth_panel/views/password_auth_view.h
index 5087c42..1677b71 100644
--- a/chromeos/ash/components/auth_panel/views/password_auth_view.h
+++ b/chromeos/ash/components/auth_panel/views/password_auth_view.h
@@ -14,6 +14,7 @@
 #include "base/scoped_observation.h"
 #include "chromeos/ash/components/auth_panel/auth_factor_store.h"
 #include "chromeos/ash/components/auth_panel/factor_auth_view.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/models/image_model.h"
 #include "ui/views/controls/textfield/textfield_controller.h"
 
@@ -44,6 +45,8 @@
 class PasswordAuthView : public FactorAuthView,
                          public views::TextfieldController,
                          public ImeControllerImpl::Observer {
+  METADATA_HEADER(PasswordAuthView, FactorAuthView)
+
  public:
   PasswordAuthView(AuthPanelEventDispatcher* dispatcher,
                    AuthFactorStore* store);
diff --git a/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.cc b/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.cc
index 11dc245b..331d0d5 100644
--- a/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.cc
+++ b/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.cc
@@ -793,6 +793,8 @@
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
     if (!response.has_value()) {
+      // TODO(b/277049005): Set the proper result code once this is disentangled
+      // from the synchronous ListScanners response.
       std::move(callback).Run(absl::nullopt);
       return;
     }
@@ -917,6 +919,7 @@
         // needs to be updated to actually remove devices.
         break;
       case lorgnette::ScannerListChangedSignal::ENUM_COMPLETE: {
+        session.response.set_result(lorgnette::OPERATION_RESULT_SUCCESS);
         lorgnette::StopScannerDiscoveryRequest request;
         request.set_session_id(session.session_id);
         StopScannerDiscovery(request, base::DoNothing());
diff --git a/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client_unittest.cc b/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client_unittest.cc
index 978e395..cd18c9e5 100644
--- a/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client_unittest.cc
+++ b/chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client_unittest.cc
@@ -73,6 +73,7 @@
   scanner.set_type("Type");
 
   lorgnette::ListScannersResponse response;
+  response.set_result(lorgnette::OPERATION_RESULT_SUCCESS);
   *response.add_scanners() = std::move(scanner);
 
   return response;
@@ -1007,6 +1008,7 @@
                 break;
               }
               case lorgnette::ScannerListChangedSignal::SESSION_ENDING:
+                actual_response.set_result(lorgnette::OPERATION_RESULT_SUCCESS);
                 run_loop.Quit();
                 break;
               default:
diff --git a/chromeos/ash/components/scalable_iph/scalable_iph.cc b/chromeos/ash/components/scalable_iph/scalable_iph.cc
index dd073f1..7fe7118f 100644
--- a/chromeos/ash/components/scalable_iph/scalable_iph.cc
+++ b/chromeos/ash/components/scalable_iph/scalable_iph.cc
@@ -189,7 +189,7 @@
 
 constexpr base::TimeDelta kTimeTickEventInterval = base::Minutes(5);
 
-std::string GetEventName(ScalableIph::Event event, Logger* logger) {
+std::string GetEventName(ScalableIph::Event event) {
   // Use switch statement as you can get a compiler error if you forget to add a
   // conversion.
   switch (event) {
@@ -223,6 +223,8 @@
       return kEventNameAppListItemActivationGooglePhotosAndroid;
     case ScalableIph::Event::kPrintJobCreated:
       return kEventNamePrintJobCreated;
+    case ScalableIph::Event::kGameWindowOpened:
+      return kEventNameGameWindowOpened;
   }
 }
 
@@ -827,7 +829,7 @@
     return;
   }
 
-  const std::string event_name = GetEventName(event, GetLogger());
+  const std::string event_name = GetEventName(event);
   SCALABLE_IPH_LOG(GetLogger()) << "Recording event as " << event_name;
   tracker_->NotifyEvent(event_name);
 
@@ -973,8 +975,7 @@
     return true;
   }
 
-  std::string trigger_event_name =
-      GetEventName(trigger_event.value(), GetLogger());
+  std::string trigger_event_name = GetEventName(trigger_event.value());
 
   const bool result = trigger_event_condition == trigger_event_name;
   SCALABLE_IPH_LOG(GetLogger())
@@ -1124,38 +1125,7 @@
 }
 
 std::ostream& operator<<(std::ostream& out, ScalableIph::Event event) {
-  switch (event) {
-    case ScalableIph::Event::kFiveMinTick:
-      return out << "FiveMinTick";
-    case ScalableIph::Event::kUnlocked:
-      return out << "Unlocked";
-    case ScalableIph::Event::kAppListShown:
-      return out << "AppListShown";
-    case ScalableIph::Event::kAppListItemActivationYouTube:
-      return out << "AppListItemActivationYouTube";
-    case ScalableIph::Event::kAppListItemActivationGoogleDocs:
-      return out << "AppListItemActivationGoogleDocs";
-    case ScalableIph::Event::kAppListItemActivationGooglePhotosWeb:
-      return out << "AppListItemActivationGooglePhotosWeb";
-    case ScalableIph::Event::kOpenPersonalizationApp:
-      return out << "OpenPersonalizationApp";
-    case ScalableIph::Event::kShelfItemActivationGoogleDocs:
-      return out << "ShelfItemActivationGoogleDocs";
-    case ScalableIph::Event::kShelfItemActivationYouTube:
-      return out << "ShelfItemActivationYouTube";
-    case ScalableIph::Event::kShelfItemActivationGooglePhotosWeb:
-      return out << "ShelfItemActivationGooglePhotosWeb";
-    case ScalableIph::Event::kShelfItemActivationGooglePhotosAndroid:
-      return out << "ShelfItemActivationGooglePhotosAndroid";
-    case ScalableIph::Event::kShelfItemActivationGooglePlay:
-      return out << "ShelfItemActivationGooglePlay";
-    case ScalableIph::Event::kAppListItemActivationGooglePlayStore:
-      return out << "AppListItemActivationGooglePlayStore";
-    case ScalableIph::Event::kAppListItemActivationGooglePhotosAndroid:
-      return out << "AppListItemActivationGooglePhotosAndroid";
-    case ScalableIph::Event::kPrintJobCreated:
-      return out << "PrintJobCreated";
-  }
+  return out << GetEventName(event);
 }
 
 }  // namespace scalable_iph
diff --git a/chromeos/ash/components/scalable_iph/scalable_iph.h b/chromeos/ash/components/scalable_iph/scalable_iph.h
index 9d264e3..48e4188 100644
--- a/chromeos/ash/components/scalable_iph/scalable_iph.h
+++ b/chromeos/ash/components/scalable_iph/scalable_iph.h
@@ -97,6 +97,7 @@
     kAppListItemActivationGooglePlayStore,
     kAppListItemActivationGooglePhotosAndroid,
     kPrintJobCreated,
+    kGameWindowOpened,
   };
 
   ScalableIph(feature_engagement::Tracker* tracker,
diff --git a/chromeos/ash/components/scalable_iph/scalable_iph_constants.h b/chromeos/ash/components/scalable_iph/scalable_iph_constants.h
index 7fdc4c2..1792c85 100644
--- a/chromeos/ash/components/scalable_iph/scalable_iph_constants.h
+++ b/chromeos/ash/components/scalable_iph/scalable_iph_constants.h
@@ -144,6 +144,10 @@
 // Recorded when a print job is created.
 constexpr char kEventNamePrintJobCreated[] = "ScalableIphPrintJobCreated";
 
+// Recorded when a game window is opened.
+inline constexpr char kEventNameGameWindowOpened[] =
+    "ScalableIphGameWindowOpened";
+
 // `FiveMinTick` event is recorded every five minutes after OOBE completion.
 inline constexpr char kEventNameFiveMinTick[] = "ScalableIphFiveMinTick";
 
diff --git a/clank b/clank
index 9198f75..20d5912 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 9198f75e85bd3e2feed339e5ed10d04e3fb76446
+Subproject commit 20d5912ad65aa985382a75f6883945a2bb40c79a
diff --git a/components/autofill/core/browser/profile_token_quality.cc b/components/autofill/core/browser/profile_token_quality.cc
index cd9981b7..0cc306f 100644
--- a/components/autofill/core/browser/profile_token_quality.cc
+++ b/components/autofill/core/browser/profile_token_quality.cc
@@ -19,6 +19,7 @@
 #include "base/feature_list.h"
 #include "base/rand_util.h"
 #include "base/ranges/algorithm.h"
+#include "base/strings/levenshtein_distance.h"
 #include "base/strings/string_util.h"
 #include "base/types/cxx23_to_underlying.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
@@ -28,7 +29,6 @@
 #include "components/autofill/core/browser/webdata/autofill_table.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_l10n_util.h"
-#include "components/autofill/core/common/autofill_util.h"
 
 namespace autofill {
 
@@ -87,9 +87,10 @@
     return ObservationType::kEditedValueCleared;
   }
 
-  if (LevenshteinDistance(base::ToLowerASCII(profile.GetInfo(type, app_locale)),
-                          base::ToLowerASCII(edited_value),
-                          ProfileTokenQuality::kMaximumLevenshteinDistance) <=
+  if (base::LevenshteinDistance(
+          base::ToLowerASCII(profile.GetInfo(type, app_locale)),
+          base::ToLowerASCII(edited_value),
+          ProfileTokenQuality::kMaximumLevenshteinDistance) <=
       ProfileTokenQuality::kMaximumLevenshteinDistance) {
     return ObservationType::kEditedToSimilarValue;
   }
diff --git a/components/autofill/core/common/autofill_util.cc b/components/autofill/core/common/autofill_util.cc
index aef95b1..6afde06 100644
--- a/components/autofill/core/common/autofill_util.cc
+++ b/components/autofill/core/common/autofill_util.cc
@@ -143,75 +143,6 @@
   return base::ContainsOnlyChars(value, *formatting);
 }
 
-size_t LevenshteinDistance(std::u16string_view a,
-                           std::u16string_view b,
-                           std::optional<size_t> max_distance) {
-  if (a.size() > b.size()) {
-    a.swap(b);
-  }
-
-  // max(a.size(), b.size()) steps always suffice.
-  const size_t k = max_distance.value_or(b.size());
-  // If the string's lengths differ by more than `k`, so does their
-  // Levenshtein distance.
-  if (a.size() + k < b.size()) {
-    return k + 1;
-  }
-  // The classical Levenshtein distance DP defines dp[i][j] as the minimum
-  // number of insert, remove and replace operation to convert a[:i] to b[:j].
-  // To make this more efficient, one can define dp[i][d] as the distance of
-  // a[:i] and b[:i + d]. Intuitively, d represents the delta between j and i in
-  // the former dp. Since the Levenshtein distance is restricted by `k`, abs(d)
-  // can be bounded by `k`. Since dp[i][d] only depends on values from dp[i-1],
-  // it is not necessary to store the entire 2D table. Instead, this code just
-  // stores the d-dimension, which represents "the distance with the current
-  // prefix of the string, for a given delta d". Since d is between `-k` and
-  // `k`, the implementation shifts the d-index by `k`, bringing it in range
-  // [0, `2*k`].
-
-  // The algorithm only cares if the Levenshtein distance is at most `k`. Thus,
-  // any unreachable states and states in which the distance is certainly larger
-  // than `k` can be set to any value larger than `k`, without affecting the
-  // result.
-  const size_t kInfinity = k + 1;
-  std::vector<size_t> dp(2 * k + 1, kInfinity);
-  // Initially, `dp[d]` represents the Levenshtein distance of the empty prefix
-  // of `a` and the first j = d - k characters of `b`. Their distance is j,
-  // since j removals are required. States with negative d are not reachable,
-  // since that corresponds to a negative index into `b`.
-  std::iota(dp.begin() + static_cast<long>(k), dp.end(), 0);
-  for (size_t i = 0; i < a.size(); i++) {
-    // Right now, `dp` represents the Levenshtein distance when considering the
-    // first `i` characters (up to index `i-1`) of `a`. After the next loop,
-    // `dp` will represent the Levenshtein distance when considering the first
-    // `i+1` characters.
-    for (size_t d = 0; d <= 2 * k; d++) {
-      if (i + d < k || i + d >= b.size() + k) {
-        // `j = i + d - k` is out of range of `b`. Since j == -1 corresponds to
-        // the empty prefix of `b`, the distance is i + 1 in this case.
-        dp[d] = i + d + 1 == k ? i + 1 : kInfinity;
-        continue;
-      }
-      const size_t j = i + d - k;
-      // If `a[i] == `b[j]` the Levenshtein distance for `d` remained the same.
-      if (a[i] != b[j]) {
-        // (i, j) -> (i-1, j-1), `d` stays the same.
-        const size_t replace = dp[d];
-        // (i, j) -> (i-1, j), `d` increases by 1.
-        // If the distance between `i` and `j` becomes larger than `k`, their
-        // distance is at least `k + 1`. Same in the `insert` case.
-        const size_t remove = d != 2 * k ? dp[d + 1] : kInfinity;
-        // (i, j) -> (i, j-1), `d` decreases by 1. Since `i` stays the same,
-        // this is intentionally using the dp value updated in the previous
-        // iteration.
-        const size_t insert = d != 0 ? dp[d - 1] : kInfinity;
-        dp[d] = 1 + std::min({replace, remove, insert});
-      }
-    }
-  }
-  return std::min(dp[b.size() + k - a.size()], k + 1);
-}
-
 bool ShouldAutoselectFirstSuggestionOnArrowDown() {
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
     BUILDFLAG(IS_CHROMEOS)
diff --git a/components/autofill/core/common/autofill_util.h b/components/autofill/core/common/autofill_util.h
index 6739fc8..ebc0b68 100644
--- a/components/autofill/core/common/autofill_util.h
+++ b/components/autofill/core/common/autofill_util.h
@@ -67,19 +67,6 @@
 // entered by the website and not a real value entered by the user.
 bool SanitizedFieldIsEmpty(const std::u16string& value);
 
-// Returns the Levenshtein distance of `a` and `b`.
-// If `k = max_distance` is provided, the distance is only correctly calculated
-// up to k. In case the actual Levenshtein distance is larger than k, k+1 is
-// returned instead. This is useful for checking whether the distance is at most
-// some small constant, since the algorithm is more efficient in this case.
-// Edits, inserts and removes each count as one step.
-// Complexity:
-// - Without k: O(|a| * |b|) time and O(max(|a|, |b|)) memory.
-// - With k: O(min(|a|, |b|) * k + k) time and O(k) memory.
-size_t LevenshteinDistance(std::u16string_view a,
-                           std::u16string_view b,
-                           std::optional<size_t> max_distance = std::nullopt);
-
 // Returns true if the first suggestion should be autoselected when the autofill
 // dropdown is shown due to an arrow down event. Enabled on desktop only.
 bool ShouldAutoselectFirstSuggestionOnArrowDown();
diff --git a/components/autofill/core/common/autofill_util_unittest.cc b/components/autofill/core/common/autofill_util_unittest.cc
index 8cbb63e..3437f96 100644
--- a/components/autofill/core/common/autofill_util_unittest.cc
+++ b/components/autofill/core/common/autofill_util_unittest.cc
@@ -142,35 +142,6 @@
         LowercaseAndTokenizeAttributeStringCase{"foO    baR bAz",
                                                 {"foo", "bar", "baz"}}));
 
-TEST(LevenshteinDistanceTest, WithoutMaxDistance) {
-  EXPECT_EQ(LevenshteinDistance(u"aa", u"aa"), 0u);
-  EXPECT_EQ(LevenshteinDistance(u"a", u"aa"), 1u);
-  EXPECT_EQ(LevenshteinDistance(u"aba", u"aa"), 1u);
-  EXPECT_EQ(LevenshteinDistance(u"", u"12"), 2u);
-  EXPECT_EQ(LevenshteinDistance(u"street", u"str."), 3u);
-  EXPECT_EQ(LevenshteinDistance(u"asdf", u"fdsa"), 4u);
-  EXPECT_EQ(
-      LevenshteinDistance(std::u16string(100, 'a'), std::u16string(200, 'a')),
-      100u);
-  EXPECT_EQ(LevenshteinDistance(u"ananas", u"banana"), 2u);
-}
-
-TEST(LevenshteinDistanceTest, WithMaxDistance) {
-  EXPECT_EQ(LevenshteinDistance(u"aa", u"aa", 0), 0u);
-  EXPECT_EQ(LevenshteinDistance(u"a", u"aa", 1), 1u);
-  EXPECT_EQ(LevenshteinDistance(u"ab", u"aa", 2), 1u);
-  EXPECT_EQ(LevenshteinDistance(u"aba", u"aa", 3), 1u);
-
-  // In the case where k is less than the LevenshteinDistance() this should
-  // return k+1.
-  EXPECT_EQ(LevenshteinDistance(u"", u"12", 1), 2u);
-  EXPECT_EQ(LevenshteinDistance(u"street", u"str.", 1), 2u);
-  EXPECT_EQ(LevenshteinDistance(u"asdf", u"fdsa", 2), 3u);
-  EXPECT_EQ(LevenshteinDistance(std::u16string(100, 'a'),
-                                std::u16string(200, 'a'), 50),
-            51u);
-}
-
 TEST(StripAuthAndParamsTest, StripsAll) {
   GURL url = GURL("https://login:password@example.com/login/?param=value#ref");
   EXPECT_EQ(GURL("https://example.com/login/"), StripAuthAndParams(url));
diff --git a/components/compose/core/browser/compose_metrics.cc b/components/compose/core/browser/compose_metrics.cc
index 3b856f1..78e0b14f 100644
--- a/components/compose/core/browser/compose_metrics.cc
+++ b/components/compose/core/browser/compose_metrics.cc
@@ -13,13 +13,14 @@
 const char kComposeResponseDurationOk[] = "Compose.Response.Duration.Ok";
 const char kComposeResponseDurationError[] = "Compose.Response.Duration.Error";
 const char kComposeResponseStatus[] = "Compose.Response.Status";
+const char kComposeShowStatus[] = "Compose.ContextMenu.ShowStatus";
 
 void LogComposeContextMenuCtr(ComposeContextMenuCtrEvent event) {
   UMA_HISTOGRAM_ENUMERATION("Compose.ContextMenu.CTR", event);
 }
 
 void LogComposeContextMenuShowStatus(ComposeShowStatus status) {
-  UMA_HISTOGRAM_ENUMERATION("Compose.ContextMenu.ShowStatus", status);
+  UMA_HISTOGRAM_ENUMERATION(kComposeShowStatus, status);
 }
 
 void LogComposeRequestDuration(base::TimeDelta duration, bool is_valid) {
@@ -27,4 +28,8 @@
       is_valid ? kComposeResponseDurationOk : kComposeResponseDurationError,
       duration);
 }
+
+void LogComposeSessionCloseReason(ComposeSessionCloseReason reason) {
+  UMA_HISTOGRAM_ENUMERATION("Compose.SessionCloseReason", reason);
+}
 }  // namespace compose
diff --git a/components/compose/core/browser/compose_metrics.h b/components/compose/core/browser/compose_metrics.h
index 5937a54a..d1c4e48 100644
--- a/components/compose/core/browser/compose_metrics.h
+++ b/components/compose/core/browser/compose_metrics.h
@@ -15,6 +15,7 @@
 extern const char kComposeResponseDurationOk[];
 extern const char kComposeResponseDurationError[];
 extern const char kComposeResponseStatus[];
+extern const char kComposeShowStatus[];
 
 // Enum for calculating the CTR of the Compose context menu item.
 // These values are persisted to logs. Entries should not be renumbered and
@@ -26,6 +27,14 @@
   kComposeOpened = 1,
   kMaxValue = kComposeOpened,
 };
+// Keep in sync with ComposeContextMenuCtrEvent in
+// src/tools/metrics/histograms/enums.xml.
+enum class ComposeSessionCloseReason {
+  kAcceptedSuggestion = 0,
+  kCloseButtonPressed = 1,
+  kEndedImplicitly = 2,
+  kMaxValue = kEndedImplicitly,
+};
 
 // Enum for recording the show status of the Compose context menu item.
 // These values are persisted to logs. Entries should not be renumbered and
@@ -39,7 +48,8 @@
   kDisabledMsbb = 3,
   kSignedOut = 4,
   kUnsupportedLanguage = 5,
-  kMaxValue = kUnsupportedLanguage,
+  kFormFieldInCrossOriginFrame = 6,
+  kMaxValue = kFormFieldInCrossOriginFrame,
 };
 
 void LogComposeContextMenuCtr(ComposeContextMenuCtrEvent event);
@@ -49,6 +59,9 @@
 // Log the duration of a compose request. |is_valid| indicates the status of
 // the request.
 void LogComposeRequestDuration(base::TimeDelta duration, bool is_ok);
+
+void LogComposeSessionCloseReason(ComposeSessionCloseReason reason);
+
 }  // namespace compose
 
 #endif  // COMPONENTS_COMPOSE_CORE_BROWSER_COMPOSE_METRICS_H_
diff --git a/components/compose/core/browser/config.cc b/components/compose/core/browser/config.cc
index f419b35..b6d54f2 100644
--- a/components/compose/core/browser/config.cc
+++ b/components/compose/core/browser/config.cc
@@ -10,8 +10,6 @@
 
 namespace compose {
 namespace {
-Config g_config;
-
 // Override any parameters that may be provided by Finch.
 void OverrideFieldTrialParams(Config& config) {
   config.input_min_words = base::GetFieldTrialParamByFeatureAsInt(
diff --git a/components/enterprise/common/proto/connectors.proto b/components/enterprise/common/proto/connectors.proto
index dfe1553..65f3c576 100644
--- a/components/enterprise/common/proto/connectors.proto
+++ b/components/enterprise/common/proto/connectors.proto
@@ -240,17 +240,23 @@
     }
     repeated TriggeredRule triggered_rules = 3;
 
+    // TODO(crbug.com/1147036): Remove fields 4-6 once a definitive approach is
+    // agreed upon.
+    optional string malware_family = 4;
+    optional string malware_category = 5;
+    optional string evidence_locker_filepath = 6;
+
     // This field is meant to override the OU-based custom messages set in the
     // client-side policies. When the result requires a
     // warning, if this field has a value it's the one that will be displayed to
     // the user, otherwise the client-side policy's custom message will be used.
     optional CustomMessage custom_message = 7;
 
-    // TODO(crbug.com/1147036): Remove fields 4-6 once a definitive approach is
-    // agreed upon.
-    optional string malware_family = 4;
-    optional string malware_category = 5;
-    optional string evidence_locker_filepath = 6;
+    enum StatusErrorMessage {
+      STATUS_ERROR_MESSAGE_UNSPECIFIED = 0;
+      DECRYPTION_FAILED = 1;
+    }
+    optional StatusErrorMessage status_error_message = 8;
   }
   repeated Result results = 4;
 
diff --git a/components/media_message_center/media_notification_view.h b/components/media_message_center/media_notification_view.h
index 1ac52c6e..956d1a10 100644
--- a/components/media_message_center/media_notification_view.h
+++ b/components/media_message_center/media_notification_view.h
@@ -26,6 +26,7 @@
 class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationView
     : public views::View {
   METADATA_HEADER(MediaNotificationView, views::View)
+
  public:
   // When |forced_expanded_state| has a value, the notification will be forced
   // into that expanded state and the user won't be given a button to toggle the
diff --git a/components/media_message_center/media_notification_view_impl.cc b/components/media_message_center/media_notification_view_impl.cc
index 45fc03e..5e20b39 100644
--- a/components/media_message_center/media_notification_view_impl.cc
+++ b/components/media_message_center/media_notification_view_impl.cc
@@ -797,7 +797,7 @@
   return buttons;
 }
 
-BEGIN_METADATA(MediaNotificationViewImpl, views::View)
+BEGIN_METADATA(MediaNotificationViewImpl)
 ADD_READONLY_PROPERTY_METADATA(bool, Expandable)
 ADD_READONLY_PROPERTY_METADATA(bool, ActuallyExpanded)
 END_METADATA
diff --git a/components/media_message_center/media_notification_view_impl.h b/components/media_message_center/media_notification_view_impl.h
index 6baf3d6..01021573 100644
--- a/components/media_message_center/media_notification_view_impl.h
+++ b/components/media_message_center/media_notification_view_impl.h
@@ -34,9 +34,9 @@
 
 class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationViewImpl
     : public MediaNotificationView {
- public:
-  METADATA_HEADER(MediaNotificationViewImpl);
+  METADATA_HEADER(MediaNotificationViewImpl, MediaNotificationView)
 
+ public:
   // The type of metadata that was displayed. This is used in metrics so new
   // values must only be added to the end.
   enum class Metadata {
diff --git a/components/password_manager/core/browser/sync_credentials_filter.cc b/components/password_manager/core/browser/sync_credentials_filter.cc
index 6268588..3bf73270 100644
--- a/components/password_manager/core/browser/sync_credentials_filter.cc
+++ b/components/password_manager/core/browser/sync_credentials_filter.cc
@@ -21,39 +21,6 @@
 
 namespace password_manager {
 
-namespace {
-
-// Returns true if `url` is google.com domain and `username` corresponds to the
-// account specified by GetAccountEmailIfSyncFeatureEnabledIncludingPasswords.
-// Returns false if GetAccountEmailIfSyncFeatureEnabledIncludingPasswords does
-// not specify any account.
-// TODO(crbug.com/1462552): Remove this function once IsSyncFeatureEnabled()/
-// IsSyncFeatureActive() is fully deprecated, see ConsentLevel::kSync
-// documentation for details.
-bool IsCredentialMatchingSyncFeatureAccount(
-    const GURL& url,
-    const std::u16string& username,
-    const syncer::SyncService* sync_service,
-    const signin::IdentityManager* identity_manager) {
-  if (!url.DomainIs("google.com")) {
-    return false;
-  }
-
-  // The empty username can mean that Chrome did not detect it correctly. For
-  // reasons described in http://crbug.com/636292#c1, the username is suspected
-  // to be the sync username unless proven otherwise.
-  if (username.empty()) {
-    return true;
-  }
-
-  return gaia::AreEmailsSame(
-      base::UTF16ToUTF8(username),
-      sync_util::GetAccountEmailIfSyncFeatureEnabledIncludingPasswords(
-          sync_service, identity_manager));
-}
-
-}  // namespace
-
 SyncCredentialsFilter::SyncCredentialsFilter(
     PasswordManagerClient* client,
     SyncServiceFactoryFunction sync_service_factory_function)
@@ -79,8 +46,21 @@
     // Legacy code path, subject to clean-up.
     // If kEnablePasswordsAccountStorage is NOT enabled, then don't allow saving
     // the password for the sync account specifically.
-    return !IsCredentialMatchingSyncFeatureAccount(
-        form.url, form.username_value, sync_service, identity_manager);
+    if (!form.url.DomainIs("google.com")) {
+      return true;
+    }
+
+    // The empty username can mean that Chrome did not detect it correctly. For
+    // reasons described in http://crbug.com/636292#c1, the username is
+    // suspected to be the sync username unless proven otherwise.
+    if (form.username_value.empty()) {
+      return false;
+    }
+
+    return !gaia::AreEmailsSame(
+        base::UTF16ToUTF8(form.username_value),
+        sync_util::GetAccountEmailIfSyncFeatureEnabledIncludingPasswords(
+            sync_service, identity_manager));
   }
 
   if (!sync_util::IsGaiaCredentialPage(form.signon_realm)) {
@@ -140,14 +120,4 @@
                                        signin::ConsentLevel::kSync);
 }
 
-// static
-bool SyncCredentialsFilter::IsCredentialMatchingSyncFeatureAccountForTest(
-    const GURL& url,
-    const std::u16string& username,
-    const syncer::SyncService* sync_service,
-    const signin::IdentityManager* identity_manager) {
-  return IsCredentialMatchingSyncFeatureAccount(url, username, sync_service,
-                                                identity_manager);
-}
-
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/sync_credentials_filter.h b/components/password_manager/core/browser/sync_credentials_filter.h
index 65d1ae00d..f78993a9 100644
--- a/components/password_manager/core/browser/sync_credentials_filter.h
+++ b/components/password_manager/core/browser/sync_credentials_filter.h
@@ -43,13 +43,6 @@
       const PasswordForm& form) const override;
   bool IsSyncAccountEmail(const std::string& username) const override;
 
-  // For unit-testing purposes only.
-  static bool IsCredentialMatchingSyncFeatureAccountForTest(
-      const GURL& url,
-      const std::u16string& username,
-      const syncer::SyncService* sync_service,
-      const signin::IdentityManager* identity_manager);
-
  private:
   const raw_ptr<PasswordManagerClient> client_;
 
diff --git a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
index 1c848c3..b32af80d 100644
--- a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
+++ b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
@@ -205,20 +205,69 @@
 #endif
 }
 
-TEST_P(CredentialsFilterTest, ShouldSave_NotSyncCredential) {
-  PasswordForm form = SimpleGaiaForm("user@example.org");
+TEST_P(CredentialsFilterTest, ShouldSave_SyncFeatureOnWithPasswordsEnabled) {
+  const char kPrimaryAccountEmail[] = "sync_user@example.org";
 
-  FakeSigninAs("different_user@example.org");
+  FakeSigninAs(kPrimaryAccountEmail);
   SetSyncingPasswords(true);
-  EXPECT_TRUE(filter_->ShouldSave(form));
+
+  // Non-Gaia forms should always offer saving.
+  EXPECT_TRUE(filter_->ShouldSave(SimpleNonGaiaForm(kPrimaryAccountEmail)));
+  EXPECT_TRUE(filter_->ShouldSave(SimpleNonGaiaForm("")));
+
+  // Gaia forms can offer saving only if the username doesn't match the primary
+  // account.
+  EXPECT_FALSE(filter_->ShouldSave(SimpleGaiaForm(kPrimaryAccountEmail)));
+  EXPECT_TRUE(filter_->ShouldSave(SimpleGaiaForm("non_sync_user@example.org")));
+
+  // Some scenarios behave differently based on whether or not the feature
+  // toggle is enabled.
+  // TODO(crbug.com/1499837): Revisit if these differences are desirable.
+  const bool passwords_account_storage_enabled =
+      base::FeatureList::IsEnabled(features::kEnablePasswordsAccountStorage);
+
+  EXPECT_EQ(filter_->ShouldSave(SimpleGaiaForm("")),
+            passwords_account_storage_enabled);
+  EXPECT_EQ(filter_->ShouldSave(SimpleGAIAChangePasswordForm()),
+            passwords_account_storage_enabled);
+  EXPECT_EQ(filter_->ShouldSave(SimpleForm("https://subdomain.google.com/",
+                                           kPrimaryAccountEmail)),
+            passwords_account_storage_enabled);
+  EXPECT_EQ(
+      filter_->ShouldSave(SimpleForm("https://subdomain.google.com/", "")),
+      passwords_account_storage_enabled);
 }
 
-TEST_P(CredentialsFilterTest, ShouldSave_SyncCredential) {
-  PasswordForm form = SimpleGaiaForm("user@example.org");
+TEST_P(CredentialsFilterTest, ShouldSave_SyncFeatureOnWithPasswordsDisabled) {
+  const char kPrimaryAccountEmail[] = "sync_user@example.org";
 
-  FakeSigninAs("user@example.org");
-  SetSyncingPasswords(true);
-  EXPECT_FALSE(filter_->ShouldSave(form));
+  FakeSigninAs(kPrimaryAccountEmail);
+  SetSyncingPasswords(false);
+
+  // Non-Gaia forms should always offer saving.
+  EXPECT_TRUE(filter_->ShouldSave(SimpleNonGaiaForm(kPrimaryAccountEmail)));
+  EXPECT_TRUE(filter_->ShouldSave(SimpleNonGaiaForm("")));
+
+  EXPECT_TRUE(filter_->ShouldSave(SimpleGaiaForm("non_sync_user@example.org")));
+
+  EXPECT_TRUE(filter_->ShouldSave(
+      SimpleForm("https://subdomain.google.com/", kPrimaryAccountEmail)));
+
+  // Some scenarios behave differently based on whether or not the feature
+  // toggle is enabled.
+  // TODO(crbug.com/1499837): Revisit if these differences are desirable.
+  const bool passwords_account_storage_enabled =
+      base::FeatureList::IsEnabled(features::kEnablePasswordsAccountStorage);
+
+  EXPECT_EQ(filter_->ShouldSave(SimpleGaiaForm(kPrimaryAccountEmail)),
+            !passwords_account_storage_enabled);
+  EXPECT_EQ(filter_->ShouldSave(SimpleGaiaForm("")),
+            passwords_account_storage_enabled);
+  EXPECT_EQ(filter_->ShouldSave(SimpleGAIAChangePasswordForm()),
+            passwords_account_storage_enabled);
+  EXPECT_EQ(
+      filter_->ShouldSave(SimpleForm("https://subdomain.google.com/", "")),
+      passwords_account_storage_enabled);
 }
 
 TEST_P(CredentialsFilterTest, ShouldSave_SignIn_Form) {
@@ -229,20 +278,6 @@
   EXPECT_FALSE(filter_->ShouldSave(form));
 }
 
-TEST_P(CredentialsFilterTest, ShouldSave_SyncCredential_NotSyncingPasswords) {
-  PasswordForm form = SimpleGaiaForm("user@example.org");
-
-  FakeSigninAs("user@example.org");
-  SetSyncingPasswords(false);
-  // If kEnablePasswordsAccountStorage is enabled, then Chrome shouldn't offer
-  // to save the password for the primary account - doesn't matter if passwords
-  // are being synced or not.
-  if (base::FeatureList::IsEnabled(features::kEnablePasswordsAccountStorage))
-    EXPECT_FALSE(filter_->ShouldSave(form));
-  else
-    EXPECT_TRUE(filter_->ShouldSave(form));
-}
-
 TEST_P(CredentialsFilterTest, ShouldSaveIfBrowserSigninDisabled) {
   client_->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false);
   EXPECT_TRUE(filter_->ShouldSave(SimpleGaiaForm("user@gmail.com")));
@@ -311,39 +346,6 @@
   EXPECT_TRUE(filter_->IsSyncAccountEmail("user@googlemail.com"));
 }
 
-TEST_P(CredentialsFilterTest, IsCredentialMatchingSyncFeatureAccount) {
-  const struct {
-    PasswordForm form;
-    std::string fake_sync_username;
-    bool expected_result;
-  } kTestCases[] = {
-      {SimpleGaiaForm("sync_user@example.org"), "sync_user@example.org", true},
-      {SimpleGaiaForm("non_sync_user@example.org"), "sync_user@example.org",
-       false},
-      {SimpleNonGaiaForm("sync_user@example.org"), "sync_user@example.org",
-       false},
-      {SimpleGaiaForm(""), "sync_user@example.org", true},
-      {SimpleNonGaiaForm(""), "sync_user@example.org", false},
-      {SimpleGAIAChangePasswordForm(), "sync_user@example.org", true},
-      {SimpleForm("https://subdomain.google.com/", "sync_user@example.org"),
-       "sync_user@example.org", true},
-      {SimpleForm("https://subdomain.google.com/", ""), "sync_user@example.org",
-       true},
-  };
-
-  for (size_t i = 0; i < std::size(kTestCases); ++i) {
-    SCOPED_TRACE(testing::Message() << "i=" << i);
-    SetSyncingPasswords(true);
-    FakeSigninAs(kTestCases[i].fake_sync_username);
-
-    EXPECT_EQ(
-        kTestCases[i].expected_result,
-        SyncCredentialsFilter::IsCredentialMatchingSyncFeatureAccountForTest(
-            kTestCases[i].form.url, kTestCases[i].form.username_value,
-            sync_service(), identity_manager()));
-  }
-}
-
 INSTANTIATE_TEST_SUITE_P(, CredentialsFilterTest, ::testing::Bool());
 
 }  // namespace password_manager
diff --git a/components/plus_addresses/plus_address_metrics.h b/components/plus_addresses/plus_address_metrics.h
index 653070c..3dc51ca 100644
--- a/components/plus_addresses/plus_address_metrics.h
+++ b/components/plus_addresses/plus_address_metrics.h
@@ -43,14 +43,14 @@
   static void RecordAutofillSuggestionEvent(
       PlusAddressAutofillSuggestionEvent
           plus_address_autofill_suggestion_event);
-  // Log latency of `request`.
+  // Log latency of a `type` of network request.
   static void RecordNetworkRequestLatency(PlusAddressNetworkRequestType type,
                                           base::TimeDelta request_latency);
-  // Log the status code of the response to `request`.
+  // Log the status code of the response to a `type` of network request.
   static void RecordNetworkRequestResponseCode(
       PlusAddressNetworkRequestType type,
       int response_code);
-  // Log the size of the response to `request`.
+  // Log the size of the response to a `type` of network request.
   static void RecordNetworkRequestResponseSize(
       PlusAddressNetworkRequestType type,
       int response_size);
diff --git a/components/policy/resources/webui/test/policy_test.ts b/components/policy/resources/webui/test/policy_test.ts
index 95bcd752..014056a 100644
--- a/components/policy/resources/webui/test/policy_test.ts
+++ b/components/policy/resources/webui/test/policy_test.ts
@@ -102,7 +102,7 @@
         PolicyScope.SCOPE_USER_VAL,
     level: Number(LevelNamesToValues[value['level']]) ??
         PolicyLevel.LEVEL_MANDATORY_VAL,
-    value: JSON.stringify(value['value']),
+    value: value['value'],
   };
 
   return policy;
diff --git a/components/previous_session_info/previous_session_info.h b/components/previous_session_info/previous_session_info.h
index 7539f6f..cb8a398 100644
--- a/components/previous_session_info/previous_session_info.h
+++ b/components/previous_session_info/previous_session_info.h
@@ -34,6 +34,8 @@
 extern NSString* const kPreviousSessionInfoMemoryFootprint;
 // Key in the UserDefaults for the number of open tabs.
 extern NSString* const kPreviousSessionInfoTabCount;
+// Key in the UserDefaults for the number of open inactive tabs.
+extern NSString* const kPreviousSessionInfoInactiveTabCount;
 // Key in the UserDefaults for the number of open "off the record" tabs.
 extern NSString* const kPreviousSessionInfoOTRTabCount;
 
@@ -143,6 +145,9 @@
 // Number of open tabs in the previous session.
 @property(nonatomic, readonly) NSInteger tabCount;
 
+// Number of open inactive tabs in the previous session.
+@property(nonatomic, readonly) NSInteger inactiveTabCount;
+
 // Number of open "off the record" tabs in the previous session.
 @property(nonatomic, readonly) NSInteger OTRTabCount;
 
@@ -218,8 +223,10 @@
 // gets destructed.
 - (void)resetSessionRestorationFlag;
 
-// Records number of regular (non off the record) tabs.
+// Records number of regular (non off the record and non inactive) tabs.
 - (void)updateCurrentSessionTabCount:(NSInteger)count;
+// Records number of inactive tabs.
+- (void)updateCurrentSessionInactiveTabCount:(NSInteger)count;
 // Records number of off the record tabs.
 - (void)updateCurrentSessionOTRTabCount:(NSInteger)count;
 
diff --git a/components/previous_session_info/previous_session_info.mm b/components/previous_session_info/previous_session_info.mm
index 129dcf7..e6be803 100644
--- a/components/previous_session_info/previous_session_info.mm
+++ b/components/previous_session_info/previous_session_info.mm
@@ -147,6 +147,8 @@
 NSString* const kPreviousSessionInfoMemoryFootprint =
     @"PreviousSessionInfoMemoryFootprint";
 NSString* const kPreviousSessionInfoTabCount = @"PreviousSessionInfoTabCount";
+NSString* const kPreviousSessionInfoInactiveTabCount =
+    @"PreviousSessionInfoInactiveTabCount";
 NSString* const kPreviousSessionInfoOTRTabCount =
     @"PreviousSessionInfoOTRTabCount";
 NSString* const kPreviousSessionInfoWarmStartCount =
@@ -186,6 +188,7 @@
 @property(nonatomic, assign) NSInteger memoryFootprint;
 @property(nonatomic, assign) BOOL applicationWillTerminateWasReceived;
 @property(nonatomic, assign) NSInteger tabCount;
+@property(nonatomic, assign) NSInteger inactiveTabCount;
 @property(nonatomic, assign) NSInteger OTRTabCount;
 @property(atomic, strong) NSString* breadcrumbs;
 @property(nonatomic, assign) NSInteger warmStartCount;
@@ -290,6 +293,9 @@
     gSharedInstance.tabCount =
         [defaults integerForKey:previous_session_info_constants::
                                     kPreviousSessionInfoTabCount];
+    gSharedInstance.inactiveTabCount =
+        [defaults integerForKey:previous_session_info_constants::
+                                    kPreviousSessionInfoInactiveTabCount];
     gSharedInstance.OTRTabCount =
         [defaults integerForKey:previous_session_info_constants::
                                     kPreviousSessionInfoOTRTabCount];
@@ -642,6 +648,14 @@
   [NSUserDefaults.standardUserDefaults synchronize];
 }
 
+- (void)updateCurrentSessionInactiveTabCount:(NSInteger)count {
+  [NSUserDefaults.standardUserDefaults
+      setInteger:count
+          forKey:previous_session_info_constants::
+                     kPreviousSessionInfoInactiveTabCount];
+  [NSUserDefaults.standardUserDefaults synchronize];
+}
+
 - (void)updateCurrentSessionOTRTabCount:(NSInteger)count {
   [NSUserDefaults.standardUserDefaults
       setInteger:count
diff --git a/components/previous_session_info/previous_session_info_unittest.mm b/components/previous_session_info/previous_session_info_unittest.mm
index cc2b122..1dbefbd 100644
--- a/components/previous_session_info/previous_session_info_unittest.mm
+++ b/components/previous_session_info/previous_session_info_unittest.mm
@@ -17,6 +17,7 @@
 
 using previous_session_info_constants::
     kPreviousSessionInfoConnectedSceneSessionIDs;
+using previous_session_info_constants::kPreviousSessionInfoInactiveTabCount;
 using previous_session_info_constants::kPreviousSessionInfoMemoryFootprint;
 using previous_session_info_constants::kPreviousSessionInfoOTRTabCount;
 using previous_session_info_constants::kPreviousSessionInfoParamsPrefix;
@@ -26,6 +27,7 @@
 namespace {
 
 const NSInteger kTabCount = 15;
+const NSInteger kInactiveTabCount = 30;
 
 // Key in the UserDefaults for a boolean value keeping track of memory warnings.
 NSString* const kDidSeeMemoryWarningShortlyBeforeTerminating =
@@ -630,6 +632,33 @@
                                 objectForKey:kPreviousSessionInfoTabCount]);
 }
 
+// Tests inactiveTabCount property.
+TEST_F(PreviousSessionInfoTest, InactiveTabCount) {
+  [PreviousSessionInfo resetSharedInstanceForTesting];
+  [NSUserDefaults.standardUserDefaults
+      setInteger:kInactiveTabCount
+          forKey:kPreviousSessionInfoInactiveTabCount];
+
+  [[PreviousSessionInfo sharedInstance] beginRecordingCurrentSession];
+  EXPECT_EQ(kInactiveTabCount,
+            [PreviousSessionInfo sharedInstance].inactiveTabCount);
+}
+
+// Tests inactive tab count gets written to NSUserDefaults.
+TEST_F(PreviousSessionInfoTest, InactiveTabCountRecording) {
+  [PreviousSessionInfo resetSharedInstanceForTesting];
+  [NSUserDefaults.standardUserDefaults
+      removeObjectForKey:kPreviousSessionInfoInactiveTabCount];
+
+  [[PreviousSessionInfo sharedInstance] beginRecordingCurrentSession];
+  [[PreviousSessionInfo sharedInstance]
+      updateCurrentSessionInactiveTabCount:kInactiveTabCount];
+
+  EXPECT_NSEQ(@(kInactiveTabCount),
+              [NSUserDefaults.standardUserDefaults
+                  objectForKey:kPreviousSessionInfoInactiveTabCount]);
+}
+
 // Tests OTRTabCount property.
 TEST_F(PreviousSessionInfoTest, OtrTabCount) {
   [PreviousSessionInfo resetSharedInstanceForTesting];
diff --git a/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm b/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
index b8eb13a..53553a70 100644
--- a/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
+++ b/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
@@ -101,10 +101,10 @@
   // NSToolbarFullScreenWindow should never become the key window, otherwise
   // the browser window will appear inactive. Activate the browser window
   // when this happens.
-  if (remote_cocoa::IsNSToolbarFullScreenWindow(notify.object)) {
-    if ([self isOnActiveSpace]) {
-      [self makeKeyAndOrderFront:nil];
-    }
+  NSWindow* toolbarWindow = notify.object;
+  if (toolbarWindow.parentWindow == self &&
+      remote_cocoa::IsNSToolbarFullScreenWindow(toolbarWindow)) {
+    [self makeKeyAndOrderFront:nil];
   }
 }
 
diff --git a/components/security_state/core/security_state.h b/components/security_state/core/security_state.h
index a1399b2..3ba3881 100644
--- a/components/security_state/core/security_state.h
+++ b/components/security_state/core/security_state.h
@@ -63,6 +63,8 @@
   // a MITM was present.
   //
   // Used only on ChromeOS, this status is unreached on other platforms.
+  // TODO(https://crbug.com/1477317): make this work on all platforms when the
+  // non-chromeos-specific policies are added.
   SECURE_WITH_POLICY_INSTALLED_CERT = 4,
 
   // Attempted HTTPS and failed, page not authenticated, HTTPS with
diff --git a/components/services/quarantine/quarantine_win_unittest.cc b/components/services/quarantine/quarantine_win_unittest.cc
index 66903b1..65d46533 100644
--- a/components/services/quarantine/quarantine_win_unittest.cc
+++ b/components/services/quarantine/quarantine_win_unittest.cc
@@ -2,10 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "components/services/quarantine/quarantine.h"
+
 #include <windows.h>
 
 #include <wininet.h>
 
+#include <string_view>
+
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
@@ -19,7 +23,6 @@
 #include "base/win/scoped_com_initializer.h"
 #include "base/win/win_util.h"
 #include "base/win/windows_version.h"
-#include "components/services/quarantine/quarantine.h"
 #include "components/services/quarantine/test_support.h"
 #include "net/base/filename_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -78,7 +81,7 @@
   };
 
   ScopedZoneForSite(base::StringPiece domain,
-                    base::WStringPiece protocol,
+                    std::wstring_view protocol,
                     ZoneIdentifierType zone_identifier_type);
 
   ScopedZoneForSite(const ScopedZoneForSite&) = delete;
@@ -94,7 +97,7 @@
 };
 
 ScopedZoneForSite::ScopedZoneForSite(base::StringPiece domain,
-                                     base::WStringPiece protocol,
+                                     std::wstring_view protocol,
                                      ZoneIdentifierType zone_identifier_type)
     : domain_(base::ASCIIToWide(domain)), protocol_(protocol) {
   base::win::RegKey registry_key(HKEY_CURRENT_USER, GetRegistryPath().c_str(),
diff --git a/components/ssl_errors/error_classification.cc b/components/ssl_errors/error_classification.cc
index 0df71f9..1a4a97a 100644
--- a/components/ssl_errors/error_classification.cc
+++ b/components/ssl_errors/error_classification.cc
@@ -12,6 +12,7 @@
 #include "base/build_time.h"
 #include "base/lazy_instance.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/strings/levenshtein_distance.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
@@ -324,36 +325,6 @@
   return false;
 }
 
-// Returns the Levenshtein distance between |str1| and |str2|.
-// Which is the minimum number of single-character edits (i.e. insertions,
-// deletions or substitutions) required to change one word into the other.
-// https://en.wikipedia.org/wiki/Levenshtein_distance
-size_t GetLevenshteinDistance(const std::string& str1,
-                              const std::string& str2) {
-  if (str1 == str2)
-    return 0;
-  if (str1.size() == 0)
-    return str2.size();
-  if (str2.size() == 0)
-    return str1.size();
-
-  std::vector<size_t> row(str2.size() + 1);
-  for (size_t i = 0; i < row.size(); ++i)
-    row[i] = i;
-
-  for (size_t i = 0; i < str1.size(); ++i) {
-    row[0] = i + 1;
-    size_t previous = i;
-    for (size_t j = 0; j < str2.size(); ++j) {
-      size_t old_row = row[j + 1];
-      int cost = str1[i] == str2[j] ? 0 : 1;
-      row[j + 1] = std::min(std::min(row[j], row[j + 1]) + 1, previous + cost);
-      previous = old_row;
-    }
-  }
-  return row[str2.size()];
-}
-
 bool IsSubDomainOutsideWildcard(const GURL& request_url,
                                 const net::X509Certificate& cert) {
   std::string host_name = request_url.host();
@@ -422,9 +393,11 @@
   static const size_t kMinimumEditDistance = 5;
   for (size_t i = 0; i < dns_names_size; ++i) {
     for (size_t j = i + 1; j < dns_names_size; ++j) {
-      size_t edit_distance = GetLevenshteinDistance(dns_names[i], dns_names[j]);
-      if (edit_distance < kMinimumEditDistance)
+      if (base::LevenshteinDistance(dns_names[i], dns_names[j],
+                                    kMinimumEditDistance - 1) <
+          kMinimumEditDistance) {
         return false;
+      }
     }
   }
   return true;
diff --git a/components/ssl_errors/error_classification.h b/components/ssl_errors/error_classification.h
index 17a43f5e..35c3b92 100644
--- a/components/ssl_errors/error_classification.h
+++ b/components/ssl_errors/error_classification.h
@@ -188,9 +188,6 @@
 bool AnyNamesUnderName(const std::vector<HostnameTokens>& potential_children,
                        const HostnameTokens& parent);
 
-// Exposed for teshting.
-size_t GetLevenshteinDistance(const std::string& str1, const std::string& str2);
-
 }  // namespace ssl_errors
 
 #endif  // COMPONENTS_SSL_ERRORS_ERROR_CLASSIFICATION_H_
diff --git a/components/ssl_errors/error_classification_unittest.cc b/components/ssl_errors/error_classification_unittest.cc
index 13b4078..1386b0e 100644
--- a/components/ssl_errors/error_classification_unittest.cc
+++ b/components/ssl_errors/error_classification_unittest.cc
@@ -210,31 +210,6 @@
   EXPECT_TRUE(ssl_errors::IsHostnameNonUniqueOrDotless("foo.blah"));
 }
 
-TEST_F(SSLErrorClassificationTest, LevenshteinDistance) {
-  EXPECT_EQ(0u, ssl_errors::GetLevenshteinDistance("banana", "banana"));
-
-  EXPECT_EQ(2u, ssl_errors::GetLevenshteinDistance("ab", "ba"));
-  EXPECT_EQ(2u, ssl_errors::GetLevenshteinDistance("ba", "ab"));
-
-  EXPECT_EQ(2u, ssl_errors::GetLevenshteinDistance("ananas", "banana"));
-  EXPECT_EQ(2u, ssl_errors::GetLevenshteinDistance("banana", "ananas"));
-
-  EXPECT_EQ(2u, ssl_errors::GetLevenshteinDistance("unclear", "nuclear"));
-  EXPECT_EQ(2u, ssl_errors::GetLevenshteinDistance("nuclear", "unclear"));
-
-  EXPECT_EQ(3u, ssl_errors::GetLevenshteinDistance("chrome", "chromium"));
-  EXPECT_EQ(3u, ssl_errors::GetLevenshteinDistance("chromium", "chrome"));
-
-  EXPECT_EQ(4u, ssl_errors::GetLevenshteinDistance("", "abcd"));
-  EXPECT_EQ(4u, ssl_errors::GetLevenshteinDistance("abcd", ""));
-
-  EXPECT_EQ(4u, ssl_errors::GetLevenshteinDistance("xxx", "xxxxxxx"));
-  EXPECT_EQ(4u, ssl_errors::GetLevenshteinDistance("xxxxxxx", "xxx"));
-
-  EXPECT_EQ(7u, ssl_errors::GetLevenshteinDistance("yyy", "xxxxxxx"));
-  EXPECT_EQ(7u, ssl_errors::GetLevenshteinDistance("xxxxxxx", "yyy"));
-}
-
 TEST_F(SSLErrorClassificationTest, GetClockState) {
   // This test aims to obtain all possible return values of
   // |GetClockState|.
diff --git a/components/subresource_filter/tools/ruleset_converter/ruleset_converter.cc b/components/subresource_filter/tools/ruleset_converter/ruleset_converter.cc
index 607386a..30e9709 100644
--- a/components/subresource_filter/tools/ruleset_converter/ruleset_converter.cc
+++ b/components/subresource_filter/tools/ruleset_converter/ruleset_converter.cc
@@ -7,6 +7,7 @@
 #include <fstream>
 #include <iostream>
 #include <string>
+#include <string_view>
 
 #include "base/check.h"
 #include "base/files/file_util.h"
@@ -84,7 +85,7 @@
     const base::CommandLine::StringType& comma_separated_paths) {
 #if BUILDFLAG(IS_WIN)
   std::wstring separatorw = L",";
-  base::WStringPiece separator(separatorw);
+  std::wstring_view separator(separatorw);
 #else
   base::StringPiece separator(",");
 #endif
diff --git a/components/translate/core/browser/translate_trigger_decision.h b/components/translate/core/browser/translate_trigger_decision.h
index fe68e77..f5ad65c 100644
--- a/components/translate/core/browser/translate_trigger_decision.h
+++ b/components/translate/core/browser/translate_trigger_decision.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_TRIGGER_DECISION_H_
 #define COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_TRIGGER_DECISION_H_
 
+#include <string>
 #include <vector>
 #include "components/translate/core/browser/translate_browser_metrics.h"
 
diff --git a/components/winhttp/network_fetcher.h b/components/winhttp/network_fetcher.h
index a9cf49c..df182f65 100644
--- a/components/winhttp/network_fetcher.h
+++ b/components/winhttp/network_fetcher.h
@@ -11,6 +11,7 @@
 
 #include <memory>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/containers/flat_map.h"
@@ -20,7 +21,6 @@
 #include "base/memory/raw_ref.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/sequence_checker.h"
-#include "base/strings/string_piece.h"
 #include "components/winhttp/proxy_configuration.h"
 #include "components/winhttp/scoped_hinternet.h"
 #include "url/gurl.h"
@@ -133,7 +133,7 @@
   int port_ = 0;
   std::string path_for_request_;
 
-  base::WStringPiece verb_;
+  std::wstring_view verb_;
   std::string request_data_;
   // The value of Content-Type header, e.g. "application/json".
   std::string content_type_;
diff --git a/content/browser/attribution_reporting/attribution_aggregatable_report_golden_unittest.cc b/content/browser/attribution_reporting/attribution_aggregatable_report_golden_unittest.cc
index f7e2bf75e..04ce447 100644
--- a/content/browser/attribution_reporting/attribution_aggregatable_report_golden_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_aggregatable_report_golden_unittest.cc
@@ -32,7 +32,6 @@
 #include "content/browser/aggregation_service/public_key.h"
 #include "content/browser/attribution_reporting/aggregatable_attribution_utils.h"
 #include "content/browser/attribution_reporting/attribution_test_utils.h"
-#include "content/browser/attribution_reporting/attribution_utils.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/test/browser_task_environment.h"
@@ -155,8 +154,7 @@
                      "AttributionReport::AggregatableAttributionData::kVersion,"
                      " actual output for "
                   << report_file << " is:\n"
-                  << SerializeAttributionJson(report.ReportBody(),
-                                              /*pretty_print=*/true);
+                  << report.ReportBody();
               run_loop.Quit();
             }));
 
diff --git a/content/browser/attribution_reporting/attribution_utils.h b/content/browser/attribution_reporting/attribution_utils.h
index e4b1a94..b4e2170 100644
--- a/content/browser/attribution_reporting/attribution_utils.h
+++ b/content/browser/attribution_reporting/attribution_utils.h
@@ -7,16 +7,14 @@
 
 #include <string>
 
-#include "content/common/content_export.h"
-
 namespace base {
 class ValueView;
 }  // namespace base
 
 namespace content {
 
-CONTENT_EXPORT std::string SerializeAttributionJson(base::ValueView body,
-                                                    bool pretty_print = false);
+std::string SerializeAttributionJson(base::ValueView body,
+                                     bool pretty_print = false);
 
 }  // namespace content
 
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index 35cf0ef..b76215ee 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -356,7 +356,8 @@
 void BindTextSuggestionHostForFrame(
     RenderFrameHost* host,
     mojo::PendingReceiver<blink::mojom::TextSuggestionHost> receiver) {
-  auto* view = static_cast<RenderWidgetHostViewAndroid*>(host->GetView());
+  auto* view =
+      RenderWidgetHostViewAndroid::FromRenderWidgetHostView(host->GetView());
   if (!view || !view->text_suggestion_host())
     return;
 
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc
index b0c4efdd..4ab3c36 100644
--- a/content/browser/media/capture/desktop_capture_device.cc
+++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -886,21 +886,34 @@
 #else
   base::MessagePumpType thread_type = base::MessagePumpType::DEFAULT;
 #endif
-
   bool zero_hertz_is_supported = true;
 #if BUILDFLAG(IS_WIN)
-  if (base::FeatureList::IsEnabled(features::kWebRtcAllowWgcScreenCapturer) ||
-      base::FeatureList::IsEnabled(features::kWebRtcAllowWgcWindowCapturer)) {
-    // TODO(https://crbug.com/1421242): Finalize 0Hz support for WGC.
-    // This feature flag is disabled by default.
-    zero_hertz_is_supported =
-        base::FeatureList::IsEnabled(features::kWebRtcAllowWgcZeroHz);
+  // TODO(https://crbug.com/1421242): Finalize 0Hz support for WGC.
+  const bool wgc_zero_hertz =
+      base::FeatureList::IsEnabled(features::kWebRtcAllowWgcZeroHz);
+  // TODO(https://crbug.com/1421656): 0Hz mode seems to cause a flickering
+  // cursor in some setups. This flag allows us to disable 0Hz when needed.
+  const bool dxgi_gdi_zero_hertz =
+      base::FeatureList::IsEnabled(features::kWebRtcAllowDxgiGdiZeroHz);
+  const bool wgc_screen_capturer =
+      base::FeatureList::IsEnabled(features::kWebRtcAllowWgcScreenCapturer);
+  const bool wgc_window_capturer =
+      base::FeatureList::IsEnabled(features::kWebRtcAllowWgcWindowCapturer);
+  if (!wgc_window_capturer && !wgc_screen_capturer) {
+    zero_hertz_is_supported = dxgi_gdi_zero_hertz;
+  } else if (!wgc_window_capturer && wgc_screen_capturer) {
+    zero_hertz_is_supported = (type == DesktopMediaID::TYPE_SCREEN)
+                                  ? wgc_zero_hertz
+                                  : dxgi_gdi_zero_hertz;
+  } else if (wgc_window_capturer && !wgc_screen_capturer) {
+    zero_hertz_is_supported = (type == DesktopMediaID::TYPE_WINDOW)
+                                  ? wgc_zero_hertz
+                                  : dxgi_gdi_zero_hertz;
   } else {
-    // TODO(https://crbug.com/1421656): 0Hz mode seems to cause a flickering
-    // cursor in some setups. This flag allows us to disable 0Hz when needed.
-    zero_hertz_is_supported =
-        base::FeatureList::IsEnabled(features::kWebRtcAllowDxgiGdiZeroHz);
+    zero_hertz_is_supported = wgc_zero_hertz;
   }
+  VLOG(1) << __func__ << " [zero_hertz_is_supported=" << zero_hertz_is_supported
+          << "]";
 #endif
 
   thread_.StartWithOptions(base::Thread::Options(thread_type, 0));
diff --git a/content/browser/network_service_instance_impl.cc b/content/browser/network_service_instance_impl.cc
index 752500f..40763514 100644
--- a/content/browser/network_service_instance_impl.cc
+++ b/content/browser/network_service_instance_impl.cc
@@ -876,10 +876,19 @@
 
   return GetCertVerifierServiceFactoryRemoteStorage();
 }
-
 network::mojom::CertVerifierServiceRemoteParamsPtr GetCertVerifierParams(
     cert_verifier::mojom::CertVerifierCreationParamsPtr
         cert_verifier_creation_params) {
+  return GetCertVerifierParamsWithUpdater(
+      std::move(cert_verifier_creation_params), mojo::NullReceiver());
+}
+
+network::mojom::CertVerifierServiceRemoteParamsPtr
+GetCertVerifierParamsWithUpdater(
+    cert_verifier::mojom::CertVerifierCreationParamsPtr
+        cert_verifier_creation_params,
+    mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceUpdater>
+        cert_verifier_updater_remote) {
   mojo::PendingRemote<cert_verifier::mojom::CertVerifierService>
       cert_verifier_remote;
   mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceClient>
@@ -887,6 +896,7 @@
 
   GetCertVerifierServiceFactory()->GetNewCertVerifier(
       cert_verifier_remote.InitWithNewPipeAndPassReceiver(),
+      std::move(cert_verifier_updater_remote),
       cert_verifier_client.InitWithNewPipeAndPassRemote(),
       std::move(cert_verifier_creation_params));
 
diff --git a/content/browser/network_service_instance_impl.h b/content/browser/network_service_instance_impl.h
index ec129b5..c753ee8 100644
--- a/content/browser/network_service_instance_impl.h
+++ b/content/browser/network_service_instance_impl.h
@@ -8,6 +8,10 @@
 #include "base/callback_list.h"
 #include "base/functional/callback.h"
 #include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom-forward.h"
+#include "services/network/public/mojom/cert_verifier_service.mojom-forward.h"
+#include "services/network/public/mojom/network_context.mojom-forward.h"
 
 namespace content {
 
@@ -53,6 +57,19 @@
 CONTENT_EXPORT void OnRestartNetworkServiceForTesting(
     base::RepeatingClosure on_restart);
 
+// Returns a CertVerifierParams that can be placed into a new
+// network::mojom::NetworkContextParams.
+//
+// Like |GetCertVerifierParams| but the |cert_verifier_updater_remote| pipe
+// passed in can be used to update the returned CertVerifierService with new
+// verification parameters.
+CONTENT_EXPORT network::mojom::CertVerifierServiceRemoteParamsPtr
+GetCertVerifierParamsWithUpdater(
+    cert_verifier::mojom::CertVerifierCreationParamsPtr
+        cert_verifier_creation_params,
+    mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceUpdater>
+        cert_verifier_updater_remote);
+
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_NETWORK_SERVICE_INSTANCE_IMPL_H_
diff --git a/content/browser/notifications/notification_database.cc b/content/browser/notifications/notification_database.cc
index b3c49adc..d281045 100644
--- a/content/browser/notifications/notification_database.cc
+++ b/content/browser/notifications/notification_database.cc
@@ -260,12 +260,7 @@
       break;
   }
 
-  // Write the changed values to the database.
-  status = WriteNotificationData(origin, *notification_database_data);
-  UMA_HISTOGRAM_ENUMERATION(
-      "Notifications.Database.ReadResultRecordInteraction", status,
-      NotificationDatabase::STATUS_COUNT);
-  return status;
+  return WriteNotificationData(origin, *notification_database_data);
 }
 
 NotificationDatabase::Status NotificationDatabase::ForEachNotificationData(
diff --git a/content/browser/preloading/prefetch/prefetch_network_context.cc b/content/browser/preloading/prefetch/prefetch_network_context.cc
index 29ea76b0..4663e5b 100644
--- a/content/browser/preloading/prefetch/prefetch_network_context.cc
+++ b/content/browser/preloading/prefetch/prefetch_network_context.cc
@@ -110,6 +110,20 @@
       GetReducedUserAgent(base::CommandLine::ForCurrentProcess()->HasSwitch(
                               switches::kUseMobileUserAgent),
                           delegate ? delegate->GetMajorVersionNumber() : "");
+  // The verifier created here does not have the same parameters as used in the
+  // profile (where additional parameters are added in
+  // chrome/browser/net/profile_network_context_service.h
+  // ProfileNetworkContextService::ConfigureNetworkContextParamsInternal, as
+  // well as updates in ProfileNetworkContextService::UpdateCertificatePolicy).
+  //
+  // Currently this does not cause problems as additional parameters only ensure
+  // more requests validate, so the only harm is that prefetch requests will
+  // fail and then later succeed when they are actually fetched. In the future
+  // when additional parameters can cause validations to fail, this will cause
+  // problems.
+  //
+  // TODO(crbug.com/1477317): figure out how to get this verifier in sync with
+  // the profile verifier.
   context_params->cert_verifier_params = GetCertVerifierParams(
       cert_verifier::mojom::CertVerifierCreationParams::New());
   context_params->cors_exempt_header_list = {kCorsExemptPurposeHeaderName};
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 5cf9571f0..95e3acef 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -216,6 +216,17 @@
 
 }  // namespace
 
+// static
+RenderWidgetHostViewAndroid*
+RenderWidgetHostViewAndroid::FromRenderWidgetHostView(
+    RenderWidgetHostView* view) {
+  if (!view || static_cast<RenderWidgetHostViewBase*>(view)
+                   ->IsRenderWidgetHostViewChildFrame()) {
+    return nullptr;
+  }
+  return static_cast<RenderWidgetHostViewAndroid*>(view);
+}
+
 RenderWidgetHostViewAndroid::ScreenStateChangeHandler::ScreenStateChangeHandler(
     RenderWidgetHostViewAndroid* rwhva)
     : rwhva_(rwhva) {}
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 15240b7..86efd55 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -86,6 +86,9 @@
       public ui::ViewAndroidObserver,
       public ui::WindowAndroidObserver {
  public:
+  static RenderWidgetHostViewAndroid* FromRenderWidgetHostView(
+      RenderWidgetHostView* view);
+
   // Note: The tree of `gfx::NativeView` might not match the tree of
   // `cc::slim::Layer`.
   RenderWidgetHostViewAndroid(RenderWidgetHostImpl* widget,
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index c260544..9d047b0 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -96,7 +96,7 @@
 // update it immediately.
 BASE_FEATURE(kDelayUpdateWindowsAfterTextInputStateChanged,
              "DelayUpdateWindowsAfterTextInputStateChanged",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 }  // namespace
 
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 5cb7b6a..b814006 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -83,6 +83,7 @@
 #include "content/browser/navigation_or_document_handle.h"
 #include "content/browser/network/shared_dictionary_util.h"
 #include "content/browser/network_context_client_base_impl.h"
+#include "content/browser/network_service_instance_impl.h"
 #include "content/browser/notifications/platform_notification_context_impl.h"
 #include "content/browser/payments/payment_app_context_impl.h"
 #include "content/browser/preloading/prerender/prerender_final_status.h"
@@ -1667,6 +1668,15 @@
   return network_context_.get();
 }
 
+cert_verifier::mojom::CertVerifierServiceUpdater*
+StoragePartitionImpl::GetCertVerifierServiceUpdater() {
+  DCHECK(initialized_);
+  if (!cert_verifier_service_updater_.is_bound()) {
+    InitNetworkContext();
+  }
+  return cert_verifier_service_updater_.get();
+}
+
 scoped_refptr<network::SharedURLLoaderFactory>
 StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcess() {
   DCHECK(initialized_);
@@ -3359,8 +3369,10 @@
          "NetworkContextParams, as they will be replaced with a new pipe to "
          "the CertVerifierService.";
 
-  context_params->cert_verifier_params =
-      GetCertVerifierParams(std::move(cert_verifier_creation_params));
+  cert_verifier_service_updater_.reset();
+  context_params->cert_verifier_params = GetCertVerifierParamsWithUpdater(
+      std::move(cert_verifier_creation_params),
+      cert_verifier_service_updater_.BindNewPipeAndPassReceiver());
 
   // This mechanisms should be used only for legacy internal headers. You can
   // find a recommended alternative approach on URLRequest::cors_exempt_headers
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index a1b55ae..5ca13f5 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -42,6 +42,7 @@
 #include "mojo/public/cpp/bindings/unique_receiver_set.h"
 #include "net/cookies/cookie_setting_override.h"
 #include "services/network/public/cpp/network_service_buildflags.h"
+#include "services/network/public/mojom/cert_verifier_service.mojom.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "storage/browser/blob/blob_url_registry.h"
@@ -164,6 +165,8 @@
   const StoragePartitionConfig& GetConfig() override;
   base::FilePath GetPath() override;
   network::mojom::NetworkContext* GetNetworkContext() override;
+  cert_verifier::mojom::CertVerifierServiceUpdater*
+  GetCertVerifierServiceUpdater() override;
   network::mojom::URLLoaderFactoryParamsPtr CreateURLLoaderFactoryParams();
   scoped_refptr<network::SharedURLLoaderFactory>
   GetURLLoaderFactoryForBrowserProcess() override;
@@ -755,6 +758,9 @@
   scoped_refptr<URLLoaderFactoryForBrowserProcess>
       shared_url_loader_factory_for_browser_process_;
 
+  mojo::Remote<cert_verifier::mojom::CertVerifierServiceUpdater>
+      cert_verifier_service_updater_;
+
   // URLLoaderFactory/CookieManager for use in the browser process only.
   // See the method comment for
   // StoragePartition::GetURLLoaderFactoryForBrowserProcess() for
diff --git a/content/common/content_switches_internal.cc b/content/common/content_switches_internal.cc
index f6b7908..50728bab 100644
--- a/content/common/content_switches_internal.cc
+++ b/content/common/content_switches_internal.cc
@@ -5,6 +5,7 @@
 #include "content/common/content_switches_internal.h"
 
 #include <string>
+#include <string_view>
 
 #include "base/command_line.h"
 #include "base/metrics/field_trial.h"
@@ -46,7 +47,7 @@
   return base::ASCIIToWide(string);
 }
 
-std::string FromNativeString(base::WStringPiece string) {
+std::string FromNativeString(std::wstring_view string) {
   return base::WideToASCII(string);
 }
 
diff --git a/content/public/browser/network_service_instance.h b/content/public/browser/network_service_instance.h
index 892b969..7078d37 100644
--- a/content/public/browser/network_service_instance.h
+++ b/content/public/browser/network_service_instance.h
@@ -12,6 +12,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom-forward.h"
 #include "services/network/public/cpp/network_connection_tracker.h"
+#include "services/network/public/mojom/cert_verifier_service.mojom-forward.h"
 #include "services/network/public/mojom/network_context.mojom-forward.h"
 
 namespace base {
@@ -81,13 +82,9 @@
 // Returns a CertVerifierParams that can be placed into a new
 // network::mojom::NetworkContextParams.
 //
-// If the CertVerifierService feature is enabled, the
-// |cert_verifier_creation_params| will be used to configure a new
+// The |cert_verifier_creation_params| will be used to configure a new
 // CertVerifierService, and a pipe to the new CertVerifierService will be placed
 // in the CertVerifierParams.
-//
-// Otherwise, |cert_verifier_creation_params| will just be placed directly into
-// the CertVerifierParams to configure an in-network-service CertVerifier.
 CONTENT_EXPORT network::mojom::CertVerifierServiceRemoteParamsPtr
 GetCertVerifierParams(cert_verifier::mojom::CertVerifierCreationParamsPtr
                           cert_verifier_creation_params);
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h
index 2197f11..5d6328f 100644
--- a/content/public/browser/storage_partition.h
+++ b/content/public/browser/storage_partition.h
@@ -18,6 +18,7 @@
 #include "components/services/storage/public/mojom/local_storage_control.mojom-forward.h"
 #include "content/common/content_export.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/mojom/cert_verifier_service.mojom-forward.h"
 #include "services/network/public/mojom/cookie_manager.mojom-forward.h"
 #include "services/network/public/mojom/restricted_cookie_manager.mojom-forward.h"
 #include "services/network/public/mojom/trust_tokens.mojom-forward.h"
@@ -104,6 +105,9 @@
   // caller should not hold onto this pointer beyond the same message loop task.
   virtual network::mojom::NetworkContext* GetNetworkContext() = 0;
 
+  virtual cert_verifier::mojom::CertVerifierServiceUpdater*
+  GetCertVerifierServiceUpdater() = 0;
+
   // Returns the SharedStorageManager for the StoragePartition, or nullptr if it
   // doesn't exist because the feature is disabled.
   virtual storage::SharedStorageManager* GetSharedStorageManager() = 0;
diff --git a/content/public/test/test_storage_partition.cc b/content/public/test/test_storage_partition.cc
index 6199438a..13bda86a 100644
--- a/content/public/test/test_storage_partition.cc
+++ b/content/public/test/test_storage_partition.cc
@@ -26,6 +26,10 @@
 network::mojom::NetworkContext* TestStoragePartition::GetNetworkContext() {
   return network_context_;
 }
+cert_verifier::mojom::CertVerifierServiceUpdater*
+TestStoragePartition::GetCertVerifierServiceUpdater() {
+  return nullptr;
+}
 
 storage::SharedStorageManager* TestStoragePartition::GetSharedStorageManager() {
   return nullptr;
diff --git a/content/public/test/test_storage_partition.h b/content/public/test/test_storage_partition.h
index 959f8ff7..ecaece3a 100644
--- a/content/public/test/test_storage_partition.h
+++ b/content/public/test/test_storage_partition.h
@@ -16,6 +16,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/storage_partition_config.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "services/network/public/mojom/cert_verifier_service.mojom.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 
 namespace blink {
@@ -62,6 +63,8 @@
     network_context_ = context;
   }
   network::mojom::NetworkContext* GetNetworkContext() override;
+  cert_verifier::mojom::CertVerifierServiceUpdater*
+  GetCertVerifierServiceUpdater() override;
 
   storage::SharedStorageManager* GetSharedStorageManager() override;
 
diff --git a/device/fido/enclave/test/passkey_enclave_client.cc b/device/fido/enclave/test/passkey_enclave_client.cc
index 7cd3d77..9c9097d 100644
--- a/device/fido/enclave/test/passkey_enclave_client.cc
+++ b/device/fido/enclave/test/passkey_enclave_client.cc
@@ -175,6 +175,7 @@
       factory_remote.BindNewPipeAndPassReceiver());
   factory_->GetNewCertVerifier(
       cert_verifier_remote.InitWithNewPipeAndPassReceiver(),
+      /*updater_receiver=*/mojo::NullReceiver(),
       cert_verifier_client.InitWithNewPipeAndPassRemote(),
       cert_verifier::mojom::CertVerifierCreationParams::New());
 
diff --git a/device/fido/win/logging.cc b/device/fido/win/logging.cc
index 88df573c..705f7d3 100644
--- a/device/fido/win/logging.cc
+++ b/device/fido/win/logging.cc
@@ -5,6 +5,7 @@
 #include "device/fido/win/logging.h"
 
 #include <string>
+#include <string_view>
 
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
@@ -24,7 +25,7 @@
   return "\"" + result + "\"";
 }
 
-std::wstring Quoted(base::WStringPiece in) {
+std::wstring Quoted(std::wstring_view in) {
   std::wstring result;
   base::ReplaceChars(in, L"\\", L"\\\\", &result);
   base::ReplaceChars(result, L"\"", L"\\\"", &result);
@@ -32,7 +33,7 @@
 }
 
 std::wstring Quoted(const wchar_t* in) {
-  return Quoted(base::WStringPiece(in ? in : L""));
+  return Quoted(std::wstring_view(in ? in : L""));
 }
 
 }  // namespace
diff --git a/device/gamepad/raw_input_gamepad_device_win.cc b/device/gamepad/raw_input_gamepad_device_win.cc
index baf183b0..51d57fe 100644
--- a/device/gamepad/raw_input_gamepad_device_win.cc
+++ b/device/gamepad/raw_input_gamepad_device_win.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <string_view>
+
 #include "raw_input_gamepad_device_win.h"
 
 // NOTE: <hidsdi.h> must be included before <hidpi.h>. clang-format will want to
@@ -395,7 +397,7 @@
   }
 
   // Remove trailing NUL characters.
-  buffer = std::wstring(base::TrimString(buffer, base::WStringPiece(L"\0", 1),
+  buffer = std::wstring(base::TrimString(buffer, std::wstring_view(L"\0", 1),
                                          base::TRIM_TRAILING));
 
   // The product string cannot be empty.
diff --git a/docs/rust.md b/docs/rust.md
index 25e381b..190b2b83 100644
--- a/docs/rust.md
+++ b/docs/rust.md
@@ -105,6 +105,15 @@
 //third_party/rust/foo/v4/patches/0002-Other-changes.diff
 ```
 
+The recommended procedure to create such patches is:
+
+1. Commit the plain new version of the crate to your local git branch
+2. Modify the crate as necessary
+3. Commit that modified version
+4. Use `git format-patch <unpatched version>` to generate the patch files
+5. Add the patch files in a new, third, commit
+6. Squash them, or rely on `git cl upload` doing so
+
 ### Updating existing third-party crates
 
 To update a crate "foo" to the latest version you must just re-import it at this
diff --git a/docs/testing/code_coverage_in_gerrit.md b/docs/testing/code_coverage_in_gerrit.md
index 266b993..aae7ff59 100644
--- a/docs/testing/code_coverage_in_gerrit.md
+++ b/docs/testing/code_coverage_in_gerrit.md
@@ -19,7 +19,12 @@
 classified into Unit Tests coverage(coverage from just unit tests) and All Tests coverage(covererd by all tests running in CQ, including unit tests). All Tests coverage is a superset of Unit Tests coverage.
 
 To further dig into specific lines that are not covered by tests, **look at the
-right column of the side by side diff view**. It only shows All Tests Coverage right now
+right column of the side by side diff view, and specifically notice the
+background color of each line number**, where a light orange color indicates
+missing coverage and a light blue color indicates existing coverage. Moreover
+hovering over the line number shows an informative tooltip with
+"Not covered by tests" or "Covered by tests" text respectively. It only shows
+All Tests Coverage right now
 
 ![code_coverage_annotations]
 
diff --git a/extensions/browser/bad_message.h b/extensions/browser/bad_message.h
index 28776b68..3de03e8 100644
--- a/extensions/browser/bad_message.h
+++ b/extensions/browser/bad_message.h
@@ -71,6 +71,7 @@
   EMF_INVALID_OPEN_CHANNEL_TO_NATIVE_APP_FROM_NATIVE_HOST = 30,
   EFH_NO_BACKGROUND_HOST_FOR_FRAME = 31,
   LEGACY_IPC_MISMATCH = 32,
+  ER_SW_INVALID_LAZY_BACKGROUND_PARAM = 33,
   // Please add new elements here. The naming convention is abbreviated class
   // name (e.g. ExtensionHost becomes EH) plus a unique description of the
   // reason. After making changes, you MUST update histograms.xml by running:
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc
index e0bdba4..2c4b72e8 100644
--- a/extensions/browser/event_router.cc
+++ b/extensions/browser/event_router.cc
@@ -1218,7 +1218,8 @@
 
 void EventRouter::DecrementInFlightEventsForServiceWorker(
     const WorkerId& worker_id,
-    int event_id) {
+    int event_id,
+    bool event_will_run_in_lazy_background_page_script) {
   auto* process = RenderProcessHost::FromID(worker_id.render_process_id);
   // Check to make sure the rendered process hasn't gone away by the time
   // we've gotten here. (It's possible it has crashed, etc.) If that's
@@ -1227,6 +1228,12 @@
   if (!process) {
     return;
   }
+
+  if (event_will_run_in_lazy_background_page_script) {
+    bad_message::ReceivedBadMessage(
+        process, bad_message::ER_SW_INVALID_LAZY_BACKGROUND_PARAM);
+  }
+
   const bool worker_stopped = !ProcessManager::Get(process->GetBrowserContext())
                                    ->HasServiceWorker(worker_id);
   content::ServiceWorkerContext* service_worker_context =
@@ -1245,7 +1252,8 @@
 void EventRouter::DecrementInFlightEventsForRenderFrameHost(
     int render_process_host,
     const ExtensionId& extension_id,
-    int event_id) {
+    int event_id,
+    bool event_will_run_in_lazy_background_page_script) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   auto* process = RenderProcessHost::FromID(render_process_host);
   if (!process) {
@@ -1255,7 +1263,7 @@
   ProcessManager* pm = ProcessManager::Get(process->GetBrowserContext());
   ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id);
   if (host) {
-    host->OnEventAck(event_id);
+    host->OnEventAck(event_id, event_will_run_in_lazy_background_page_script);
   }
 }
 
diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h
index bcd9658..e47c9a4 100644
--- a/extensions/browser/event_router.h
+++ b/extensions/browser/event_router.h
@@ -480,12 +480,16 @@
                                base::TimeTicks dispatch_start_time,
                                int64_t service_worker_version_id,
                                EventDispatchSource dispatch_source);
-  void DecrementInFlightEventsForServiceWorker(const WorkerId& worker_id,
-                                               int event_id);
+  void DecrementInFlightEventsForServiceWorker(
+      const WorkerId& worker_id,
+      int event_id,
+      // Always false since this is only possibly true for lazy background page.
+      bool event_will_run_in_lazy_background_page_script);
   void DecrementInFlightEventsForRenderFrameHost(
       int render_process_host,
       const ExtensionId& extension_id,
-      int event_id);
+      int event_id,
+      bool event_will_run_in_lazy_background_page_script);
 
   void RouteDispatchEvent(
       content::RenderProcessHost* rph,
diff --git a/extensions/browser/event_router_unittest.cc b/extensions/browser/event_router_unittest.cc
index 338363a0..cc6e718 100644
--- a/extensions/browser/event_router_unittest.cc
+++ b/extensions/browser/event_router_unittest.cc
@@ -89,7 +89,8 @@
   void DispatchEvent(mojom::DispatchEventParamsPtr params,
                      base::Value::List event_args,
                      DispatchEventCallback callback) override {
-    std::move(callback).Run();
+    std::move(callback).Run(
+        /*event_will_run_in_lazy_background_page_script=*/false);
   }
 
  private:
diff --git a/extensions/browser/extension_host.cc b/extensions/browser/extension_host.cc
index bf2c4d83..9a4af1b 100644
--- a/extensions/browser/extension_host.cc
+++ b/extensions/browser/extension_host.cc
@@ -317,7 +317,9 @@
 }
 #endif
 
-void ExtensionHost::OnEventAck(int event_id) {
+void ExtensionHost::OnEventAck(
+    int event_id,
+    bool event_will_run_in_lazy_background_page_script) {
   // This should always be true since event acks are only sent by extensions
   // with lazy background pages but it doesn't hurt to be extra careful.
   const bool is_background_page = IsBackgroundPage();
@@ -352,17 +354,28 @@
 
   const UnackedEventData& unacked_message_data = it->second;
 
-  // Only emit events that use the EventRouter::DispatchEventToProcess() event
-  // routing flow since EventRouter::DispatchEventToSender() uses a different
-  // flow that doesn't include dispatch start and service worker start time.
-  if (unacked_messages_[event_id].dispatch_source ==
-      EventDispatchSource::kDispatchEventToProcess) {
-    base::UmaHistogramCustomMicrosecondsTimes(
-        "Extensions.Events.DispatchToAckTime.ExtensionEventPage2",
-        /*sample=*/base::TimeTicks::Now() -
-            unacked_message_data.dispatch_start_time,
-        /*min=*/base::Microseconds(1), /*max=*/base::Minutes(5),
-        /*buckets=*/100);
+  // From the browser side, we add an in-flight event (`unacked_messages_`) for
+  // every event that goes to an extension process for an extension with a lazy
+  // background page, whether or not the event is going to be received by the
+  // background page. On the browser side, we can't easily determine if an event
+  // will be handled in the background page. Instead, here we rely on a signal
+  // from the renderer that the event ran in the background page and only emit
+  // background-related metrics if that's the case.
+  // TODO(crbug.com/1470045): Remove this condition once crbug.com/1470045
+  // allows us to only ack for lazy background page events.
+  if (event_will_run_in_lazy_background_page_script) {
+    // Only emit events that use the EventRouter::DispatchEventToProcess() event
+    // routing flow since EventRouter::DispatchEventToSender() uses a different
+    // flow that doesn't include dispatch start and service worker start time.
+    if (unacked_messages_[event_id].dispatch_source ==
+        EventDispatchSource::kDispatchEventToProcess) {
+      base::UmaHistogramCustomMicrosecondsTimes(
+          "Extensions.Events.DispatchToAckTime.ExtensionEventPage3",
+          /*sample=*/base::TimeTicks::Now() -
+              unacked_message_data.dispatch_start_time,
+          /*min=*/base::Microseconds(1), /*max=*/base::Minutes(5),
+          /*buckets=*/100);
+    }
   }
 
   EventRouter* router = EventRouter::Get(browser_context_);
diff --git a/extensions/browser/extension_host.h b/extensions/browser/extension_host.h
index 316d778..5439ec6b 100644
--- a/extensions/browser/extension_host.h
+++ b/extensions/browser/extension_host.h
@@ -178,7 +178,10 @@
                            const Extension* extension,
                            UnloadedExtensionReason reason) override;
 
-  void OnEventAck(int event_id);
+  // Notifies observers when an event has been acknowledged from the renderer to
+  // the browser. `event_ran_in_lazy_background_page_context` being set to true
+  // emits histograms for some events that ran in lazy background pages.
+  void OnEventAck(int event_id, bool event_ran_in_lazy_background_page_context);
 
  protected:
   // Called each time this ExtensionHost completes a load finishes loading,
diff --git a/extensions/common/extension_messages.h b/extensions/common/extension_messages.h
index 004db2a..aaaa0b0 100644
--- a/extensions/common/extension_messages.h
+++ b/extensions/common/extension_messages.h
@@ -226,7 +226,9 @@
 // Messages sent from the renderer to the browser:
 
 // Notify the browser that an event has finished being dispatched.
-IPC_MESSAGE_ROUTED1(ExtensionHostMsg_EventAck, int /* message_id */)
+IPC_MESSAGE_ROUTED2(ExtensionHostMsg_EventAck,
+                    int /* message_id */,
+                    bool /* event_will_run_in_lazy_background_page_script */)
 
 // Open a channel to all listening contexts owned by the extension with
 // the given ID. This responds asynchronously with ExtensionMsg_AssignPortId.
diff --git a/extensions/common/mojom/event_dispatcher.mojom b/extensions/common/mojom/event_dispatcher.mojom
index 1afb311..fe4f7e5 100644
--- a/extensions/common/mojom/event_dispatcher.mojom
+++ b/extensions/common/mojom/event_dispatcher.mojom
@@ -12,10 +12,17 @@
 // pages, or a web renderer, for content script listeners).
 // The interface is implemented in //extensions/renderer code, and is
 // called on the browser side by the EventRouter.
+// `event_will_run_in_lazy_background_page_script` indicates that during the
+// event dispatch the event will, at least, run in a lazy background page
+// script. It is should always be false for service workers.
 interface EventDispatcher {
     // Sent to the renderer to dispatch an event to a listener.
     DispatchEvent(DispatchEventParams params,
-                  mojo_base.mojom.ListValue event_args) => ();
+                  mojo_base.mojom.ListValue event_args) => (
+                    // TODO(crbug.com/1470045): Remove this variable once
+                    // crbug.com/1470045  allows us to only ack for lazy
+                    // background page events.
+                    bool event_will_run_in_lazy_background_page_script);
 };
 
 struct EventFilteringInfo {
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index c99fb86..2eaef1b 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -1383,6 +1383,14 @@
   CHECK_EQ(params->worker_thread_id, kMainThreadId);
   content::RenderFrame* background_frame =
       ExtensionFrameHelper::GetBackgroundPageFrame(params->extension_id);
+  ScriptContext* background_context = nullptr;
+  if (background_frame) {
+    background_context =
+        ScriptContextSet::GetMainWorldContextForFrame(background_frame);
+  }
+  bool event_has_listener_in_background_context =
+      background_context && bindings_system_->HasEventListenerInContext(
+                                params->event_name, background_context);
 
   // Synthesize a user gesture if this was in response to user action; this is
   // necessary if the gesture was e.g. by clicking on the extension toolbar
@@ -1393,14 +1401,10 @@
   // the user gesture. This is intentional, since frames other than the
   // background page should have their own user gestures, such as through button
   // clicks.
-  if (params->is_user_gesture && background_frame) {
-    ScriptContext* background_context =
-        ScriptContextSet::GetMainWorldContextForFrame(background_frame);
-    if (background_context && bindings_system_->HasEventListenerInContext(
-                                  params->event_name, background_context)) {
-      background_frame->GetWebFrame()->NotifyUserActivation(
-          blink::mojom::UserActivationNotificationType::kExtensionEvent);
-    }
+  if (params->is_user_gesture && background_context &&
+      event_has_listener_in_background_context) {
+    background_frame->GetWebFrame()->NotifyUserActivation(
+        blink::mojom::UserActivationNotificationType::kExtensionEvent);
   }
 
   DispatchEventHelper(params->extension_id, params->event_name, event_args,
@@ -1414,11 +1418,12 @@
         RendererExtensionRegistry::Get()->GetByID(params->extension_id);
     if (extension && BackgroundInfo::HasLazyBackgroundPage(extension)) {
       background_frame->Send(new ExtensionHostMsg_EventAck(
-          background_frame->GetRoutingID(), params->event_id));
+          background_frame->GetRoutingID(), params->event_id,
+          event_has_listener_in_background_context));
     }
   }
 #endif
-  std::move(callback).Run();
+  std::move(callback).Run(event_has_listener_in_background_context);
 }
 
 void Dispatcher::SetDeveloperMode(bool current_developer_mode) {
diff --git a/extensions/renderer/service_worker_data.cc b/extensions/renderer/service_worker_data.cc
index db05225..f69783f65 100644
--- a/extensions/renderer/service_worker_data.cc
+++ b/extensions/renderer/service_worker_data.cc
@@ -144,7 +144,10 @@
   bindings_system()->DispatchEventInContext(params->event_name, event_args,
                                             std::move(params->filtering_info),
                                             context());
-  std::move(callback).Run();
+
+  std::move(callback).Run(
+      // False since this is only possibly true for lazy background page.
+      /*event_will_run_in_lazy_background_page_script=*/false);
 }
 
 void ServiceWorkerData::DispatchOnConnect(
diff --git a/extensions/renderer/worker_thread_dispatcher.cc b/extensions/renderer/worker_thread_dispatcher.cc
index b6e6412..90839ac8 100644
--- a/extensions/renderer/worker_thread_dispatcher.cc
+++ b/extensions/renderer/worker_thread_dispatcher.cc
@@ -466,7 +466,10 @@
   // Note that this will run right away on the IO thread and the worker thread
   // will not have processed the event. The browser does not use this callback
   // when ENABLE_EXTENSIONS_LEGACY_IPC is enabled so this is fine.
-  std::move(callback).Run();
+  // `event_will_run_in_lazy_background_page_script` will always be false since
+  // this event will run for a service worker not a lazy background page.
+  std::move(callback).Run(
+      /*event_will_run_in_lazy_background_page_script=*/false);
 }
 
 void WorkerThreadDispatcher::OnDispatchOnConnect(
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 0fe4b1f..c635320 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -96682,7 +96682,7 @@
         seconds: 120
       }
       build_numbers: YES
-      service_account: "chromium-cipd-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
       task_template_canary_percentage {
         value: 5
       }
diff --git a/infra/config/generated/testing/test_suites.pyl b/infra/config/generated/testing/test_suites.pyl
index 4491776..60c705a 100644
--- a/infra/config/generated/testing/test_suites.pyl
+++ b/infra/config/generated/testing/test_suites.pyl
@@ -7470,6 +7470,10 @@
       'lacros_skylab_tests': {
         'variants': [
           'CROS_JACUZZI_RELEASE_LKGM',
+        ],
+      },
+      'lacros_skylab_tests_version_skew': {
+        'variants': [
           'CROS_JACUZZI_RELEASE_DEV',
           'CROS_JACUZZI_RELEASE_BETA',
           'CROS_JACUZZI_RELEASE_STABLE',
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl
index 1323e4d..9e427c25 100644
--- a/infra/config/generated/testing/variants.pyl
+++ b/infra/config/generated/testing/variants.pyl
@@ -70,16 +70,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 121.0.6115.0',
+    'description': 'Run with ash-chrome version 121.0.6116.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v121.0.6115.0',
-          'revision': 'version:121.0.6115.0',
+          'location': 'lacros_version_skew_tests_v121.0.6116.0',
+          'revision': 'version:121.0.6116.0',
         },
       ],
     },
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.infra.star b/infra/config/subprojects/chromium/try/tryserver.chromium.infra.star
index cdffdad..39da6008 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.infra.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.infra.star
@@ -90,4 +90,5 @@
     os = os.LINUX_DEFAULT,
     contact_team_email = "chrome-browser-infra-team@google.com",
     execution_timeout = 36 * time.hour,  # We expect it can take a while.
+    service_account = try_.DEFAULT_SERVICE_ACCOUNT,
 )
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json
index 9e20cc0..81564be 100644
--- a/infra/config/targets/lacros-version-skew-variants.json
+++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -1,16 +1,16 @@
 {
   "LACROS_VERSION_SKEW_CANARY": {
     "args": [
-      "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome"
+      "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome"
     ],
-    "description": "Run with ash-chrome version 121.0.6115.0",
+    "description": "Run with ash-chrome version 121.0.6116.0",
     "identifier": "Lacros version skew testing ash canary",
     "swarming": {
       "cipd_packages": [
         {
           "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-          "location": "lacros_version_skew_tests_v121.0.6115.0",
-          "revision": "version:121.0.6115.0"
+          "location": "lacros_version_skew_tests_v121.0.6116.0",
+          "revision": "version:121.0.6116.0"
         }
       ]
     }
diff --git a/infra/config/targets/matrix_compound_suites.star b/infra/config/targets/matrix_compound_suites.star
index 221f5850..0df6a09 100644
--- a/infra/config/targets/matrix_compound_suites.star
+++ b/infra/config/targets/matrix_compound_suites.star
@@ -1003,6 +1003,10 @@
         "lacros_skylab_tests": targets.legacy_matrix_config(
             variants = [
                 "CROS_JACUZZI_RELEASE_LKGM",
+            ],
+        ),
+        "lacros_skylab_tests_version_skew": targets.legacy_matrix_config(
+            variants = [
                 "CROS_JACUZZI_RELEASE_DEV",
                 "CROS_JACUZZI_RELEASE_BETA",
                 "CROS_JACUZZI_RELEASE_STABLE",
diff --git a/ios/chrome/browser/crash_report/model/crash_helper_unittest.mm b/ios/chrome/browser/crash_report/model/crash_helper_unittest.mm
index 7e48f7c6..359de51 100644
--- a/ios/chrome/browser/crash_report/model/crash_helper_unittest.mm
+++ b/ios/chrome/browser/crash_report/model/crash_helper_unittest.mm
@@ -67,6 +67,7 @@
   crash_keys::SetCurrentHorizontalSizeClass(2);
   crash_keys::SetCurrentUserInterfaceStyle(2);
   crash_keys::SetRegularTabCount(999);
+  crash_keys::SetInactiveTabCount(999);
   crash_keys::SetIncognitoTabCount(999);
   crash_keys::SetForegroundScenesCount(999);
   crash_keys::SetConnectedScenesCount(999);
@@ -96,11 +97,11 @@
   EXPECT_NSEQ(reportParameters[@"memory_warning_count"], @"2");
   EXPECT_NSEQ(reportParameters[@"crashed_in_background"], @"yes");
   EXPECT_NSEQ(reportParameters[@"free_memory_in_kb"], @"1234");
-  EXPECT_NSEQ(
-      reportParameters[@"user_application_state"],
-      @"{\"OTRTabs\":999,\"avplay\":1,\"destroyingAndRebuildingOTR\":1,"
-      @"\"fgScenes\":999,\"orient\":37,\"pdf\":1,\"regTabs\":999,\"scenes\":"
-      @"999,\"signIn\":1,\"sizeclass\":2,\"user_interface_style\":2}");
+  EXPECT_NSEQ(reportParameters[@"user_application_state"],
+              @"{\"OTRTabs\":999,\"avplay\":1,\"destroyingAndRebuildingOTR\":1,"
+              @"\"fgScenes\":999,\"inactiveTabs\":999,\"orient\":37,\"pdf\":1,"
+              @"\"regTabs\":999,\"scenes\":999,\"signIn\":1,\"sizeclass\":2,"
+              @"\"user_interface_style\":2}");
   EXPECT_NSEQ(reportParameters[@"free_disk_in_kb"], @"12345");
   EXPECT_NSEQ(reportParameters[@"memory_warning_in_progress"], @"yes");
 }
diff --git a/ios/chrome/browser/crash_report/model/crash_keys_helper.h b/ios/chrome/browser/crash_report/model/crash_keys_helper.h
index c308e7aa..58835413 100644
--- a/ios/chrome/browser/crash_report/model/crash_keys_helper.h
+++ b/ios/chrome/browser/crash_report/model/crash_keys_helper.h
@@ -71,6 +71,9 @@
 // Sets a key in browser_state dictionary to store the count of regular tabs.
 void SetRegularTabCount(int tabCount);
 
+// Sets a key in browser_state dictionary to store the count of inactive tabs.
+void SetInactiveTabCount(int tabCount);
+
 // Sets a key in browser_state dictionary to store the count of incognito tabs.
 void SetIncognitoTabCount(int tabCount);
 
diff --git a/ios/chrome/browser/crash_report/model/crash_keys_helper.mm b/ios/chrome/browser/crash_report/model/crash_keys_helper.mm
index c12b4de..faf4e71 100644
--- a/ios/chrome/browser/crash_report/model/crash_keys_helper.mm
+++ b/ios/chrome/browser/crash_report/model/crash_keys_helper.mm
@@ -37,6 +37,7 @@
 char const kVideoPlaying[] = "avplay";
 char const kIncognitoTabCount[] = "OTRTabs";
 char const kRegularTabCount[] = "regTabs";
+char const kInactiveTabCount[] = "inactiveTabs";
 char const kConnectedScenes[] = "scenes";
 char const kForegroundScenes[] = "fgScenes";
 char const kDestroyingAndRebuildingIncognitoBrowserState[] =
@@ -187,6 +188,13 @@
   [[PreviousSessionInfo sharedInstance] updateCurrentSessionTabCount:tabCount];
 }
 
+void SetInactiveTabCount(int tabCount) {
+  [[CrashReportUserApplicationState sharedInstance] setValue:kInactiveTabCount
+                                                   withValue:tabCount];
+  [[PreviousSessionInfo sharedInstance]
+      updateCurrentSessionInactiveTabCount:tabCount];
+}
+
 void SetIncognitoTabCount(int tabCount) {
   [[CrashReportUserApplicationState sharedInstance] setValue:kIncognitoTabCount
                                                    withValue:tabCount];
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index a6173a7..8647471 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -921,16 +921,6 @@
      flag_descriptions::kOverflowMenuCustomizationName,
      flag_descriptions::kOverflowMenuCustomizationDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kOverflowMenuCustomization)},
-    {"enable-lens-in-home-screen-widget",
-     flag_descriptions::kEnableLensInHomeScreenWidgetName,
-     flag_descriptions::kEnableLensInHomeScreenWidgetDescription,
-     flags_ui::kOsIos, FEATURE_VALUE_TYPE(kEnableLensInHomeScreenWidget)},
-    {"enable-lens-in-keyboard", flag_descriptions::kEnableLensInKeyboardName,
-     flag_descriptions::kEnableLensInKeyboardDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(kEnableLensInKeyboard)},
-    {"enable-lens-in-ntp", flag_descriptions::kEnableLensInNTPName,
-     flag_descriptions::kEnableLensInNTPDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(kEnableLensInNTP)},
     {"enable-lens-in-omnibox-copied-image",
      flag_descriptions::kEnableLensInOmniboxCopiedImageName,
      flag_descriptions::kEnableLensInOmniboxCopiedImageDescription,
@@ -1523,10 +1513,6 @@
      FEATURE_WITH_PARAMS_VALUE_TYPE(kTabResumption,
                                     kTabResumptionVariations,
                                     "TabResumption")},
-    {"ios-lens-use-direct-upload",
-     flag_descriptions::kIOSLensUseDirectUploadName,
-     flag_descriptions::kIOSLensUseDirectUploadDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(kIOSLensUseDirectUpload)},
     {"autofill-enable-payments-mandatory-reauth-on-bling",
      flag_descriptions::kAutofillEnablePaymentsMandatoryReauthOnBlingName,
      flag_descriptions::
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 498e2430..bd8151e0 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -1014,32 +1014,6 @@
     "When enabled, the Fakebox on Home appears larger and has an updated "
     "design.";
 
-const char kIOSLensUseDirectUploadName[] =
-    "Use direct upload for Lens searches";
-const char kIOSLensUseDirectUploadDescription[] =
-    "When enabled, use the direct upload Lens endpoint when searching images "
-    "with Lens.";
-
-const char kEnableLensInHomeScreenWidgetName[] =
-    "Enable Google Lens in the Home Screen Widget";
-const char kEnableLensInHomeScreenWidgetDescription[] =
-    "When enabled, use Lens to search for images from your device camera "
-    "menu when Google is the selected search engine, accessible from the"
-    "home screen widget.";
-
-const char kEnableLensInKeyboardName[] =
-    "Enable Google Lens in the Omnibox Keyboard";
-const char kEnableLensInKeyboardDescription[] =
-    "When enabled, use Lens to search for images from your device camera "
-    "menu when Google is the selected search engine, accessible from the"
-    "omnibox keyboard.";
-
-const char kEnableLensInNTPName[] = "Enable Google Lens in the NTP";
-const char kEnableLensInNTPDescription[] =
-    "When enabled, use Lens to search for images from your device camera "
-    "menu when Google is the selected search engine, accessible from the"
-    "new tab page.";
-
 const char kEnableLensInOmniboxCopiedImageName[] =
     "Enable Google Lens in the Omnibox for Copied Images";
 const char kEnableLensInOmniboxCopiedImageDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index a2ab5151..76f8605e 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -880,11 +880,6 @@
 extern const char kThemeColorInTopToolbarName[];
 extern const char kThemeColorInTopToolbarDescription[];
 
-// Title and description for the flag to enable using Lens to search using
-// the device camera from the home screen widget.
-extern const char kEnableLensInHomeScreenWidgetName[];
-extern const char kEnableLensInHomeScreenWidgetDescription[];
-
 // Title and description for the flag to enable the iOS Hide Feed with Search
 // Choice feature.
 extern const char kIOSHideFeedWithSearchChoiceName[];
@@ -894,21 +889,6 @@
 extern const char kIOSLargeFakeboxName[];
 extern const char kIOSLargeFakeboxDescription[];
 
-// Title and description for the flag to enable using direct upload for
-// Lens searches in iOS.
-extern const char kIOSLensUseDirectUploadName[];
-extern const char kIOSLensUseDirectUploadDescription[];
-
-// Title and description for the flag to enable using Lens to search using
-// the device camera from the keyboard.
-extern const char kEnableLensInKeyboardName[];
-extern const char kEnableLensInKeyboardDescription[];
-
-// Title and description for the flag to enable using Lens to search using
-// the device camera from the ntp.
-extern const char kEnableLensInNTPName[];
-extern const char kEnableLensInNTPDescription[];
-
 // Title and description for the flag to enable using Lens to search using
 // copied images in the omnibox.
 extern const char kEnableLensInOmniboxCopiedImageName[];
diff --git a/ios/chrome/browser/lens/lens_browser_agent.mm b/ios/chrome/browser/lens/lens_browser_agent.mm
index 96a8333..00311b5 100644
--- a/ios/chrome/browser/lens/lens_browser_agent.mm
+++ b/ios/chrome/browser/lens/lens_browser_agent.mm
@@ -114,25 +114,12 @@
   // experience.
   switch (entry_point.value()) {
     case LensEntrypoint::Keyboard:
-      if (!base::FeatureList::IsEnabled(kEnableLensInKeyboard)) {
-        return std::nullopt;
-      }
-      break;
     case LensEntrypoint::NewTabPage:
-      if (!base::FeatureList::IsEnabled(kEnableLensInNTP)) {
-        return std::nullopt;
-      }
-      break;
     case LensEntrypoint::HomeScreenWidget:
-      if (!base::FeatureList::IsEnabled(kEnableLensInHomeScreenWidget)) {
-        return std::nullopt;
-      }
-      break;
+      return entry_point;
     default:
       return std::nullopt;
   }
-
-  return entry_point;
 }
 
 #pragma mark - BrowserObserver
diff --git a/ios/chrome/browser/link_to_text/model/link_to_text_java_script_feature.h b/ios/chrome/browser/link_to_text/model/link_to_text_java_script_feature.h
index 8635f79..10bc2a9 100644
--- a/ios/chrome/browser/link_to_text/model/link_to_text_java_script_feature.h
+++ b/ios/chrome/browser/link_to_text/model/link_to_text_java_script_feature.h
@@ -5,13 +5,14 @@
 #ifndef IOS_CHROME_BROWSER_LINK_TO_TEXT_MODEL_LINK_TO_TEXT_JAVA_SCRIPT_FEATURE_H_
 #define IOS_CHROME_BROWSER_LINK_TO_TEXT_MODEL_LINK_TO_TEXT_JAVA_SCRIPT_FEATURE_H_
 
-#include "base/gtest_prod_util.h"
+#import <optional>
+
+#import "base/gtest_prod_util.h"
 #import "base/memory/weak_ptr.h"
 #import "base/no_destructor.h"
 #import "base/values.h"
 #import "ios/chrome/browser/link_to_text/model/link_to_text_response.h"
 #import "ios/web/public/js_messaging/java_script_feature.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class ElapsedTimer;
@@ -63,7 +64,7 @@
       std::vector<LinkToTextResponse*> responses);
 
   static bool ShouldAttemptIframeGeneration(
-      absl::optional<shared_highlighting::LinkGenerationError> error,
+      std::optional<shared_highlighting::LinkGenerationError> error,
       const GURL& main_frame_url);
 
   LinkToTextJavaScriptFeature(const LinkToTextJavaScriptFeature&) = delete;
diff --git a/ios/chrome/browser/link_to_text/model/link_to_text_java_script_feature.mm b/ios/chrome/browser/link_to_text/model/link_to_text_java_script_feature.mm
index e456034f..8cdecb4 100644
--- a/ios/chrome/browser/link_to_text/model/link_to_text_java_script_feature.mm
+++ b/ios/chrome/browser/link_to_text/model/link_to_text_java_script_feature.mm
@@ -78,7 +78,7 @@
 
 // static
 bool LinkToTextJavaScriptFeature::ShouldAttemptIframeGeneration(
-    absl::optional<shared_highlighting::LinkGenerationError> error,
+    std::optional<shared_highlighting::LinkGenerationError> error,
     const GURL& main_frame_url) {
   if (!base::FeatureList::IsEnabled(
           shared_highlighting::kSharedHighlightingAmp)) {
@@ -101,7 +101,7 @@
       linkToTextResponseWithValue:response
                          webState:web_state.get()
                           latency:link_generation_timer.Elapsed()];
-  absl::optional<shared_highlighting::LinkGenerationError> error =
+  std::optional<shared_highlighting::LinkGenerationError> error =
       [parsed_response error];
 
   std::vector<web::WebFrame*> amp_frames;
diff --git a/ios/chrome/browser/link_to_text/model/link_to_text_response.h b/ios/chrome/browser/link_to_text/model/link_to_text_response.h
index ef5fe8a..cec6050b 100644
--- a/ios/chrome/browser/link_to_text/model/link_to_text_response.h
+++ b/ios/chrome/browser/link_to_text/model/link_to_text_response.h
@@ -7,10 +7,11 @@
 
 #import <UIKit/UIKit.h>
 
-#include "base/time/time.h"
+#import <optional>
+
+#import "base/time/time.h"
 #import "components/shared_highlighting/core/common/shared_highlighting_metrics.h"
 #import "ios/chrome/browser/link_to_text/model/link_generation_outcome.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 #import "url/gurl.h"
 
 namespace base {
@@ -42,7 +43,7 @@
 // Error which occurred when trying to generate a link. Empty when `payload`
 // has a value.
 @property(nonatomic, readonly)
-    absl::optional<shared_highlighting::LinkGenerationError>
+    std::optional<shared_highlighting::LinkGenerationError>
         error;
 
 // Source ID for the associated WebState.
diff --git a/ios/chrome/browser/link_to_text/model/link_to_text_response.mm b/ios/chrome/browser/link_to_text/model/link_to_text_response.mm
index e22b67c..ecaf8f2 100644
--- a/ios/chrome/browser/link_to_text/model/link_to_text_response.mm
+++ b/ios/chrome/browser/link_to_text/model/link_to_text_response.mm
@@ -97,7 +97,7 @@
   }
 
   const base::Value::Dict& dict = value->GetDict();
-  absl::optional<LinkGenerationOutcome> outcome =
+  std::optional<LinkGenerationOutcome> outcome =
       link_to_text::ParseStatus(dict.FindDouble("status"));
   if (!outcome.has_value()) {
     return [self linkToTextResponseWithUnknownErrorAndSourceID:sourceID
@@ -114,10 +114,10 @@
 
   // Attempts to parse a payload from the response.
   NSString* title = tab_util::GetTabTitle(webState);
-  absl::optional<TextFragment> fragment =
+  std::optional<TextFragment> fragment =
       TextFragment::FromValue(dict.Find("fragment"));
   const std::string* selectedText = dict.FindString("selectedText");
-  absl::optional<CGRect> sourceRect =
+  std::optional<CGRect> sourceRect =
       shared_highlighting::ParseRect(dict.FindDict("selectionRect"));
 
   // All values must be present to have a valid payload.
@@ -128,7 +128,7 @@
   }
 
   GURL baseURL = webState->GetLastCommittedURL();
-  absl::optional<GURL> canonicalURL =
+  std::optional<GURL> canonicalURL =
       shared_highlighting::ParseURL(dict.FindString("canonicalUrl"));
 
   // Use the canonical URL as base when it exists, and only on HTTPS pages.
diff --git a/ios/chrome/browser/link_to_text/model/link_to_text_tab_helper.mm b/ios/chrome/browser/link_to_text/model/link_to_text_tab_helper.mm
index de2e699a..592eb10 100644
--- a/ios/chrome/browser/link_to_text/model/link_to_text_tab_helper.mm
+++ b/ios/chrome/browser/link_to_text/model/link_to_text_tab_helper.mm
@@ -13,7 +13,6 @@
 #import "ios/web/public/js_messaging/web_frames_manager.h"
 #import "ios/web/public/ui/crw_web_view_proxy.h"
 #import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 #import "url/gurl.h"
 
 // Interface encapsulating the properties needed to check the contents of the
diff --git a/ios/chrome/browser/link_to_text/model/link_to_text_utils.h b/ios/chrome/browser/link_to_text/model/link_to_text_utils.h
index 71fd9ce..1637428e 100644
--- a/ios/chrome/browser/link_to_text/model/link_to_text_utils.h
+++ b/ios/chrome/browser/link_to_text/model/link_to_text_utils.h
@@ -5,9 +5,10 @@
 #ifndef IOS_CHROME_BROWSER_LINK_TO_TEXT_MODEL_LINK_TO_TEXT_UTILS_H_
 #define IOS_CHROME_BROWSER_LINK_TO_TEXT_MODEL_LINK_TO_TEXT_UTILS_H_
 
+#import <optional>
+
 #import "components/shared_highlighting/core/common/shared_highlighting_metrics.h"
 #import "ios/chrome/browser/link_to_text/model/link_generation_outcome.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class TimeDelta;
@@ -18,8 +19,7 @@
 // Attempts to convert a numerical `status` value from the
 // text-fragments-polyfill library into a LinkGenerationOutcome enum
 // value, representing outcomes for that library.
-absl::optional<LinkGenerationOutcome> ParseStatus(
-    absl::optional<double> status);
+std::optional<LinkGenerationOutcome> ParseStatus(std::optional<double> status);
 
 // Converts a given text-fragments-polyfill library error `outcome` to its
 // LinkGenerationError counterpart.
diff --git a/ios/chrome/browser/link_to_text/model/link_to_text_utils.mm b/ios/chrome/browser/link_to_text/model/link_to_text_utils.mm
index e8ca226..82a4982 100644
--- a/ios/chrome/browser/link_to_text/model/link_to_text_utils.mm
+++ b/ios/chrome/browser/link_to_text/model/link_to_text_utils.mm
@@ -12,16 +12,15 @@
 
 namespace link_to_text {
 
-absl::optional<LinkGenerationOutcome> ParseStatus(
-    absl::optional<double> status) {
+std::optional<LinkGenerationOutcome> ParseStatus(std::optional<double> status) {
   if (!status.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   int status_value = static_cast<int>(status.value());
   if (status_value < 0 ||
       status_value > static_cast<int>(LinkGenerationOutcome::kMaxValue)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return static_cast<LinkGenerationOutcome>(status_value);
diff --git a/ios/chrome/browser/link_to_text/model/link_to_text_utils_unittest.mm b/ios/chrome/browser/link_to_text/model/link_to_text_utils_unittest.mm
index ef4674c..09060b0 100644
--- a/ios/chrome/browser/link_to_text/model/link_to_text_utils_unittest.mm
+++ b/ios/chrome/browser/link_to_text/model/link_to_text_utils_unittest.mm
@@ -21,12 +21,12 @@
        ++i) {
     LinkGenerationOutcome expected_outcome =
         static_cast<LinkGenerationOutcome>(i);
-    absl::optional<double> status = static_cast<double>(i);
+    std::optional<double> status = static_cast<double>(i);
     EXPECT_EQ(expected_outcome, ParseStatus(status).value());
   }
 
   // Invalid values.
-  EXPECT_FALSE(ParseStatus(absl::nullopt).has_value());
+  EXPECT_FALSE(ParseStatus(std::nullopt).has_value());
   EXPECT_FALSE(ParseStatus(-1).has_value());
   EXPECT_FALSE(
       ParseStatus(static_cast<int>(LinkGenerationOutcome::kMaxValue) + 1)
diff --git a/ios/chrome/browser/overlays/model/public/infobar_modal/save_address_profile_infobar_modal_overlay_request_config.h b/ios/chrome/browser/overlays/model/public/infobar_modal/save_address_profile_infobar_modal_overlay_request_config.h
index 27f22f4..de2515d 100644
--- a/ios/chrome/browser/overlays/model/public/infobar_modal/save_address_profile_infobar_modal_overlay_request_config.h
+++ b/ios/chrome/browser/overlays/model/public/infobar_modal/save_address_profile_infobar_modal_overlay_request_config.h
@@ -6,6 +6,9 @@
 #define IOS_CHROME_BROWSER_OVERLAYS_MODEL_PUBLIC_INFOBAR_MODAL_SAVE_ADDRESS_PROFILE_INFOBAR_MODAL_OVERLAY_REQUEST_CONFIG_H_
 
 #import <UIKit/UIKit.h>
+
+#include <optional>
+
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
 #include "ios/chrome/browser/overlays/model/public/overlay_request_config.h"
@@ -63,7 +66,7 @@
 
   bool is_migration_to_account() const { return is_migration_to_account_; }
 
-  absl::optional<std::u16string> user_email() const { return user_email_; }
+  std::optional<std::u16string> user_email() const { return user_email_; }
 
   bool is_profile_an_account_profile() const {
     return is_profile_an_account_profile_;
@@ -108,7 +111,7 @@
   bool is_profile_an_account_profile_ = false;
 
   // Denotes the email address of the signed-in account.
-  absl::optional<std::u16string> user_email_;
+  std::optional<std::u16string> user_email_;
 
   // Denotes the profile description shown in the migration prompt.
   std::u16string profile_description_for_migration_prompt_;
diff --git a/ios/chrome/browser/policy/policy_app_interface.mm b/ios/chrome/browser/policy/policy_app_interface.mm
index b645208..13b6fb0 100644
--- a/ios/chrome/browser/policy/policy_app_interface.mm
+++ b/ios/chrome/browser/policy/policy_app_interface.mm
@@ -9,7 +9,8 @@
 
 #import "base/files/file_path.h"
 #import "base/files/file_util.h"
-#import "base/json/json_string_value_serializer.h"
+#import "base/json/json_reader.h"
+#import "base/json/json_writer.h"
 #import "base/path_service.h"
 #import "base/strings/sys_string_conversions.h"
 #import "base/task/thread_pool.h"
@@ -55,35 +56,27 @@
 // `value` is nullptr, returns a string representing a `base::Value` of type
 // NONE.
 NSString* SerializeValue(const base::Value* value) {
-  base::Value none_value(base::Value::Type::NONE);
-
   if (!value) {
-    value = &none_value;
+    // The representation for base::Value::Type::NONE, according to the
+    // JSON spec at https://www.json.org/json-en.html
+    return @"null";
   }
-  DCHECK(value);
 
-  std::string serialized_value;
-  JSONStringValueSerializer serializer(&serialized_value);
-  serializer.Serialize(*value);
-  return base::SysUTF8ToNSString(serialized_value);
+  const std::optional<std::string> json_string = base::WriteJson(*value);
+  return base::SysUTF8ToNSString(json_string.value_or(std::string()));
 }
 
 // Takes a JSON-encoded string representing a `base::Value`, and deserializes
 // into a `base::Value` pointer. If nullptr is given, returns a pointer to a
 // `base::Value` of type NONE.
 std::optional<base::Value> DeserializeValue(NSString* json_value) {
-  if (!json_value) {
-    return base::Value(base::Value::Type::NONE);
+  if (!json_value.length) {
+    return base::Value();
   }
 
-  std::string json = base::SysNSStringToUTF8(json_value);
-  JSONStringValueDeserializer deserializer(json);
-  std::unique_ptr<base::Value> value =
-      deserializer.Deserialize(/*error_code=*/nullptr,
-                               /*error_message=*/nullptr);
-  return value ? absl::make_optional<base::Value>(std::move(*value))
-               : std::nullopt;
+  return base::JSONReader::Read(base::SysNSStringToUTF8(json_value));
 }
+
 }  // namespace
 
 @implementation PolicyAppInterface
diff --git a/ios/chrome/browser/shared/public/features/features.mm b/ios/chrome/browser/shared/public/features/features.mm
index 911bde1..3d400c59 100644
--- a/ios/chrome/browser/shared/public/features/features.mm
+++ b/ios/chrome/browser/shared/public/features/features.mm
@@ -150,22 +150,6 @@
              "kIOSNewOmniboxImplementation",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-BASE_FEATURE(kIOSLensUseDirectUpload,
-             "IOSLensUseDirectUpload",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
-BASE_FEATURE(kEnableLensInHomeScreenWidget,
-             "EnableLensInHomeScreenWidget",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
-BASE_FEATURE(kEnableLensInKeyboard,
-             "EnableLensInKeyboard",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
-BASE_FEATURE(kEnableLensInNTP,
-             "EnableLensInNTP",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 BASE_FEATURE(kEnableLensInOmniboxCopiedImage,
              "EnableLensInOmniboxCopiedImage",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_item_view.mm b/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_item_view.mm
index 135d4bb..a156de0 100644
--- a/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_item_view.mm
+++ b/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_item_view.mm
@@ -23,10 +23,10 @@
 namespace {
 
 // The spacing between the title and description.
-constexpr CGFloat kTitleDescriptionSpacing = 5;
+constexpr CGFloat kTitleDescriptionSpacing = 2;
 
 // The spacing between elements within the item.
-constexpr CGFloat kContentStackSpacing = 16;
+constexpr CGFloat kContentStackSpacing = 14;
 
 // Constants related to the icon container view.
 constexpr CGFloat kIconContainerSize = 56;
diff --git a/ios/chrome/browser/ui/lens/lens_availability.mm b/ios/chrome/browser/ui/lens/lens_availability.mm
index 430d4771..38c868f 100644
--- a/ios/chrome/browser/ui/lens/lens_availability.mm
+++ b/ios/chrome/browser/ui/lens/lens_availability.mm
@@ -28,9 +28,6 @@
 bool CheckAndLogAvailabilityForLensEntryPoint(
     LensEntrypoint entry_point,
     BOOL is_google_default_search_engine) {
-  // Check if the feature is enabled for the entry point. Starts at
-  // YES to account for removing flags for launched features.
-  BOOL flag_enabled = YES;
   const char* availability_metric_name = nullptr;
 
   switch (entry_point) {
@@ -38,42 +35,21 @@
       availability_metric_name = kIOSLensContextMenuSupportStatusHistogramName;
       break;
     case LensEntrypoint::Keyboard:
-      if (!base::FeatureList::IsEnabled(kEnableLensInKeyboard)) {
-        flag_enabled = NO;
-      }
       availability_metric_name = kIOSLensKeyboardSupportStatusHistogramName;
       break;
     case LensEntrypoint::NewTabPage:
-      if (!base::FeatureList::IsEnabled(kEnableLensInNTP)) {
-        flag_enabled = NO;
-      }
       availability_metric_name = kIOSLensNewTabPageSupportStatusHistogramName;
       break;
     case LensEntrypoint::HomeScreenWidget:
-      if (!base::FeatureList::IsEnabled(kEnableLensInHomeScreenWidget)) {
-        flag_enabled = NO;
-      }
       // Home screen widget cannot log availailability.
       break;
     case LensEntrypoint::AppIconLongPress:
-      // App icon entrypoint is controlled by the home screen widget flag.
-      if (!base::FeatureList::IsEnabled(kEnableLensInHomeScreenWidget)) {
-        flag_enabled = NO;
-      }
       // App icon long press cannot log availailability.
       break;
     case LensEntrypoint::Spotlight:
-      // Spotlight entrypoint is controlled by the home screen widget flag.
-      if (!base::FeatureList::IsEnabled(kEnableLensInHomeScreenWidget)) {
-        flag_enabled = NO;
-      }
       availability_metric_name = kIOSSpotlightSupportStatusHistogramName;
       break;
     case LensEntrypoint::PlusButton:
-      // Plus Button entrypoint is controlled by the ntp flag.
-      if (!base::FeatureList::IsEnabled(kEnableLensInNTP)) {
-        flag_enabled = NO;
-      }
       availability_metric_name = kIOSPlusButtonSupportStatusHistogramName;
       break;
     default:
@@ -83,8 +59,6 @@
   LensSupportStatus lens_support_status;
   if (!ios::provider::IsLensSupported()) {
     lens_support_status = LensSupportStatus::ProviderUnsupported;
-  } else if (!flag_enabled) {
-    lens_support_status = LensSupportStatus::DisabledByFlag;
   } else if (!GetApplicationContext()->GetLocalState()->GetBoolean(
                  prefs::kLensCameraAssistedSearchPolicyAllowed)) {
     lens_support_status = LensSupportStatus::DisabledByEnterprisePolicy;
diff --git a/ios/chrome/browser/ui/lens/lens_coordinator.mm b/ios/chrome/browser/ui/lens/lens_coordinator.mm
index 29180668..ced5c91 100644
--- a/ios/chrome/browser/ui/lens/lens_coordinator.mm
+++ b/ios/chrome/browser/ui/lens/lens_coordinator.mm
@@ -454,7 +454,6 @@
   // is determined elsewhere in the Extension Search Engine Data Updater.
   const bool enableLensInWidget =
       ios::provider::IsLensSupported() &&
-      base::FeatureList::IsEnabled(kEnableLensInHomeScreenWidget) &&
       GetApplicationContext()->GetLocalState()->GetBoolean(
           prefs::kLensCameraAssistedSearchPolicyAllowed) &&
       ui::GetDeviceFormFactor() != ui::DEVICE_FORM_FACTOR_TABLET;
diff --git a/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_keyboard_accessory_view.mm b/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_keyboard_accessory_view.mm
index 030a2590..67194181 100644
--- a/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_keyboard_accessory_view.mm
+++ b/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_keyboard_accessory_view.mm
@@ -125,7 +125,6 @@
   // Create and add a stackview containing the leading assistive buttons, i.e.
   // Voice search, camera/Lens search and paste search.
   BOOL useLens = ios::provider::IsLensSupported() &&
-                 base::FeatureList::IsEnabled(kEnableLensInKeyboard) &&
                  [self isGoogleSearchEngine:self.templateURLService];
   NSArray<UIControl*>* leadingControls =
       OmniboxAssistiveKeyboardLeadingControls(_delegate, self.pasteTarget,
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_formatter.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_formatter.mm
index b9a76d7..d0b95fea 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_formatter.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_formatter.mm
@@ -14,14 +14,10 @@
 namespace {
 
 OmniboxSuggestionIconType IconTypeFromMatch(const AutocompleteMatch& match) {
-  std::optional<int> answerType =
-      match.answer.has_value() ? absl::make_optional<int>(match.answer->type())
-                               : std::nullopt;
-
   // Some suggestions have custom icons. Others fallback to the icon from the
   // overall match type.
-  if (answerType) {
-    switch (answerType.value()) {
+  if (match.answer.has_value()) {
+    switch (match.answer.value().type()) {
       case SuggestionAnswer::ANSWER_TYPE_DICTIONARY:
         return OmniboxSuggestionIconType::kDictionary;
       case SuggestionAnswer::ANSWER_TYPE_FINANCE:
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/autofill_address_profile/save_address_profile_infobar_banner_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_banner/autofill_address_profile/save_address_profile_infobar_banner_overlay_mediator_unittest.mm
index 6e011447b..30aae21 100644
--- a/ios/chrome/browser/ui/overlays/infobar_banner/autofill_address_profile/save_address_profile_infobar_banner_overlay_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/autofill_address_profile/save_address_profile_infobar_banner_overlay_mediator_unittest.mm
@@ -46,7 +46,7 @@
       passed_delegate = std::make_unique<
           autofill::AutofillSaveUpdateAddressProfileDelegateIOS>(
           profile, /*original_profile=*/nullptr,
-          /*user_email=*/absl::nullopt,
+          /*user_email=*/std::nullopt,
           /*locale=*/"en-US",
           autofill::AutofillClient::SaveAddressProfilePromptOptions{},
           base::DoNothing());
@@ -86,7 +86,7 @@
       passed_delegate = std::make_unique<
           autofill::AutofillSaveUpdateAddressProfileDelegateIOS>(
           profile, /*original_profile=*/nullptr,
-          /*user_email=*/absl::nullopt,
+          /*user_email=*/std::nullopt,
           /*locale=*/"en-US",
           autofill::AutofillClient::SaveAddressProfilePromptOptions{},
           base::DoNothing());
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm
index aeccbaa..84a30f9 100644
--- a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm
@@ -104,7 +104,7 @@
 
   NSString* title = base::SysUTF16ToNSString(delegate->GetMessageText());
 
-  absl::optional<std::string> account_string =
+  std::optional<std::string> account_string =
       delegate->GetAccountToStorePassword();
   NSString* subtitle =
       account_string ? l10n_util::GetNSStringF(
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator_unittest.mm
index 9b8caa281..ada7805 100644
--- a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator_unittest.mm
@@ -48,7 +48,7 @@
   }
 
   void InitInfobar(
-      absl::optional<std::string> account_to_store_password = absl::nullopt) {
+      std::optional<std::string> account_to_store_password = std::nullopt) {
     infobar_ = std::make_unique<InfoBarIOS>(
         InfobarType::kInfobarTypePasswordSave,
         MockIOSChromeSavePasswordInfoBarDelegate::Create(
diff --git a/ios/chrome/browser/ui/overlays/infobar_modal/autofill_address_profile/save_address_profile_infobar_modal_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_modal/autofill_address_profile/save_address_profile_infobar_modal_overlay_mediator_unittest.mm
index d568d67..d3fd192 100644
--- a/ios/chrome/browser/ui/overlays/infobar_modal/autofill_address_profile/save_address_profile_infobar_modal_overlay_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_modal/autofill_address_profile/save_address_profile_infobar_modal_overlay_mediator_unittest.mm
@@ -48,7 +48,7 @@
         delegate = std::make_unique<
             autofill::AutofillSaveUpdateAddressProfileDelegateIOS>(
             profile, /*original_profile=*/nullptr,
-            /*user_email=*/absl::nullopt,
+            /*user_email=*/std::nullopt,
             /*locale=*/"en-US",
             autofill::AutofillClient::SaveAddressProfilePromptOptions{},
             base::DoNothing());
diff --git a/ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_mediator.mm b/ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_mediator.mm
index b1459cc..41aebbf 100644
--- a/ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_mediator.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_mediator.mm
@@ -60,7 +60,7 @@
                                                  withString:@"•"
                                             startingAtIndex:0]];
   [_consumer setUnmaskedPassword:password];
-  absl::optional<std::string> account_string =
+  std::optional<std::string> account_string =
       delegate_->GetAccountToStorePassword();
   NSString* details_text =
       account_string
diff --git a/ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_mediator_unittest.mm
index ca98ce9..492a498 100644
--- a/ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_mediator_unittest.mm
@@ -51,7 +51,7 @@
   }
 
   void InitInfobar(
-      absl::optional<std::string> account_to_store_password = absl::nullopt) {
+      std::optional<std::string> account_to_store_password = std::nullopt) {
     infobar_ = std::make_unique<InfoBarIOS>(
         InfobarType::kInfobarTypePasswordSave,
         MockIOSChromeSavePasswordInfoBarDelegate::Create(
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
index 0a86a2b2..25560a7f 100644
--- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
+++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
@@ -1504,28 +1504,23 @@
 // is not an error.
 - (std::optional<SyncSettingsItemType>)syncErrorItemType {
   if (self.isSyncDisabledByAdministrator) {
-    return absl::make_optional<SyncSettingsItemType>(
-        SyncDisabledByAdministratorErrorItemType);
+    return SyncDisabledByAdministratorErrorItemType;
   }
   switch (_syncService->GetUserActionableError()) {
     case syncer::SyncService::UserActionableError::kSignInNeedsUpdate:
-      return absl::make_optional<SyncSettingsItemType>(
-          PrimaryAccountReauthErrorItemType);
+      return PrimaryAccountReauthErrorItemType;
     case syncer::SyncService::UserActionableError::kNeedsPassphrase:
-      return absl::make_optional<SyncSettingsItemType>(
-          ShowPassphraseDialogErrorItemType);
+      return ShowPassphraseDialogErrorItemType;
     case syncer::SyncService::UserActionableError::
         kNeedsTrustedVaultKeyForPasswords:
     case syncer::SyncService::UserActionableError::
         kNeedsTrustedVaultKeyForEverything:
-      return absl::make_optional<SyncSettingsItemType>(
-          SyncNeedsTrustedVaultKeyErrorItemType);
+      return SyncNeedsTrustedVaultKeyErrorItemType;
     case syncer::SyncService::UserActionableError::
         kTrustedVaultRecoverabilityDegradedForPasswords:
     case syncer::SyncService::UserActionableError::
         kTrustedVaultRecoverabilityDegradedForEverything:
-      return absl::make_optional<SyncSettingsItemType>(
-          SyncTrustedVaultRecoverabilityDegradedErrorItemType);
+      return SyncTrustedVaultRecoverabilityDegradedErrorItemType;
     case syncer::SyncService::UserActionableError::kGenericUnrecoverableError:
     case syncer::SyncService::UserActionableError::kNone:
       return std::nullopt;
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
index 74c398e..961b1b1 100644
--- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -749,9 +749,11 @@
 // Shows the Safety Check page and starts the Safety Check for `referrer`.
 - (void)showSafetyCheckAndStartSafetyCheck:
     (password_manager::PasswordCheckReferrer)referrer {
-  if ([self.topViewController isKindOfClass:[SafetyCheckCoordinator class]]) {
-    // The top view controller is already the Safety Check panel.
-    // No need to open it.
+  if ([self.topViewController isKindOfClass:[SafetyCheckCoordinator class]] ||
+      [self.safetyCheckCoordinator.baseViewController isBeingDismissed]) {
+    // Do not open the Safety Check panel if:
+    // [1] The top view controller is already the Safety Check panel, or
+    // [2] The Safety Check view controller is currently being dismissed.
     return;
   }
   DCHECK(!self.safetyCheckCoordinator);
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/BUILD.gn
index 37e63c3..fbaf01d 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/BUILD.gn
@@ -23,6 +23,7 @@
     "//components/prefs/ios",
     "//components/sessions",
     "//ios/chrome/app/strings",
+    "//ios/chrome/browser/crash_report/model",
     "//ios/chrome/browser/sessions",
     "//ios/chrome/browser/sessions:restoration_agent",
     "//ios/chrome/browser/sessions:serialisation",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_mediator.mm
index a66d6d0..ebe010e2 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_mediator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_mediator.mm
@@ -11,6 +11,7 @@
 #import "components/prefs/pref_change_registrar.h"
 #import "components/prefs/pref_service.h"
 #import "components/sessions/core/tab_restore_service.h"
+#import "ios/chrome/browser/crash_report/model/crash_keys_helper.h"
 #import "ios/chrome/browser/sessions/session_restoration_browser_agent.h"
 #import "ios/chrome/browser/sessions/session_window_ios.h"
 #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h"
@@ -80,6 +81,7 @@
                            WebStateList* web_state_list) {
   [consumer populateItems:CreateItemsOrderedByRecency(web_state_list)
            selectedItemID:web::WebStateID()];
+  crash_keys::SetInactiveTabCount(web_state_list->count());
 }
 
 }  // namespace
diff --git a/ios/chrome/browser/web/chrome_web_client_unittest.mm b/ios/chrome/browser/web/chrome_web_client_unittest.mm
index a94f1800..4382001 100644
--- a/ios/chrome/browser/web/chrome_web_client_unittest.mm
+++ b/ios/chrome/browser/web/chrome_web_client_unittest.mm
@@ -249,8 +249,7 @@
       net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
   info.is_fatal_cert_error = false;
   info.cert_status = net::CERT_STATUS_COMMON_NAME_INVALID;
-  std::optional<net::SSLInfo> ssl_info =
-      absl::make_optional<net::SSLInfo>(info);
+  std::optional<net::SSLInfo> ssl_info = info;
   ChromeWebClient web_client;
   NSError* error =
       [NSError errorWithDomain:NSURLErrorDomain
diff --git a/ios/third_party/earl_grey2/src b/ios/third_party/earl_grey2/src
index b089cf6..2afe6d2 160000
--- a/ios/third_party/earl_grey2/src
+++ b/ios/third_party/earl_grey2/src
@@ -1 +1 @@
-Subproject commit b089cf61fdc4829854190ab753167a8f4179380a
+Subproject commit 2afe6d25f15c122be700d7e693cd095f46495a69
diff --git a/ios/web/annotations/annotations_java_script_feature.h b/ios/web/annotations/annotations_java_script_feature.h
index 7a16fdc..431de1f 100644
--- a/ios/web/annotations/annotations_java_script_feature.h
+++ b/ios/web/annotations/annotations_java_script_feature.h
@@ -5,12 +5,12 @@
 #ifndef IOS_WEB_ANNOTATIONS_ANNOTATIONS_JAVA_SCRIPT_FEATURE_H_
 #define IOS_WEB_ANNOTATIONS_ANNOTATIONS_JAVA_SCRIPT_FEATURE_H_
 
+#import <optional>
 #import <string>
 
 #import "base/no_destructor.h"
 #import "base/values.h"
 #import "ios/web/public/js_messaging/java_script_feature.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web {
 
@@ -45,7 +45,7 @@
   // JavaScriptFeature:
   void ScriptMessageReceived(WebState* web_state,
                              const ScriptMessage& script_message) override;
-  absl::optional<std::string> GetScriptMessageHandlerName() const override;
+  std::optional<std::string> GetScriptMessageHandlerName() const override;
   AnnotationsJavaScriptFeature();
   ~AnnotationsJavaScriptFeature() override;
 
diff --git a/ios/web/annotations/annotations_java_script_feature.mm b/ios/web/annotations/annotations_java_script_feature.mm
index d0f803f..398a2a7d 100644
--- a/ios/web/annotations/annotations_java_script_feature.mm
+++ b/ios/web/annotations/annotations_java_script_feature.mm
@@ -139,7 +139,7 @@
 
   if (*command == "annotations.extractedText") {
     const std::string* text = dict.FindString("text");
-    absl::optional<double> seq_id = dict.FindDouble("seqId");
+    std::optional<double> seq_id = dict.FindDouble("seqId");
     const base::Value::Dict* metadata = dict.FindDict("metadata");
     if (!text || !seq_id || !metadata) {
       return;
@@ -147,9 +147,8 @@
     manager->OnTextExtracted(web_state, *text, static_cast<int>(seq_id.value()),
                              *metadata);
   } else if (*command == "annotations.decoratingComplete") {
-    absl::optional<double> optional_annotations =
-        dict.FindDouble("annotations");
-    absl::optional<double> optional_successes = dict.FindDouble("successes");
+    std::optional<double> optional_annotations = dict.FindDouble("annotations");
+    std::optional<double> optional_successes = dict.FindDouble("successes");
     if (!optional_annotations || !optional_successes) {
       return;
     }
@@ -158,7 +157,7 @@
     manager->OnDecorated(web_state, successes, annotations);
   } else if (*command == "annotations.onClick") {
     const std::string* data = dict.FindString("data");
-    absl::optional<CGRect> rect =
+    std::optional<CGRect> rect =
         shared_highlighting::ParseRect(dict.FindDict("rect"));
     const std::string* text = dict.FindString("text");
     if (!data || !rect || !text) {
@@ -170,7 +169,7 @@
   }
 }
 
-absl::optional<std::string>
+std::optional<std::string>
 AnnotationsJavaScriptFeature::GetScriptMessageHandlerName() const {
   return kScriptHandlerName;
 }
diff --git a/ios/web/content/js_messaging/content_java_script_feature_manager.mm b/ios/web/content/js_messaging/content_java_script_feature_manager.mm
index edf19f07..ef4f8d4 100644
--- a/ios/web/content/js_messaging/content_java_script_feature_manager.mm
+++ b/ios/web/content/js_messaging/content_java_script_feature_manager.mm
@@ -89,10 +89,10 @@
     }
   }
 
-  absl::optional<std::string> handler_name =
+  std::optional<std::string> handler_name =
       feature->GetScriptMessageHandlerName();
   if (handler_name) {
-    absl::optional<JavaScriptFeature::ScriptMessageHandler> handler =
+    std::optional<JavaScriptFeature::ScriptMessageHandler> handler =
         feature->GetScriptMessageHandler();
     CHECK(handler);
     CHECK(!script_message_handlers_.count(*handler_name));
diff --git a/ios/web/content/js_messaging/ios_web_message_host_factory.mm b/ios/web/content/js_messaging/ios_web_message_host_factory.mm
index b0c7411..74c2c58 100644
--- a/ios/web/content/js_messaging/ios_web_message_host_factory.mm
+++ b/ios/web/content/js_messaging/ios_web_message_host_factory.mm
@@ -33,7 +33,7 @@
   // js_injection::WebMessageHost:
   void OnPostMessage(
       std::unique_ptr<js_injection::WebMessage> web_message) override {
-    absl::optional<std::u16string> received_message;
+    std::optional<std::u16string> received_message;
     absl::visit(
         base::Overloaded{
             [&received_message](const std::u16string& str) {
@@ -49,7 +49,7 @@
     }
 
     // TODO(crbug.com/1423527): Move this parsing to the renderer process.
-    absl::optional<base::Value> message_value =
+    std::optional<base::Value> message_value =
         base::JSONReader::Read(base::UTF16ToUTF8(*received_message));
     if (!message_value) {
       return;
diff --git a/ios/web/content/navigation/content_navigation_context.mm b/ios/web/content/navigation/content_navigation_context.mm
index d25319a9..8639e31 100644
--- a/ios/web/content/navigation/content_navigation_context.mm
+++ b/ios/web/content/navigation/content_navigation_context.mm
@@ -4,14 +4,15 @@
 
 #import "ios/web/content/navigation/content_navigation_context.h"
 
+#import <optional>
+
 #import "base/notreached.h"
 #import "content/public/browser/navigation_handle.h"
 #import "net/base/net_errors.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web {
 
-absl::optional<NSInteger> GetIOSErrorForNetError(int net_error_code) {
+std::optional<NSInteger> GetIOSErrorForNetError(int net_error_code) {
   switch (net_error_code) {
     case net::ERR_ACCESS_DENIED:
       // TODO(crbug.com/1419001): no analog for
@@ -87,7 +88,7 @@
     default:
       break;
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 NavigationContext* ContentNavigationContext::GetOrCreate(
diff --git a/ios/web/content/web_state/content_web_state.h b/ios/web/content/web_state/content_web_state.h
index 5d05e10..48326e7 100644
--- a/ios/web/content/web_state/content_web_state.h
+++ b/ios/web/content/web_state/content_web_state.h
@@ -8,6 +8,7 @@
 #import "ios/web/public/web_state.h"
 
 #import <memory>
+#import <optional>
 
 #import <UIKit/UIKit.h>
 
@@ -115,7 +116,7 @@
   int GetNavigationItemCount() const override;
   const GURL& GetVisibleURL() const override;
   const GURL& GetLastCommittedURL() const override;
-  absl::optional<GURL> GetLastCommittedURLIfTrusted() const override;
+  std::optional<GURL> GetLastCommittedURLIfTrusted() const override;
   WebFramesManager* GetWebFramesManager(ContentWorld world) override;
   CRWWebViewProxyType GetWebViewProxy() const override;
   void AddObserver(WebStateObserver* observer) override;
diff --git a/ios/web/content/web_state/content_web_state.mm b/ios/web/content/web_state/content_web_state.mm
index 1b9461c..8fbf18ae 100644
--- a/ios/web/content/web_state/content_web_state.mm
+++ b/ios/web/content/web_state/content_web_state.mm
@@ -399,7 +399,7 @@
   return item ? item->GetURL() : GURL::EmptyGURL();
 }
 
-absl::optional<GURL> ContentWebState::GetLastCommittedURLIfTrusted() const {
+std::optional<GURL> ContentWebState::GetLastCommittedURLIfTrusted() const {
   return GetLastCommittedURL();
 }
 
diff --git a/ios/web/content/web_state/content_web_state_builder.mm b/ios/web/content/web_state/content_web_state_builder.mm
index fd34159..e8c8bd1 100644
--- a/ios/web/content/web_state/content_web_state_builder.mm
+++ b/ios/web/content/web_state/content_web_state_builder.mm
@@ -38,8 +38,8 @@
     std::unique_ptr<content::NavigationEntry> new_entry =
         content::NavigationController::CreateNavigationEntry(
             navigation_item_storage.virtualURL, content::Referrer(),
-            /* initiator_origin= */ absl::nullopt,
-            /* initiator_base_url= */ absl::nullopt, ui::PAGE_TRANSITION_RELOAD,
+            /* initiator_origin= */ std::nullopt,
+            /* initiator_base_url= */ std::nullopt, ui::PAGE_TRANSITION_RELOAD,
             /* is_renderer_initiated= */ false, std::string(), browser_context,
             /* blob_url_loader_factory= */ nullptr);
     new_entry->SetOriginalRequestURL(navigation_item_storage.URL);
diff --git a/ios/web/download/download_session_task_impl.mm b/ios/web/download/download_session_task_impl.mm
index 01b1403..0cf5d66 100644
--- a/ios/web/download/download_session_task_impl.mm
+++ b/ios/web/download/download_session_task_impl.mm
@@ -229,11 +229,11 @@
 }
 
 // Move the `base::File` out of `optional` and reset the `optional` to have
-// no value (i.e. to be equal to `absl::nullopt`).
-base::File take(absl::optional<base::File>& optional) {
+// no value (i.e. to be equal to `std::nullopt`).
+base::File take(std::optional<base::File>& optional) {
   DCHECK(optional.has_value());
   base::File value = std::move(optional.value());
-  optional = absl::nullopt;
+  optional = std::nullopt;
   return value;
 }
 
@@ -358,11 +358,11 @@
   // empty or not, the data is enqueued in `pending_` or a new task is
   // posted to the background sequence using `task_runner_`.
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
-  absl::optional<base::File> file_;
+  std::optional<base::File> file_;
   NSMutableArray<NSData*>* pending_ = nil;
 
   // Stores the error code received from `TaskFinished`.
-  absl::optional<int> error_code_;
+  std::optional<int> error_code_;
 
   // References to the NSURLSession and NSURLSessionTask used to perform
   // the download in the background.
diff --git a/ios/web/favicon/favicon_java_script_feature.h b/ios/web/favicon/favicon_java_script_feature.h
index 3153397..8f9bb5c2 100644
--- a/ios/web/favicon/favicon_java_script_feature.h
+++ b/ios/web/favicon/favicon_java_script_feature.h
@@ -5,6 +5,8 @@
 #ifndef IOS_WEB_FAVICON_FAVICON_JAVA_SCRIPT_FEATURE_H_
 #define IOS_WEB_FAVICON_FAVICON_JAVA_SCRIPT_FEATURE_H_
 
+#import <optional>
+
 #import "ios/web/public/js_messaging/java_script_feature.h"
 
 namespace web {
@@ -16,7 +18,7 @@
 
  private:
   // JavaScriptFeature:
-  absl::optional<std::string> GetScriptMessageHandlerName() const override;
+  std::optional<std::string> GetScriptMessageHandlerName() const override;
   void ScriptMessageReceived(web::WebState* web_state,
                              const web::ScriptMessage& message) override;
 
diff --git a/ios/web/favicon/favicon_java_script_feature.mm b/ios/web/favicon/favicon_java_script_feature.mm
index 1ba6eea..b5f354bb 100644
--- a/ios/web/favicon/favicon_java_script_feature.mm
+++ b/ios/web/favicon/favicon_java_script_feature.mm
@@ -40,7 +40,7 @@
 
 FaviconJavaScriptFeature::~FaviconJavaScriptFeature() {}
 
-absl::optional<std::string>
+std::optional<std::string>
 FaviconJavaScriptFeature::GetScriptMessageHandlerName() const {
   return kFaviconScriptHandlerName;
 }
diff --git a/ios/web/find_in_page/find_in_page_java_script_feature.h b/ios/web/find_in_page/find_in_page_java_script_feature.h
index 108439d..913a319a 100644
--- a/ios/web/find_in_page/find_in_page_java_script_feature.h
+++ b/ios/web/find_in_page/find_in_page_java_script_feature.h
@@ -5,11 +5,12 @@
 #ifndef IOS_WEB_FIND_IN_PAGE_FIND_IN_PAGE_JAVA_SCRIPT_FEATURE_H_
 #define IOS_WEB_FIND_IN_PAGE_FIND_IN_PAGE_JAVA_SCRIPT_FEATURE_H_
 
+#include <optional>
+
 #include "base/functional/callback.h"
 #include "base/no_destructor.h"
 #include "base/values.h"
 #include "ios/web/public/js_messaging/java_script_feature.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web {
 
@@ -33,14 +34,14 @@
   // necessary before match count is available.
   bool Search(WebFrame* frame,
               const std::string& query,
-              base::OnceCallback<void(absl::optional<int>)> callback);
+              base::OnceCallback<void(std::optional<int>)> callback);
 
   // Continues an ongoing search started with `Search` which hasn't yet
   // completed. `callback` returns the number of search results found or
   // `kFindInPagePending` if more calls to `Pump` are necessary before match
   // count is available.
   void Pump(WebFrame* frame,
-            base::OnceCallback<void(absl::optional<int>)> callback);
+            base::OnceCallback<void(std::optional<int>)> callback);
 
   // Selects the given match at `index` in `frame`. `callback` is called with
   // the dictionary value results from the selection.
@@ -58,7 +59,7 @@
   // Processes the JavaScript `result` to extract the match count and send it
   // to `callback`.
   void ProcessSearchResult(
-      base::OnceCallback<void(const absl::optional<int>)> callback,
+      base::OnceCallback<void(const std::optional<int>)> callback,
       const base::Value* result);
 
   FindInPageJavaScriptFeature();
diff --git a/ios/web/find_in_page/find_in_page_java_script_feature.mm b/ios/web/find_in_page/find_in_page_java_script_feature.mm
index 07b5e2e..815757f 100644
--- a/ios/web/find_in_page/find_in_page_java_script_feature.mm
+++ b/ios/web/find_in_page/find_in_page_java_script_feature.mm
@@ -58,7 +58,7 @@
 bool FindInPageJavaScriptFeature::Search(
     WebFrame* frame,
     const std::string& query,
-    base::OnceCallback<void(absl::optional<int>)> callback) {
+    base::OnceCallback<void(std::optional<int>)> callback) {
   base::Value::List params;
   params.Append(query);
   params.Append(kFindInPageFindTimeout);
@@ -71,7 +71,7 @@
 
 void FindInPageJavaScriptFeature::Pump(
     WebFrame* frame,
-    base::OnceCallback<void(absl::optional<int>)> callback) {
+    base::OnceCallback<void(std::optional<int>)> callback) {
   base::Value::List params;
   params.Append(kFindInPageFindTimeout);
   CallJavaScriptFunction(
@@ -97,9 +97,9 @@
 }
 
 void FindInPageJavaScriptFeature::ProcessSearchResult(
-    base::OnceCallback<void(const absl::optional<int>)> callback,
+    base::OnceCallback<void(const std::optional<int>)> callback,
     const base::Value* result) {
-  absl::optional<int> match_count;
+  std::optional<int> match_count;
   if (result && result->is_double()) {
     // Valid match number returned. If not, match count will be 0 in order to
     // zero-out count from previous find.
diff --git a/ios/web/find_in_page/find_in_page_js_unittest.mm b/ios/web/find_in_page/find_in_page_js_unittest.mm
index 69a54de..f15d87d 100644
--- a/ios/web/find_in_page/find_in_page_js_unittest.mm
+++ b/ios/web/find_in_page/find_in_page_js_unittest.mm
@@ -5,6 +5,8 @@
 #import <UIKit/UIKit.h>
 #import <WebKit/WebKit.h>
 
+#import <optional>
+
 #import "base/functional/bind.h"
 #import "base/functional/callback.h"
 #import "base/run_loop.h"
@@ -24,7 +26,6 @@
 #import "ios/web/public/web_state.h"
 #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
 #import "testing/gtest_mac.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 using base::test::ios::kWaitForJSCompletionTimeout;
 using base::test::ios::kWaitForPageLoadTimeout;
@@ -613,11 +614,11 @@
         ASSERT_TRUE(result);
         ASSERT_TRUE(result->is_dict());
         const base::Value::Dict& result_dict = result->GetDict();
-        const absl::optional<double> count =
+        const std::optional<double> count =
             result_dict.FindDouble(kSelectAndScrollResultMatches);
         ASSERT_TRUE(count);
         ASSERT_EQ(2.0, count.value());
-        const absl::optional<double> index =
+        const std::optional<double> index =
             result_dict.FindDouble(kSelectAndScrollResultIndex);
         ASSERT_TRUE(index);
         ASSERT_EQ(0.0, index.value());
@@ -663,7 +664,7 @@
         ASSERT_TRUE(result);
         ASSERT_TRUE(result->is_dict());
         const base::Value::Dict& result_dict = result->GetDict();
-        const absl::optional<double> index =
+        const std::optional<double> index =
             result_dict.FindDouble(kSelectAndScrollResultIndex);
         ASSERT_TRUE(index);
         EXPECT_EQ(3.0, index.value());
@@ -686,7 +687,7 @@
         ASSERT_TRUE(result);
         ASSERT_TRUE(result->is_dict());
         const base::Value::Dict& result_dict = result->GetDict();
-        const absl::optional<double> index =
+        const std::optional<double> index =
             result_dict.FindDouble(kSelectAndScrollResultIndex);
         ASSERT_TRUE(index);
         // Since there are only two visible matches now and this
diff --git a/ios/web/find_in_page/java_script_find_in_page_manager_impl.h b/ios/web/find_in_page/java_script_find_in_page_manager_impl.h
index 0c720a1..2914184 100644
--- a/ios/web/find_in_page/java_script_find_in_page_manager_impl.h
+++ b/ios/web/find_in_page/java_script_find_in_page_manager_impl.h
@@ -5,6 +5,7 @@
 #ifndef IOS_WEB_FIND_IN_PAGE_JAVA_SCRIPT_FIND_IN_PAGE_MANAGER_IMPL_H_
 #define IOS_WEB_FIND_IN_PAGE_JAVA_SCRIPT_FIND_IN_PAGE_MANAGER_IMPL_H_
 
+#include <optional>
 #include <string>
 
 #include "base/memory/weak_ptr.h"
@@ -13,7 +14,6 @@
 #import "ios/web/public/find_in_page/java_script_find_in_page_manager.h"
 #import "ios/web/public/js_messaging/web_frames_manager.h"
 #include "ios/web/public/web_state_observer.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 @class NSString;
 
@@ -55,7 +55,7 @@
   // null, then does nothing more.
   void ProcessFindInPageResult(const std::string& frame_id,
                                const int request_id,
-                               absl::optional<int> result);
+                               std::optional<int> result);
   // Calls delegate DidHighlightMatches() method if `delegate_` is set and
   // starts a FindInPageNext find. Called when the last frame returns results
   // from a Find request.
diff --git a/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm b/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm
index 3bf0c6edb..baabf0b 100644
--- a/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm
+++ b/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm
@@ -4,6 +4,8 @@
 
 #import "ios/web/find_in_page/java_script_find_in_page_manager_impl.h"
 
+#import <optional>
+
 #import "base/metrics/user_metrics.h"
 #import "base/metrics/user_metrics_action.h"
 #import "base/strings/sys_string_conversions.h"
@@ -17,7 +19,6 @@
 #import "ios/web/public/thread/web_task_traits.h"
 #import "ios/web/public/thread/web_thread.h"
 #import "ios/web/web_state/web_state_impl.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web {
 
@@ -176,7 +177,7 @@
 void JavaScriptFindInPageManagerImpl::ProcessFindInPageResult(
     const std::string& frame_id,
     const int unique_id,
-    absl::optional<int> result_matches) {
+    std::optional<int> result_matches) {
   if (unique_id != last_find_request_.GetRequestId()) {
     // New find was started or current find was stopped.
     return;
@@ -236,7 +237,7 @@
   if (result && result->is_dict()) {
     const base::Value::Dict& result_dict = result->GetDict();
     // Get updated match count.
-    const absl::optional<double> matches =
+    const std::optional<double> matches =
         result_dict.FindDouble(kSelectAndScrollResultMatches);
     if (matches) {
       int match_count = static_cast<int>(matches.value());
@@ -250,7 +251,7 @@
       }
     }
     // Get updated currently selected index.
-    const absl::optional<double> index =
+    const std::optional<double> index =
         result_dict.FindDouble(kSelectAndScrollResultIndex);
     if (index) {
       int current_index = static_cast<int>(index.value());
diff --git a/ios/web/js_features/context_menu/context_menu_java_script_feature.h b/ios/web/js_features/context_menu/context_menu_java_script_feature.h
index 7efbe9f..340b5f9 100644
--- a/ios/web/js_features/context_menu/context_menu_java_script_feature.h
+++ b/ios/web/js_features/context_menu/context_menu_java_script_feature.h
@@ -44,7 +44,7 @@
                          ElementDetailsCallback callback);
 
   // JavaScriptFeature:
-  absl::optional<std::string> GetScriptMessageHandlerName() const override;
+  std::optional<std::string> GetScriptMessageHandlerName() const override;
   void ScriptMessageReceived(WebState* web_state,
                              const ScriptMessage& message) override;
 
diff --git a/ios/web/js_features/context_menu/context_menu_java_script_feature.mm b/ios/web/js_features/context_menu/context_menu_java_script_feature.mm
index e5fe9a87..fb62843b 100644
--- a/ios/web/js_features/context_menu/context_menu_java_script_feature.mm
+++ b/ios/web/js_features/context_menu/context_menu_java_script_feature.mm
@@ -75,7 +75,7 @@
                          parameters);
 }
 
-absl::optional<std::string>
+std::optional<std::string>
 ContextMenuJavaScriptFeature::GetScriptMessageHandlerName() const {
   return kFindElementResultHandlerName;
 }
diff --git a/ios/web/js_features/context_menu/context_menu_params_utils.mm b/ios/web/js_features/context_menu/context_menu_params_utils.mm
index 7b6ef97f..e4b3694 100644
--- a/ios/web/js_features/context_menu/context_menu_params_utils.mm
+++ b/ios/web/js_features/context_menu/context_menu_params_utils.mm
@@ -55,7 +55,7 @@
     params.alt_text = base::SysUTF8ToNSString(*alt_text);
   }
 
-  absl::optional<double> text_offset =
+  std::optional<double> text_offset =
       element.FindDouble(web::kContextMenuElementTextOffset);
   if (text_offset.has_value()) {
     params.text_offset = *text_offset;
@@ -67,7 +67,7 @@
     params.surrounding_text = base::SysUTF8ToNSString(*surrounding_text);
   }
 
-  absl::optional<double> surrounding_text_offset =
+  std::optional<double> surrounding_text_offset =
       element.FindDouble(web::kContextMenuElementSurroundingTextOffset);
   if (surrounding_text_offset.has_value()) {
     params.surrounding_text_offset = *surrounding_text_offset;
diff --git a/ios/web/js_features/error_page/error_page_java_script_feature.h b/ios/web/js_features/error_page/error_page_java_script_feature.h
index 9885aa5..57b00c2 100644
--- a/ios/web/js_features/error_page/error_page_java_script_feature.h
+++ b/ios/web/js_features/error_page/error_page_java_script_feature.h
@@ -5,6 +5,8 @@
 #ifndef IOS_WEB_JS_FEATURES_ERROR_PAGE_ERROR_PAGE_JAVA_SCRIPT_FEATURE_H_
 #define IOS_WEB_JS_FEATURES_ERROR_PAGE_ERROR_PAGE_JAVA_SCRIPT_FEATURE_H_
 
+#import <optional>
+
 #import "base/no_destructor.h"
 #import "ios/web/public/js_messaging/java_script_feature.h"
 
@@ -25,7 +27,7 @@
   friend class base::NoDestructor<ErrorPageJavaScriptFeature>;
 
   // JavaScriptFeature overrides
-  absl::optional<std::string> GetScriptMessageHandlerName() const override;
+  std::optional<std::string> GetScriptMessageHandlerName() const override;
   void ScriptMessageReceived(WebState* web_state,
                              const ScriptMessage& script_message) override;
 
diff --git a/ios/web/js_features/error_page/error_page_java_script_feature.mm b/ios/web/js_features/error_page/error_page_java_script_feature.mm
index ac1a175..5ee704e 100644
--- a/ios/web/js_features/error_page/error_page_java_script_feature.mm
+++ b/ios/web/js_features/error_page/error_page_java_script_feature.mm
@@ -34,7 +34,7 @@
 
 ErrorPageJavaScriptFeature::~ErrorPageJavaScriptFeature() = default;
 
-absl::optional<std::string>
+std::optional<std::string>
 ErrorPageJavaScriptFeature::GetScriptMessageHandlerName() const {
   return kWebUIMessageHandlerName;
 }
@@ -47,7 +47,7 @@
     return;
   }
 
-  absl::optional<GURL> url = script_message.request_url();
+  std::optional<GURL> url = script_message.request_url();
   // Messages must be from an error page.
   if (!url || ![CRWErrorPageHelper isErrorPageFileURL:url.value()]) {
     return;
diff --git a/ios/web/js_features/window_error/window_error_java_script_feature.h b/ios/web/js_features/window_error/window_error_java_script_feature.h
index b64a9fe..c333e20b 100644
--- a/ios/web/js_features/window_error/window_error_java_script_feature.h
+++ b/ios/web/js_features/window_error/window_error_java_script_feature.h
@@ -5,6 +5,8 @@
 #ifndef IOS_WEB_JS_FEATURES_WINDOW_ERROR_WINDOW_ERROR_JAVA_SCRIPT_FEATURE_H_
 #define IOS_WEB_JS_FEATURES_WINDOW_ERROR_WINDOW_ERROR_JAVA_SCRIPT_FEATURE_H_
 
+#include <optional>
+
 #include "base/functional/callback.h"
 #include "ios/web/public/js_messaging/java_script_feature.h"
 #include "url/gurl.h"
@@ -47,7 +49,7 @@
 
  private:
   // JavaScriptFeature:
-  absl::optional<std::string> GetScriptMessageHandlerName() const override;
+  std::optional<std::string> GetScriptMessageHandlerName() const override;
   void ScriptMessageReceived(WebState* web_state,
                              const ScriptMessage& message) override;
 
diff --git a/ios/web/js_features/window_error/window_error_java_script_feature.mm b/ios/web/js_features/window_error/window_error_java_script_feature.mm
index 51ac0f0..afee1ba 100644
--- a/ios/web/js_features/window_error/window_error_java_script_feature.mm
+++ b/ios/web/js_features/window_error/window_error_java_script_feature.mm
@@ -41,7 +41,7 @@
 }
 WindowErrorJavaScriptFeature::~WindowErrorJavaScriptFeature() = default;
 
-absl::optional<std::string>
+std::optional<std::string>
 WindowErrorJavaScriptFeature::GetScriptMessageHandlerName() const {
   return kWindowErrorResultHandlerName;
 }
diff --git a/ios/web/js_features/window_error/window_error_java_script_feature_unittest.mm b/ios/web/js_features/window_error/window_error_java_script_feature_unittest.mm
index f58d8d0..4a960f9 100644
--- a/ios/web/js_features/window_error/window_error_java_script_feature_unittest.mm
+++ b/ios/web/js_features/window_error/window_error_java_script_feature_unittest.mm
@@ -5,13 +5,13 @@
 #import "ios/web/js_features/window_error/window_error_java_script_feature.h"
 
 #import <memory>
+#import <optional>
 
 #import "base/test/ios/wait_util.h"
 #import "ios/web/js_messaging/java_script_feature_manager.h"
 #import "ios/web/public/js_messaging/java_script_feature_util.h"
 #import "ios/web/public/test/web_test_with_web_state.h"
 #import "testing/gtest_mac.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 using base::test::ios::WaitUntilConditionOrTimeout;
 using base::test::ios::kWaitForJSCompletionTimeout;
@@ -33,13 +33,13 @@
         {web::java_script_features::GetMessageJavaScriptFeature(), &feature_});
   }
 
-  absl::optional<WindowErrorJavaScriptFeature::ErrorDetails> error_details() {
+  std::optional<WindowErrorJavaScriptFeature::ErrorDetails> error_details() {
     return error_details_;
   }
 
  private:
   WindowErrorJavaScriptFeature feature_;
-  absl::optional<WindowErrorJavaScriptFeature::ErrorDetails> error_details_;
+  std::optional<WindowErrorJavaScriptFeature::ErrorDetails> error_details_;
 };
 
 // Tests that error details are received for a script error occurring in the
diff --git a/ios/web/js_messaging/java_script_content_world.mm b/ios/web/js_messaging/java_script_content_world.mm
index eb40125..4e14505 100644
--- a/ios/web/js_messaging/java_script_content_world.mm
+++ b/ios/web/js_messaging/java_script_content_world.mm
@@ -4,6 +4,8 @@
 
 #import "ios/web/js_messaging/java_script_content_world.h"
 
+#import <optional>
+
 #import "base/check_op.h"
 #import "base/containers/contains.h"
 #import "base/debug/crash_logging.h"
@@ -19,7 +21,6 @@
 #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
 #import "ios/web/web_state/web_state_impl.h"
 #import "net/base/mac/url_conversions.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web {
 
@@ -174,7 +175,7 @@
   }
 
   NSURL* ns_url = script_message.frameInfo.request.URL;
-  absl::optional<GURL> url;
+  std::optional<GURL> url;
   if (ns_url) {
     url = net::GURLWithNSURL(ns_url);
   }
diff --git a/ios/web/js_messaging/java_script_feature.mm b/ios/web/js_messaging/java_script_feature.mm
index 481f65a6..02b75f7 100644
--- a/ios/web/js_messaging/java_script_feature.mm
+++ b/ios/web/js_messaging/java_script_feature.mm
@@ -52,7 +52,7 @@
   NSString* injection_token =
       InjectionTokenForScript(base::SysUTF8ToNSString(filename));
   return JavaScriptFeature::FeatureScript(
-      filename, /*script=*/absl::nullopt, injection_token, injection_time,
+      filename, /*script=*/std::nullopt, injection_token, injection_time,
       target_frames, reinjection_behavior, replacements_callback);
 }
 
@@ -66,13 +66,13 @@
   NSString* unique_id = [[NSProcessInfo processInfo] globallyUniqueString];
   NSString* injection_token = InjectionTokenForScript(unique_id);
   return JavaScriptFeature::FeatureScript(
-      /*filename=*/absl::nullopt, script, injection_token, injection_time,
+      /*filename=*/std::nullopt, script, injection_token, injection_time,
       target_frames, reinjection_behavior, replacements_callback);
 }
 
 JavaScriptFeature::FeatureScript::FeatureScript(
-    absl::optional<std::string> filename,
-    absl::optional<std::string> script,
+    std::optional<std::string> filename,
+    std::optional<std::string> script,
     NSString* injection_token,
     InjectionTime injection_time,
     TargetFrames target_frames,
@@ -177,15 +177,15 @@
   return dependent_features_;
 }
 
-absl::optional<std::string> JavaScriptFeature::GetScriptMessageHandlerName()
+std::optional<std::string> JavaScriptFeature::GetScriptMessageHandlerName()
     const {
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<JavaScriptFeature::ScriptMessageHandler>
+std::optional<JavaScriptFeature::ScriptMessageHandler>
 JavaScriptFeature::GetScriptMessageHandler() const {
   if (!GetScriptMessageHandlerName()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return base::BindRepeating(&JavaScriptFeature::ScriptMessageReceived,
diff --git a/ios/web/js_messaging/script_message.mm b/ios/web/js_messaging/script_message.mm
index a6ca7a2..acd58cc 100644
--- a/ios/web/js_messaging/script_message.mm
+++ b/ios/web/js_messaging/script_message.mm
@@ -13,7 +13,7 @@
 ScriptMessage::ScriptMessage(std::unique_ptr<base::Value> body,
                              bool is_user_interacting,
                              bool is_main_frame,
-                             absl::optional<GURL> request_url)
+                             std::optional<GURL> request_url)
     : body_(std::move(body)),
       is_user_interacting_(is_user_interacting),
       is_main_frame_(is_main_frame),
diff --git a/ios/web/js_messaging/web_view_js_utils_unittest.mm b/ios/web/js_messaging/web_view_js_utils_unittest.mm
index 5df28a83..90e8b77e 100644
--- a/ios/web/js_messaging/web_view_js_utils_unittest.mm
+++ b/ios/web/js_messaging/web_view_js_utils_unittest.mm
@@ -15,7 +15,6 @@
 #import "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #import "testing/platform_test.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 using base::test::ios::WaitUntilConditionOrTimeout;
 using base::test::ios::kWaitForJSCompletionTimeout;
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm
index 77d6e65..73d372f 100644
--- a/ios/web/navigation/crw_wk_navigation_handler.mm
+++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -2051,7 +2051,7 @@
   DCHECK_EQ(item->GetUniqueID(), context->GetNavigationItemUniqueID());
 
   net::SSLInfo info;
-  absl::optional<net::SSLInfo> ssl_info = absl::nullopt;
+  std::optional<net::SSLInfo> ssl_info = std::nullopt;
 
   if (web::IsWKWebViewSSLCertError(error)) {
     web::GetSSLInfoFromWKWebViewSSLCertError(error, &info);
@@ -2082,7 +2082,7 @@
                                 cacheHit);
         }
       }
-      ssl_info = absl::make_optional<net::SSLInfo>(info);
+      ssl_info = info;
     }
   }
   NSString* failingURLString =
diff --git a/ios/web/navigation/navigation_java_script_feature.h b/ios/web/navigation/navigation_java_script_feature.h
index 71dc79a..21a1041 100644
--- a/ios/web/navigation/navigation_java_script_feature.h
+++ b/ios/web/navigation/navigation_java_script_feature.h
@@ -5,6 +5,8 @@
 #ifndef IOS_WEB_NAVIGATION_NAVIGATION_JAVA_SCRIPT_FEATURE_H_
 #define IOS_WEB_NAVIGATION_NAVIGATION_JAVA_SCRIPT_FEATURE_H_
 
+#include <optional>
+
 #include "base/no_destructor.h"
 #import "ios/web/public/js_messaging/java_script_feature.h"
 
@@ -28,7 +30,7 @@
       delete;
 
   // JavaScriptFeature:
-  absl::optional<std::string> GetScriptMessageHandlerName() const override;
+  std::optional<std::string> GetScriptMessageHandlerName() const override;
   void ScriptMessageReceived(web::WebState* web_state,
                              const web::ScriptMessage& message) override;
 };
diff --git a/ios/web/navigation/navigation_java_script_feature.mm b/ios/web/navigation/navigation_java_script_feature.mm
index ef1ce044..196bca547 100644
--- a/ios/web/navigation/navigation_java_script_feature.mm
+++ b/ios/web/navigation/navigation_java_script_feature.mm
@@ -47,7 +47,7 @@
 
 NavigationJavaScriptFeature::~NavigationJavaScriptFeature() = default;
 
-absl::optional<std::string>
+std::optional<std::string>
 NavigationJavaScriptFeature::GetScriptMessageHandlerName() const {
   return kScriptHandlerName;
 }
diff --git a/ios/web/public/BUILD.gn b/ios/web/public/BUILD.gn
index 4d4f46c..2f3384c 100644
--- a/ios/web/public/BUILD.gn
+++ b/ios/web/public/BUILD.gn
@@ -16,7 +16,6 @@
     "//net",
     "//services/network/public/cpp",
     "//services/network/public/mojom",
-    "//third_party/abseil-cpp:absl",
     "//ui/base",
   ]
 
diff --git a/ios/web/public/js_messaging/BUILD.gn b/ios/web/public/js_messaging/BUILD.gn
index 15b27047..c6db556 100644
--- a/ios/web/public/js_messaging/BUILD.gn
+++ b/ios/web/public/js_messaging/BUILD.gn
@@ -11,10 +11,7 @@
     "//url",
   ]
 
-  public_deps = [
-    "//base",
-    "//third_party/abseil-cpp:absl",
-  ]
+  public_deps = [ "//base" ]
 
   frameworks = [ "Foundation.framework" ]
 
diff --git a/ios/web/public/js_messaging/fuzzer_support/fuzzer_util.cc b/ios/web/public/js_messaging/fuzzer_support/fuzzer_util.cc
index d8be37eb..ff215ff 100644
--- a/ios/web/public/js_messaging/fuzzer_support/fuzzer_util.cc
+++ b/ios/web/public/js_messaging/fuzzer_support/fuzzer_util.cc
@@ -15,8 +15,8 @@
 
 std::unique_ptr<web::ScriptMessage> ProtoToScriptMessage(
     const web::ScriptMessageProto& proto) {
-  absl::optional<base::Value> body = base::JSONReader::Read(proto.body());
-  absl::optional<GURL> url;
+  std::optional<base::Value> body = base::JSONReader::Read(proto.body());
+  std::optional<GURL> url;
   if (proto.has_url()) {
     url = GURL(proto.url());
   }
@@ -30,7 +30,7 @@
     LOG(WARNING) << "is_user_interacting: "
                  << script_message->is_user_interacting();
     LOG(WARNING) << "is_main_frame: " << script_message->is_main_frame();
-    absl::optional<GURL> request_url = script_message->request_url();
+    std::optional<GURL> request_url = script_message->request_url();
     LOG(WARNING) << "request_url: "
                  << (request_url ? request_url.value() : GURL());
   }
diff --git a/ios/web/public/js_messaging/java_script_feature.h b/ios/web/public/js_messaging/java_script_feature.h
index 03b90b3..1c43c24 100644
--- a/ios/web/public/js_messaging/java_script_feature.h
+++ b/ios/web/public/js_messaging/java_script_feature.h
@@ -7,6 +7,7 @@
 
 #import <Foundation/Foundation.h>
 
+#import <optional>
 #include <string>
 #include <vector>
 
@@ -14,7 +15,6 @@
 #import "base/memory/weak_ptr.h"
 #import "base/values.h"
 #import "ios/web/public/js_messaging/content_world.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 class TimeDelta;
@@ -121,8 +121,8 @@
     ~FeatureScript();
 
    private:
-    FeatureScript(absl::optional<std::string> filename,
-                  absl::optional<std::string> script,
+    FeatureScript(std::optional<std::string> filename,
+                  std::optional<std::string> script,
                   NSString* injection_token,
                   InjectionTime injection_time,
                   TargetFrames target_frames,
@@ -133,8 +133,8 @@
     // instructed by `replacements_callback_`.
     NSString* ReplacePlaceholders(NSString* script) const;
 
-    absl::optional<std::string> script_filename_;
-    absl::optional<std::string> script_;
+    std::optional<std::string> script_filename_;
+    std::optional<std::string> script_;
     NSString* injection_token_;
     InjectionTime injection_time_;
     TargetFrames target_frames_;
@@ -180,14 +180,14 @@
 
   // Returns the script message handler name which this feature will receive
   // messages from JavaScript. Returning null will not register any handler.
-  virtual absl::optional<std::string> GetScriptMessageHandlerName() const;
+  virtual std::optional<std::string> GetScriptMessageHandlerName() const;
 
   using ScriptMessageHandler =
       base::RepeatingCallback<void(WebState* web_state,
                                    const ScriptMessage& message)>;
   // Returns the script message handler callback if
   // `GetScriptMessageHandlerName()` returns a handler name.
-  absl::optional<ScriptMessageHandler> GetScriptMessageHandler() const;
+  std::optional<ScriptMessageHandler> GetScriptMessageHandler() const;
 
   JavaScriptFeature(const JavaScriptFeature&) = delete;
 
diff --git a/ios/web/public/js_messaging/script_message.h b/ios/web/public/js_messaging/script_message.h
index 81afa73..c5bf432 100644
--- a/ios/web/public/js_messaging/script_message.h
+++ b/ios/web/public/js_messaging/script_message.h
@@ -6,9 +6,9 @@
 #define IOS_WEB_PUBLIC_JS_MESSAGING_SCRIPT_MESSAGE_H_
 
 #include <memory>
+#include <optional>
 
 #include "base/values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace web {
@@ -19,7 +19,7 @@
   explicit ScriptMessage(std::unique_ptr<base::Value> body,
                          bool is_user_interacting,
                          bool is_main_frame,
-                         absl::optional<GURL> request_url);
+                         std::optional<GURL> request_url);
   ~ScriptMessage();
 
   ScriptMessage& operator=(const ScriptMessage&) = delete;
@@ -36,13 +36,13 @@
   bool is_main_frame() const { return is_main_frame_; }
 
   // The url, if available, of the frame which sent this message.
-  absl::optional<GURL> request_url() const { return request_url_; }
+  std::optional<GURL> request_url() const { return request_url_; }
 
  private:
   std::unique_ptr<base::Value> body_;
   bool is_user_interacting_;
   bool is_main_frame_;
-  absl::optional<GURL> request_url_;
+  std::optional<GURL> request_url_;
 };
 
 }  // namespace web
diff --git a/ios/web/public/test/fakes/fake_cookie_store.cc b/ios/web/public/test/fakes/fake_cookie_store.cc
index 9ea124b..87a0c77 100644
--- a/ios/web/public/test/fakes/fake_cookie_store.cc
+++ b/ios/web/public/test/fakes/fake_cookie_store.cc
@@ -4,9 +4,10 @@
 
 #include "ios/web/public/test/fakes/fake_cookie_store.h"
 
+#include <optional>
+
 #include "ios/web/public/thread/web_task_traits.h"
 #include "ios/web/public/thread/web_thread.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web {
 
@@ -29,7 +30,7 @@
     const GURL& source_url,
     const net::CookieOptions& options,
     SetCookiesCallback callback,
-    absl::optional<net::CookieAccessResult> cookie_access_result) {
+    std::optional<net::CookieAccessResult> cookie_access_result) {
   NOTIMPLEMENTED() << "Implement this if necessary.";
 }
 
diff --git a/ios/web/public/test/fakes/fake_cookie_store.h b/ios/web/public/test/fakes/fake_cookie_store.h
index b5c90ea6..1a625aa 100644
--- a/ios/web/public/test/fakes/fake_cookie_store.h
+++ b/ios/web/public/test/fakes/fake_cookie_store.h
@@ -5,8 +5,9 @@
 #ifndef IOS_WEB_PUBLIC_TEST_FAKES_FAKE_COOKIE_STORE_H_
 #define IOS_WEB_PUBLIC_TEST_FAKES_FAKE_COOKIE_STORE_H_
 
+#include <optional>
+
 #include "net/cookies/cookie_store.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web {
 
@@ -29,8 +30,8 @@
       const GURL& source_url,
       const net::CookieOptions& options,
       SetCookiesCallback callback,
-      absl::optional<net::CookieAccessResult> cookie_access_result =
-          absl::nullopt) override;
+      std::optional<net::CookieAccessResult> cookie_access_result =
+          std::nullopt) override;
   void GetCookieListWithOptionsAsync(
       const GURL& url,
       const net::CookieOptions& options,
diff --git a/ios/web/public/test/fakes/fake_web_client.h b/ios/web/public/test/fakes/fake_web_client.h
index 88f027f..0ee96964 100644
--- a/ios/web/public/test/fakes/fake_web_client.h
+++ b/ios/web/public/test/fakes/fake_web_client.h
@@ -6,6 +6,8 @@
 #define IOS_WEB_PUBLIC_TEST_FAKES_FAKE_WEB_CLIENT_H_
 
 #import <Foundation/Foundation.h>
+
+#include <optional>
 #include <vector>
 
 #import "ios/web/public/web_client.h"
@@ -43,7 +45,7 @@
                         NSError* error,
                         bool is_post,
                         bool is_off_the_record,
-                        const absl::optional<net::SSLInfo>& info,
+                        const std::optional<net::SSLInfo>& info,
                         int64_t navigation_id,
                         base::OnceCallback<void(NSString*)> callback) override;
   UIView* GetWindowedContainer() override;
diff --git a/ios/web/public/test/fakes/fake_web_client.mm b/ios/web/public/test/fakes/fake_web_client.mm
index 3ea990f..f209a3f5 100644
--- a/ios/web/public/test/fakes/fake_web_client.mm
+++ b/ios/web/public/test/fakes/fake_web_client.mm
@@ -64,7 +64,7 @@
     NSError* error,
     bool is_post,
     bool is_off_the_record,
-    const absl::optional<net::SSLInfo>& info,
+    const std::optional<net::SSLInfo>& info,
     int64_t navigation_id,
     base::OnceCallback<void(NSString*)> callback) {
   net::CertStatus cert_status = info.has_value() ? info.value().cert_status : 0;
diff --git a/ios/web/public/test/fakes/fake_web_state.h b/ios/web/public/test/fakes/fake_web_state.h
index 94ccb880..194b1090 100644
--- a/ios/web/public/test/fakes/fake_web_state.h
+++ b/ios/web/public/test/fakes/fake_web_state.h
@@ -10,6 +10,7 @@
 #include <stdint.h>
 
 #include <memory>
+#include <optional>
 #include <string>
 
 #include "base/memory/weak_ptr.h"
@@ -88,7 +89,7 @@
   int GetNavigationItemCount() const override;
   const GURL& GetVisibleURL() const override;
   const GURL& GetLastCommittedURL() const override;
-  absl::optional<GURL> GetLastCommittedURLIfTrusted() const override;
+  std::optional<GURL> GetLastCommittedURLIfTrusted() const override;
   CRWWebViewProxyType GetWebViewProxy() const override;
 
   void AddObserver(WebStateObserver* observer) override;
diff --git a/ios/web/public/test/fakes/fake_web_state.mm b/ios/web/public/test/fakes/fake_web_state.mm
index c8090c7..ecf3c0b 100644
--- a/ios/web/public/test/fakes/fake_web_state.mm
+++ b/ios/web/public/test/fakes/fake_web_state.mm
@@ -264,7 +264,7 @@
   return url_;
 }
 
-absl::optional<GURL> FakeWebState::GetLastCommittedURLIfTrusted() const {
+std::optional<GURL> FakeWebState::GetLastCommittedURLIfTrusted() const {
   return url_;
 }
 
diff --git a/ios/web/public/test/web_view_content_test_util.mm b/ios/web/public/test/web_view_content_test_util.mm
index 46230790..53d8497 100644
--- a/ios/web/public/test/web_view_content_test_util.mm
+++ b/ios/web/public/test/web_view_content_test_util.mm
@@ -120,7 +120,7 @@
     FindInPageJavaScriptFeature* find_in_page_feature =
         FindInPageJavaScriptFeature::GetInstance();
     find_in_page_feature->Search(
-        frame, text, base::BindOnce(^(absl::optional<int> result_matches) {
+        frame, text, base::BindOnce(^(std::optional<int> result_matches) {
           if (result_matches && result_matches.value() >= 1) {
             text_found = true;
           }
diff --git a/ios/web/public/test/web_view_interaction_test_util.mm b/ios/web/public/test/web_view_interaction_test_util.mm
index aa5166d..3740c81 100644
--- a/ios/web/public/test/web_view_interaction_test_util.mm
+++ b/ios/web/public/test/web_view_interaction_test_util.mm
@@ -207,10 +207,10 @@
   if (!found)
     return CGRectNull;
 
-  absl::optional<double> left = rect->FindDouble("left");
-  absl::optional<double> top = rect->FindDouble("top");
-  absl::optional<double> width = rect->FindDouble("width");
-  absl::optional<double> height = rect->FindDouble("height");
+  std::optional<double> left = rect->FindDouble("left");
+  std::optional<double> top = rect->FindDouble("top");
+  std::optional<double> width = rect->FindDouble("width");
+  std::optional<double> height = rect->FindDouble("height");
   if (!(left && top && width && height))
     return CGRectNull;
 
diff --git a/ios/web/public/web_client.h b/ios/web/public/web_client.h
index d475ba6..e7dafe6 100644
--- a/ios/web/public/web_client.h
+++ b/ios/web/public/web_client.h
@@ -7,6 +7,7 @@
 
 #include <map>
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -15,7 +16,6 @@
 #include "base/task/thread_pool/thread_pool_instance.h"
 #include "ios/web/common/user_agent.h"
 #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/resource/resource_scale_factor.h"
 
 namespace base {
@@ -137,7 +137,7 @@
                                 NSError* error,
                                 bool is_post,
                                 bool is_off_the_record,
-                                const absl::optional<net::SSLInfo>& info,
+                                const std::optional<net::SSLInfo>& info,
                                 int64_t navigation_id,
                                 base::OnceCallback<void(NSString*)> callback);
 
diff --git a/ios/web/public/web_state.h b/ios/web/public/web_state.h
index ce2ab9f..9631f653 100644
--- a/ios/web/public/web_state.h
+++ b/ios/web/public/web_state.h
@@ -11,6 +11,7 @@
 
 #include <map>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -27,7 +28,6 @@
 #include "ios/web/public/web_state_id.h"
 #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
 #include "mojo/public/cpp/system/message_pipe.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
 #include "url/gurl.h"
@@ -105,7 +105,7 @@
     // is left default initialized, then the value will not be passed on
     // to the WebState and GetLastActiveTime() will return the WebState's
     // creation time.
-    absl::optional<base::Time> last_active_time;
+    std::optional<base::Time> last_active_time;
   };
 
   // Parameters for the OpenURL() method.
@@ -428,8 +428,8 @@
   virtual const GURL& GetLastCommittedURL() const = 0;
 
   // Returns the last committed URL if the correctness of this URL's origin is
-  // trusted, and absl::nullopt otherwise.
-  virtual absl::optional<GURL> GetLastCommittedURLIfTrusted() const = 0;
+  // trusted, and std::nullopt otherwise.
+  virtual std::optional<GURL> GetLastCommittedURLIfTrusted() const = 0;
 
   // Returns the current CRWWebViewProxy object.
   virtual CRWWebViewProxyType GetWebViewProxy() const = 0;
diff --git a/ios/web/test/fakes/fake_java_script_feature.h b/ios/web/test/fakes/fake_java_script_feature.h
index 77e604b..a3b5be19 100644
--- a/ios/web/test/fakes/fake_java_script_feature.h
+++ b/ios/web/test/fakes/fake_java_script_feature.h
@@ -6,6 +6,7 @@
 #define IOS_WEB_TEST_FAKES_FAKE_JAVA_SCRIPT_FEATURE_H_
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -60,7 +61,7 @@
 
  private:
   // JavaScriptFeature:
-  absl::optional<std::string> GetScriptMessageHandlerName() const override;
+  std::optional<std::string> GetScriptMessageHandlerName() const override;
   void ScriptMessageReceived(WebState* web_state,
                              const ScriptMessage& message) override;
 
diff --git a/ios/web/test/fakes/fake_java_script_feature.mm b/ios/web/test/fakes/fake_java_script_feature.mm
index 134afa68..434fc9bf 100644
--- a/ios/web/test/fakes/fake_java_script_feature.mm
+++ b/ios/web/test/fakes/fake_java_script_feature.mm
@@ -84,7 +84,7 @@
                          base::Seconds(kGetErrorCountTimeout));
 }
 
-absl::optional<std::string> FakeJavaScriptFeature::GetScriptMessageHandlerName()
+std::optional<std::string> FakeJavaScriptFeature::GetScriptMessageHandlerName()
     const {
   return std::string(kFakeJavaScriptFeatureScriptHandlerName);
 }
diff --git a/ios/web/text_fragments/text_fragments_java_script_feature.h b/ios/web/text_fragments/text_fragments_java_script_feature.h
index d7e77c8..8a8854e9 100644
--- a/ios/web/text_fragments/text_fragments_java_script_feature.h
+++ b/ios/web/text_fragments/text_fragments_java_script_feature.h
@@ -5,12 +5,12 @@
 #ifndef IOS_WEB_TEXT_FRAGMENTS_TEXT_FRAGMENTS_JAVA_SCRIPT_FEATURE_H_
 #define IOS_WEB_TEXT_FRAGMENTS_TEXT_FRAGMENTS_JAVA_SCRIPT_FEATURE_H_
 
+#include <optional>
 #include <string>
 
 #include "base/no_destructor.h"
 #include "base/values.h"
 #import "ios/web/public/js_messaging/java_script_feature.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace web {
@@ -39,7 +39,7 @@
   // JavaScriptFeature:
   void ScriptMessageReceived(WebState* web_state,
                              const ScriptMessage& script_message) override;
-  absl::optional<std::string> GetScriptMessageHandlerName() const override;
+  std::optional<std::string> GetScriptMessageHandlerName() const override;
   TextFragmentsJavaScriptFeature();
   ~TextFragmentsJavaScriptFeature() override;
 
diff --git a/ios/web/text_fragments/text_fragments_java_script_feature.mm b/ios/web/text_fragments/text_fragments_java_script_feature.mm
index 3eeed1aa..3679a3ab 100644
--- a/ios/web/text_fragments/text_fragments_java_script_feature.mm
+++ b/ios/web/text_fragments/text_fragments_java_script_feature.mm
@@ -111,9 +111,9 @@
 
   if (*command == "textFragments.processingComplete") {
     // Extract success metrics.
-    absl::optional<double> optional_fragment_count =
+    std::optional<double> optional_fragment_count =
         dict.FindDoubleByDottedPath("result.fragmentsCount");
-    absl::optional<double> optional_success_count =
+    std::optional<double> optional_success_count =
         dict.FindDoubleByDottedPath("result.successCount");
 
     // Since the response can't be trusted, don't log metrics if the results
@@ -139,7 +139,7 @@
   } else if (*command == "textFragments.onClick") {
     manager->OnClick();
   } else if (*command == "textFragments.onClickWithSender") {
-    absl::optional<CGRect> rect =
+    std::optional<CGRect> rect =
         shared_highlighting::ParseRect(dict.FindDict("rect"));
     const std::string* text = dict.FindString("text");
 
@@ -147,7 +147,7 @@
     std::vector<shared_highlighting::TextFragment> fragments;
     if (fragment_values_list) {
       for (const base::Value& val : *fragment_values_list) {
-        absl::optional<shared_highlighting::TextFragment> fragment =
+        std::optional<shared_highlighting::TextFragment> fragment =
             shared_highlighting::TextFragment::FromValue(&val);
         if (fragment) {
           fragments.push_back(*fragment);
@@ -164,7 +164,7 @@
   }
 }
 
-absl::optional<std::string>
+std::optional<std::string>
 TextFragmentsJavaScriptFeature::GetScriptMessageHandlerName() const {
   return kScriptHandlerName;
 }
diff --git a/ios/web/text_fragments/text_fragments_manager_impl.h b/ios/web/text_fragments/text_fragments_manager_impl.h
index 87d1379..d8b7fa20 100644
--- a/ios/web/text_fragments/text_fragments_manager_impl.h
+++ b/ios/web/text_fragments/text_fragments_manager_impl.h
@@ -7,6 +7,8 @@
 
 #import <UIKit/UIKit.h>
 
+#import <optional>
+
 #import "base/memory/weak_ptr.h"
 #import "base/values.h"
 #import "ios/web/public/js_messaging/web_frames_manager.h"
@@ -14,7 +16,6 @@
 #import "ios/web/public/web_state_observer.h"
 #import "ios/web/text_fragments/text_fragments_java_script_feature.h"
 #import "services/metrics/public/cpp/ukm_source_id.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 @protocol CRWWebViewHandlerDelegate;
 
@@ -85,7 +86,7 @@
   // If the URL and navigation state indicate that a highlight should occur,
   // returns the needed params to complete highlighting. Otherwise, returns
   // empty.
-  absl::optional<TextFragmentProcessingParams> ProcessTextFragments(
+  std::optional<TextFragmentProcessingParams> ProcessTextFragments(
       const web::NavigationContext* context,
       const web::Referrer& referrer);
 
@@ -111,7 +112,7 @@
   // Processing may be deferred in cases where the main WebFrame isn't available
   // right away. In those cases, the params needed to complete processing are
   // cached here until a frame becomes available.
-  absl::optional<TextFragmentProcessingParams> deferred_processing_params_;
+  std::optional<TextFragmentProcessingParams> deferred_processing_params_;
 
   __weak id<TextFragmentsDelegate> delegate_;
 };
diff --git a/ios/web/text_fragments/text_fragments_manager_impl.mm b/ios/web/text_fragments/text_fragments_manager_impl.mm
index 9c94f06..0038986 100644
--- a/ios/web/text_fragments/text_fragments_manager_impl.mm
+++ b/ios/web/text_fragments/text_fragments_manager_impl.mm
@@ -144,7 +144,7 @@
 
 #pragma mark - Private Methods
 
-absl::optional<TextFragmentsManagerImpl::TextFragmentProcessingParams>
+std::optional<TextFragmentsManagerImpl::TextFragmentProcessingParams>
 TextFragmentsManagerImpl::ProcessTextFragments(
     const web::NavigationContext* context,
     const web::Referrer& referrer) {
@@ -179,7 +179,7 @@
         ToHexStringRGB(shared_highlighting::kFragmentTextForegroundColorARGB);
   }
 
-  return absl::optional<TextFragmentProcessingParams>(
+  return std::optional<TextFragmentProcessingParams>(
       {std::move(parsed_fragments), bg_color, fg_color});
 }
 
diff --git a/ios/web/web_client.mm b/ios/web/web_client.mm
index 9e73a19..2af277f 100644
--- a/ios/web/web_client.mm
+++ b/ios/web/web_client.mm
@@ -69,7 +69,7 @@
                                  NSError* error,
                                  bool is_post,
                                  bool is_off_the_record,
-                                 const absl::optional<net::SSLInfo>& info,
+                                 const std::optional<net::SSLInfo>& info,
                                  int64_t navigation_id,
                                  base::OnceCallback<void(NSString*)> callback) {
   DCHECK(error);
diff --git a/ios/web/web_client_unittest.mm b/ios/web/web_client_unittest.mm
index 310d5d9b..90256a62 100644
--- a/ios/web/web_client_unittest.mm
+++ b/ios/web/web_client_unittest.mm
@@ -23,7 +23,7 @@
                           code:NSURLErrorNotConnectedToInternet
                       userInfo:@{NSLocalizedDescriptionKey : description}];
 
-  absl::optional<net::SSLInfo> info = absl::nullopt;
+  std::optional<net::SSLInfo> info = std::nullopt;
   __block bool callback_called = false;
   __block NSString* html = nil;
   web_client.PrepareErrorPage(/*web_state*/ nullptr, GURL::EmptyGURL(), error,
diff --git a/ios/web/web_state/policy_decision_state_tracker_unittest.mm b/ios/web/web_state/policy_decision_state_tracker_unittest.mm
index 7e3e7b6..6b2ad03 100644
--- a/ios/web/web_state/policy_decision_state_tracker_unittest.mm
+++ b/ios/web/web_state/policy_decision_state_tracker_unittest.mm
@@ -4,10 +4,11 @@
 
 #import "ios/web/web_state/policy_decision_state_tracker.h"
 
+#import <optional>
+
 #import "base/functional/callback.h"
 #import "testing/gtest/include/gtest/gtest.h"
 #import "testing/platform_test.h"
-#import "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web {
 
@@ -24,7 +25,7 @@
   }
 
   PolicyDecisionStateTracker policy_decision_state_tracker_;
-  absl::optional<WebStatePolicyDecider::PolicyDecision> policy_decision_;
+  std::optional<WebStatePolicyDecider::PolicyDecision> policy_decision_;
 };
 
 // Tests the case where every decision received is to allow the navigation, and
@@ -298,7 +299,7 @@
   }
 
   std::unique_ptr<PolicyDecisionStateTracker> policy_decision_state_tracker_;
-  absl::optional<WebStatePolicyDecider::PolicyDecision> policy_decision_;
+  std::optional<WebStatePolicyDecider::PolicyDecision> policy_decision_;
 };
 
 // Tests the case where no decisions have been received by the time the
diff --git a/ios/web/web_state/ui/crw_context_menu_controller.mm b/ios/web/web_state/ui/crw_context_menu_controller.mm
index f90bdd82..f72a67d 100644
--- a/ios/web/web_state/ui/crw_context_menu_controller.mm
+++ b/ios/web/web_state/ui/crw_context_menu_controller.mm
@@ -94,7 +94,7 @@
   CGPoint locationInWebView =
       [self.webView.scrollView convertPoint:location fromView:interaction.view];
 
-  absl::optional<web::ContextMenuParams> optionalParams =
+  std::optional<web::ContextMenuParams> optionalParams =
       [self fetchContextMenuParamsAtLocation:locationInWebView];
 
   if (!optionalParams.has_value()) {
@@ -196,7 +196,7 @@
 
 // Fetches the context menu params for the element at `locationInWebView`. The
 // returned params can be empty.
-- (absl::optional<web::ContextMenuParams>)fetchContextMenuParamsAtLocation:
+- (std::optional<web::ContextMenuParams>)fetchContextMenuParamsAtLocation:
     (CGPoint)locationInWebView {
   // While traditionally using dispatch_async would be used here, we have to
   // instead use CFRunLoop because dispatch_async blocks the thread. As this
@@ -207,7 +207,7 @@
   __block BOOL javascriptEvaluationComplete = NO;
   __block BOOL isRunLoopComplete = NO;
 
-  __block absl::optional<web::ContextMenuParams> resultParams;
+  __block std::optional<web::ContextMenuParams> resultParams;
 
   __weak __typeof(self) weakSelf = self;
   [self.elementFetcher
diff --git a/ios/web/web_state/web_state_impl.h b/ios/web/web_state/web_state_impl.h
index a3aa09b..9335a74 100644
--- a/ios/web/web_state/web_state_impl.h
+++ b/ios/web/web_state/web_state_impl.h
@@ -12,6 +12,7 @@
 
 #include <map>
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -339,7 +340,7 @@
   int GetNavigationItemCount() const final;
   const GURL& GetVisibleURL() const final;
   const GURL& GetLastCommittedURL() const final;
-  absl::optional<GURL> GetLastCommittedURLIfTrusted() const final;
+  std::optional<GURL> GetLastCommittedURLIfTrusted() const final;
   id<CRWWebViewProxy> GetWebViewProxy() const final;
   void DidChangeVisibleSecurityState() final;
   InterfaceBinder* GetInterfaceBinderForMainFrame() final;
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index e903049a..b354f36 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -711,7 +711,7 @@
                         : saved_->GetLastCommittedURL();
 }
 
-absl::optional<GURL> WebStateImpl::GetLastCommittedURLIfTrusted() const {
+std::optional<GURL> WebStateImpl::GetLastCommittedURLIfTrusted() const {
   return LIKELY(pimpl_) ? pimpl_->GetLastCommittedURLIfTrusted()
                         : saved_->GetLastCommittedURL();
 }
diff --git a/ios/web/web_state/web_state_impl_realized_web_state.h b/ios/web/web_state/web_state_impl_realized_web_state.h
index b5e6a75..67d8102 100644
--- a/ios/web/web_state/web_state_impl_realized_web_state.h
+++ b/ios/web/web_state/web_state_impl_realized_web_state.h
@@ -196,7 +196,7 @@
   int GetNavigationItemCount() const;
   const GURL& GetVisibleURL() const;
   const GURL& GetLastCommittedURL() const;
-  absl::optional<GURL> GetLastCommittedURLIfTrusted() const;
+  std::optional<GURL> GetLastCommittedURLIfTrusted() const;
   id<CRWWebViewProxy> GetWebViewProxy() const;
   void DidChangeVisibleSecurityState();
   WebState::InterfaceBinder* GetInterfaceBinderForMainFrame();
diff --git a/ios/web/web_state/web_state_impl_realized_web_state.mm b/ios/web/web_state/web_state_impl_realized_web_state.mm
index 479b38d83..5af02d39 100644
--- a/ios/web/web_state/web_state_impl_realized_web_state.mm
+++ b/ios/web/web_state/web_state_impl_realized_web_state.mm
@@ -771,7 +771,7 @@
   return item ? item->GetVirtualURL() : GURL::EmptyGURL();
 }
 
-absl::optional<GURL>
+std::optional<GURL>
 WebStateImpl::RealizedWebState::GetLastCommittedURLIfTrusted() const {
   NavigationItemImpl* item = navigation_manager_->GetLastCommittedItemImpl();
   if (!item) {
@@ -779,7 +779,7 @@
   }
 
   if (item->IsUntrusted()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return item->GetVirtualURL();
diff --git a/ios/web/webui/mojo_facade.mm b/ios/web/webui/mojo_facade.mm
index bbf4a3c..a61282c 100644
--- a/ios/web/webui/mojo_facade.mm
+++ b/ios/web/webui/mojo_facade.mm
@@ -94,7 +94,7 @@
   const std::string* interface_name = args.FindString("interfaceName");
   CHECK(interface_name);
 
-  absl::optional<int> pipe_id = args.FindInt("requestHandle");
+  std::optional<int> pipe_id = args.FindInt("requestHandle");
   CHECK(pipe_id.has_value());
 
   mojo::ScopedMessagePipeHandle pipe = TakePipeFromId(*pipe_id);
@@ -104,7 +104,7 @@
 }
 
 void MojoFacade::HandleMojoHandleClose(base::Value::Dict args) {
-  absl::optional<int> pipe_id = args.FindInt("handle");
+  std::optional<int> pipe_id = args.FindInt("handle");
   CHECK(pipe_id.has_value());
 
   // Will close once out of scope.
@@ -121,7 +121,7 @@
 }
 
 base::Value MojoFacade::HandleMojoHandleWriteMessage(base::Value::Dict args) {
-  absl::optional<int> pipe_id = args.FindInt("handle");
+  std::optional<int> pipe_id = args.FindInt("handle");
   CHECK(pipe_id.has_value());
   mojo::MessagePipeHandle pipe = GetPipeFromId(*pipe_id);
   CHECK(pipe.is_valid());
@@ -139,7 +139,7 @@
     int one_handle = (*handles_list)[i].GetInt();
     handles[i] = TakePipeFromId(one_handle);
   }
-  absl::optional<std::vector<uint8_t>> bytes = base::Base64Decode(*buffer);
+  std::optional<std::vector<uint8_t>> bytes = base::Base64Decode(*buffer);
   if (!bytes) {
     return base::Value(static_cast<int>(MOJO_RESULT_INVALID_ARGUMENT));
   }
@@ -190,11 +190,11 @@
 }
 
 base::Value MojoFacade::HandleMojoHandleWatch(base::Value::Dict args) {
-  absl::optional<int> pipe_id = args.FindInt("handle");
+  std::optional<int> pipe_id = args.FindInt("handle");
   CHECK(pipe_id.has_value());
-  absl::optional<int> signals = args.FindInt("signals");
+  std::optional<int> signals = args.FindInt("signals");
   CHECK(signals.has_value());
-  absl::optional<int> callback_id = args.FindInt("callbackId");
+  std::optional<int> callback_id = args.FindInt("callbackId");
   CHECK(callback_id.has_value());
 
   mojo::SimpleWatcher::ReadyCallback callback = base::BindRepeating(
@@ -220,7 +220,7 @@
 }
 
 void MojoFacade::HandleMojoWatcherCancel(base::Value::Dict args) {
-  absl::optional<int> watch_id = args.FindInt("watchId");
+  std::optional<int> watch_id = args.FindInt("watchId");
   CHECK(watch_id.has_value());
   watchers_.erase(*watch_id);
 }
diff --git a/ios/web/webui/web_ui_messaging_java_script_feature.h b/ios/web/webui/web_ui_messaging_java_script_feature.h
index 584bf58a..fb39ebc 100644
--- a/ios/web/webui/web_ui_messaging_java_script_feature.h
+++ b/ios/web/webui/web_ui_messaging_java_script_feature.h
@@ -5,6 +5,8 @@
 #ifndef IOS_WEB_WEBUI_WEB_UI_MESSAGING_JAVA_SCRIPT_FEATURE_H_
 #define IOS_WEB_WEBUI_WEB_UI_MESSAGING_JAVA_SCRIPT_FEATURE_H_
 
+#include <optional>
+
 #include "base/no_destructor.h"
 #import "ios/web/public/js_messaging/java_script_feature.h"
 
@@ -22,7 +24,7 @@
   friend class base::NoDestructor<WebUIMessagingJavaScriptFeature>;
 
   // JavaScriptFeature overrides
-  absl::optional<std::string> GetScriptMessageHandlerName() const override;
+  std::optional<std::string> GetScriptMessageHandlerName() const override;
   void ScriptMessageReceived(WebState* web_state,
                              const ScriptMessage& script_message) override;
 
diff --git a/ios/web/webui/web_ui_messaging_java_script_feature.mm b/ios/web/webui/web_ui_messaging_java_script_feature.mm
index 48254ce..619eae1 100644
--- a/ios/web/webui/web_ui_messaging_java_script_feature.mm
+++ b/ios/web/webui/web_ui_messaging_java_script_feature.mm
@@ -30,7 +30,7 @@
 
 WebUIMessagingJavaScriptFeature::~WebUIMessagingJavaScriptFeature() = default;
 
-absl::optional<std::string>
+std::optional<std::string>
 WebUIMessagingJavaScriptFeature::GetScriptMessageHandlerName() const {
   return kWebUIMessageHandlerName;
 }
@@ -43,7 +43,7 @@
     return;
   }
 
-  absl::optional<GURL> url = script_message.request_url();
+  std::optional<GURL> url = script_message.request_url();
   // Messages must be from an app specific url.
   if (!url || !web::GetWebClient()->IsAppSpecificURL(url.value())) {
     return;
diff --git a/media/base/audio_bus.cc b/media/base/audio_bus.cc
index e3428100..2e3d7e2 100644
--- a/media/base/audio_bus.cc
+++ b/media/base/audio_bus.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 #include <stdint.h>
+#include <string.h>
 
 #include <limits>
 #include <utility>
@@ -27,9 +28,9 @@
 // We do this by allocating space for potentially more frames than requested.
 // This method returns the required size for the contiguous memory block
 // in bytes and outputs the adjusted number of frames via |out_aligned_frames|.
-static int CalculateMemorySizeInternal(int channels,
-                                       int frames,
-                                       int* out_aligned_frames) {
+static size_t CalculateMemorySizeInternal(int channels,
+                                          int frames,
+                                          int* out_aligned_frames) {
   // Since our internal sample format is float, we can guarantee the alignment
   // by making the number of frames an integer multiple of
   // AudioBus::kChannelAlignment / sizeof(float).
@@ -63,10 +64,11 @@
   ValidateConfig(channels, frames_);
 
   int aligned_frames = 0;
-  int size = CalculateMemorySizeInternal(channels, frames, &aligned_frames);
+  size_t size = CalculateMemorySizeInternal(channels, frames, &aligned_frames);
 
   data_.reset(static_cast<float*>(base::AlignedAlloc(
       size, AudioBus::kChannelAlignment)));
+  memset(data_.get(), 0, size);
 
   BuildChannelData(channels, aligned_frames, data_.get());
 }
diff --git a/mojo/core/broker_host.cc b/mojo/core/broker_host.cc
index 7a5d4f94..0f827bed 100644
--- a/mojo/core/broker_host.cc
+++ b/mojo/core/broker_host.cc
@@ -4,6 +4,7 @@
 
 #include "mojo/core/broker_host.h"
 
+#include <string_view>
 #include <utility>
 
 #include "base/logging.h"
@@ -99,7 +100,7 @@
 
 #if BUILDFLAG(IS_WIN)
 
-void BrokerHost::SendNamedChannel(base::WStringPiece pipe_name) {
+void BrokerHost::SendNamedChannel(std::wstring_view pipe_name) {
   InitData* data;
   wchar_t* name_data;
   Channel::MessagePtr message = CreateBrokerMessage(
diff --git a/mojo/core/broker_host.h b/mojo/core/broker_host.h
index b1bbc6fb..051b391 100644
--- a/mojo/core/broker_host.h
+++ b/mojo/core/broker_host.h
@@ -6,11 +6,12 @@
 #define MOJO_CORE_BROKER_HOST_H_
 
 #include <stdint.h>
+
+#include <string_view>
 #include <vector>
 
 #include "base/process/process.h"
 #include "base/process/process_handle.h"
-#include "base/strings/string_piece.h"
 #include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "mojo/core/channel.h"
@@ -39,7 +40,7 @@
 
 #if BUILDFLAG(IS_WIN)
   // Sends a named channel to the client. Like above, but for named pipes.
-  void SendNamedChannel(base::WStringPiece pipe_name);
+  void SendNamedChannel(std::wstring_view pipe_name);
 #endif
 
  private:
diff --git a/net/base/chunked_upload_data_stream_unittest.cc b/net/base/chunked_upload_data_stream_unittest.cc
index 8dbb8e5..135ef38 100644
--- a/net/base/chunked_upload_data_stream_unittest.cc
+++ b/net/base/chunked_upload_data_stream_unittest.cc
@@ -32,7 +32,7 @@
 // Reads data once from the upload data stream, and returns the data as string.
 // Expects the read to succeed synchronously.
 std::string ReadSync(UploadDataStream* stream, int buffer_size) {
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(buffer_size);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(buffer_size);
   int result = stream->Read(buf.get(),
                             buffer_size,
                             TestCompletionCallback().callback());
@@ -53,7 +53,7 @@
   EXPECT_FALSE(stream.IsEOF());
 
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   int result = stream.Read(buf.get(), kTestBufferSize, callback.callback());
   ASSERT_THAT(result, IsError(ERR_IO_PENDING));
 
@@ -120,7 +120,7 @@
   EXPECT_FALSE(stream.IsEOF());
 
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   for (size_t i = 0; i < kTestDataSize; ++i) {
     EXPECT_EQ(0u, stream.size());  // Content-Length is 0 for chunked data.
     EXPECT_EQ(i, stream.position());
@@ -150,7 +150,7 @@
   EXPECT_EQ(0u, stream.position());
   EXPECT_FALSE(stream.IsEOF());
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   for (size_t i = 0; i < kTestDataSize; ++i) {
     EXPECT_EQ(i, stream.position());
     ASSERT_FALSE(stream.IsEOF());
@@ -238,7 +238,7 @@
   EXPECT_FALSE(stream.IsEOF());
 
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   int result = stream.Read(buf.get(), kTestBufferSize, callback.callback());
   ASSERT_THAT(result, IsError(ERR_IO_PENDING));
 
@@ -312,7 +312,7 @@
   EXPECT_FALSE(stream.IsEOF());
 
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   int result = stream.Read(buf.get(), kTestBufferSize, callback.callback());
   ASSERT_THAT(result, IsError(ERR_IO_PENDING));
 
diff --git a/net/base/elements_upload_data_stream_unittest.cc b/net/base/elements_upload_data_stream_unittest.cc
index f205f55..7261093 100644
--- a/net/base/elements_upload_data_stream_unittest.cc
+++ b/net/base/elements_upload_data_stream_unittest.cc
@@ -52,7 +52,7 @@
 // Reads data from the upload data stream, and returns the data as string.
 std::string ReadFromUploadDataStream(UploadDataStream* stream) {
   std::string data_read;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   while (!stream->IsEOF()) {
     TestCompletionCallback callback;
     const int result =
@@ -183,7 +183,7 @@
   EXPECT_EQ(kTestDataSize, stream->size());
   EXPECT_EQ(0U, stream->position());
   EXPECT_FALSE(stream->IsEOF());
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   while (!stream->IsEOF()) {
     int bytes_read =
         stream->Read(buf.get(), kTestBufferSize, CompletionOnceCallback());
@@ -214,7 +214,7 @@
   EXPECT_EQ(kTestDataSize, stream->size());
   EXPECT_EQ(0U, stream->position());
   EXPECT_FALSE(stream->IsEOF());
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   while (!stream->IsEOF()) {
     TestCompletionCallback read_callback;
     ASSERT_EQ(
@@ -251,7 +251,7 @@
   EXPECT_EQ(kFakeSize, stream->size());
   EXPECT_EQ(0U, stream->position());
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   EXPECT_FALSE(stream->IsEOF());
 
   TestCompletionCallback read_callback;
@@ -293,7 +293,7 @@
   EXPECT_FALSE(stream->IsEOF());
 
   // Prepare a buffer filled with non-zero data.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   std::fill_n(buf->data(), kTestBufferSize, -1);
 
   // Read() results in success even when the reader returns error.
@@ -331,7 +331,7 @@
   EXPECT_FALSE(stream->IsEOF());
 
   // Prepare a buffer filled with non-zero data.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   std::fill_n(buf->data(), kTestBufferSize, -1);
 
   // Read() results in success even when the reader returns error.
@@ -373,7 +373,7 @@
   EXPECT_EQ(kStreamSize, stream->size());
   EXPECT_EQ(0U, stream->position());
   EXPECT_FALSE(stream->IsEOF());
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
   while (!stream->IsEOF()) {
     TestCompletionCallback read_callback;
     const int result =
@@ -476,7 +476,7 @@
   EXPECT_EQ(kTestDataSize, stream->size());
   EXPECT_EQ(0U, stream->position());
   EXPECT_FALSE(stream->IsEOF());
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestDataSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestDataSize);
   int bytes_read =
       stream->Read(buf.get(), kTestDataSize, CompletionOnceCallback());
   ASSERT_TRUE(bytes_read);  // Not an error.
@@ -519,7 +519,7 @@
               IsError(ERR_IO_PENDING));
   EXPECT_THAT(init_callback.WaitForResult(), IsOk());
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTestBufferSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
 
   // Consume the first element.
   TestCompletionCallback read_callback1;
@@ -701,7 +701,7 @@
   // Read some.
   TestCompletionCallback read_callback1;
   std::vector<char> buf(kTestDataSize + kTestDataSize / 2);
-  scoped_refptr<IOBuffer> wrapped_buffer =
+  auto wrapped_buffer =
       base::MakeRefCounted<WrappedIOBuffer>(buf.data(), buf.size());
   EXPECT_EQ(
       ERR_IO_PENDING,
@@ -721,7 +721,7 @@
   // Read.
   TestCompletionCallback read_callback2;
   std::vector<char> buf2(kTestDataSize * 2);
-  scoped_refptr<IOBuffer> wrapped_buffer2 =
+  auto wrapped_buffer2 =
       base::MakeRefCounted<WrappedIOBuffer>(buf2.data(), buf2.size());
   EXPECT_EQ(ERR_IO_PENDING,
             stream->Read(
@@ -766,7 +766,7 @@
   // Read.
   TestCompletionCallback read_callback2;
   std::vector<char> buf2(kTestDataSize * 2);
-  scoped_refptr<IOBuffer> wrapped_buffer2 =
+  auto wrapped_buffer2 =
       base::MakeRefCounted<WrappedIOBuffer>(buf2.data(), buf2.size());
   EXPECT_EQ(ERR_IO_PENDING,
             stream->Read(
@@ -810,7 +810,7 @@
   // Start reading.
   TestCompletionCallback read_callback1;
   std::vector<char> buf(kTestDataSize * 2);
-  scoped_refptr<IOBuffer> wrapped_buffer =
+  auto wrapped_buffer =
       base::MakeRefCounted<WrappedIOBuffer>(buf.data(), buf.size());
   EXPECT_EQ(
       ERR_IO_PENDING,
@@ -828,7 +828,7 @@
   // Read.
   TestCompletionCallback read_callback2;
   std::vector<char> buf2(kTestDataSize * 2);
-  scoped_refptr<IOBuffer> wrapped_buffer2 =
+  auto wrapped_buffer2 =
       base::MakeRefCounted<WrappedIOBuffer>(buf2.data(), buf2.size());
   EXPECT_EQ(ERR_IO_PENDING,
             stream->Read(
diff --git a/net/base/file_stream_unittest.cc b/net/base/file_stream_unittest.cc
index 977f39e..c4028cea 100644
--- a/net/base/file_stream_unittest.cc
+++ b/net/base/file_stream_unittest.cc
@@ -780,7 +780,7 @@
   auto stream = std::make_unique<FileStream>(
       std::move(file), base::SingleThreadTaskRunner::GetCurrentDefault());
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(1);
+  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBufferWithSize>(1);
   buf->data()[0] = 0;
 
   TestCompletionCallback callback;
@@ -805,7 +805,7 @@
   auto stream = std::make_unique<FileStream>(
       std::move(file), base::SingleThreadTaskRunner::GetCurrentDefault());
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(1);
+  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBufferWithSize>(1);
   TestCompletionCallback callback;
   int rv = stream->Read(buf.get(), 1, callback.callback());
   if (rv == ERR_IO_PENDING)
diff --git a/net/base/filename_util_internal.cc b/net/base/filename_util_internal.cc
index c128560c..e0962b5 100644
--- a/net/base/filename_util_internal.cc
+++ b/net/base/filename_util_internal.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/base/filename_util.h"
+#include "net/base/filename_util_internal.h"
 
 #include "base/containers/contains.h"
 #include "base/files/file_path.h"
@@ -13,7 +13,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
-#include "net/base/filename_util_internal.h"
+#include "net/base/filename_util.h"
 #include "net/base/mime_util.h"
 #include "net/base/net_string_util.h"
 #include "net/http/http_content_disposition.h"
@@ -319,7 +319,7 @@
       replace_illegal_characters_function);
 
 #if BUILDFLAG(IS_WIN)
-  base::FilePath generated_name(base::AsWStringPiece(file_name));
+  base::FilePath generated_name(base::AsWStringView(file_name));
 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
   base::FilePath generated_name(
       base::SysWideToNativeMB(base::UTF16ToWide(file_name)));
diff --git a/net/cert/cert_verifier.cc b/net/cert/cert_verifier.cc
index feee793..bcc185c 100644
--- a/net/cert/cert_verifier.cc
+++ b/net/cert/cert_verifier.cc
@@ -28,21 +28,22 @@
  public:
   scoped_refptr<net::CertVerifyProc> CreateCertVerifyProc(
       scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
-      const CertVerifyProcFactory::ImplParams& impl_params) override {
+      const CertVerifyProc::ImplParams& impl_params,
+      const CertVerifyProc::InstanceParams& instance_params) override {
 #if BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL)
     if (impl_params.use_chrome_root_store) {
       return CertVerifyProc::CreateBuiltinWithChromeRootStore(
           std::move(cert_net_fetcher), impl_params.crl_set,
-          base::OptionalToPtr(impl_params.root_store_data));
+          base::OptionalToPtr(impl_params.root_store_data), instance_params);
     }
 #endif
 #if BUILDFLAG(CHROME_ROOT_STORE_ONLY)
     return CertVerifyProc::CreateBuiltinWithChromeRootStore(
         std::move(cert_net_fetcher), impl_params.crl_set,
-        base::OptionalToPtr(impl_params.root_store_data));
+        base::OptionalToPtr(impl_params.root_store_data), instance_params);
 #elif BUILDFLAG(IS_FUCHSIA)
-    return CertVerifyProc::CreateBuiltinVerifyProc(std::move(cert_net_fetcher),
-                                                   impl_params.crl_set);
+    return CertVerifyProc::CreateBuiltinVerifyProc(
+        std::move(cert_net_fetcher), impl_params.crl_set, instance_params);
 #else
     return CertVerifyProc::CreateSystemVerifyProc(std::move(cert_net_fetcher),
                                                   impl_params.crl_set);
@@ -116,7 +117,7 @@
     scoped_refptr<CertNetFetcher> cert_net_fetcher) {
   auto proc_factory = base::MakeRefCounted<DefaultCertVerifyProcFactory>();
   return std::make_unique<MultiThreadedCertVerifier>(
-      proc_factory->CreateCertVerifyProc(std::move(cert_net_fetcher), {}),
+      proc_factory->CreateCertVerifyProc(std::move(cert_net_fetcher), {}, {}),
       proc_factory);
 }
 
@@ -132,14 +133,10 @@
                 const CertVerifier::Config& rhs) {
   return std::tie(
              lhs.enable_rev_checking, lhs.require_rev_checking_local_anchors,
-             lhs.enable_sha1_local_anchors, lhs.disable_symantec_enforcement,
-             lhs.additional_trust_anchors,
-             lhs.additional_untrusted_authorities) ==
+             lhs.enable_sha1_local_anchors, lhs.disable_symantec_enforcement) ==
          std::tie(
              rhs.enable_rev_checking, rhs.require_rev_checking_local_anchors,
-             rhs.enable_sha1_local_anchors, rhs.disable_symantec_enforcement,
-             rhs.additional_trust_anchors,
-             rhs.additional_untrusted_authorities);
+             rhs.enable_sha1_local_anchors, rhs.disable_symantec_enforcement);
 }
 
 bool operator!=(const CertVerifier::Config& lhs,
diff --git a/net/cert/cert_verifier.h b/net/cert/cert_verifier.h
index 026ffc8e..96b47d0 100644
--- a/net/cert/cert_verifier.h
+++ b/net/cert/cert_verifier.h
@@ -68,18 +68,6 @@
     // Disable enforcement of the policies described at
     // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html
     bool disable_symantec_enforcement = false;
-
-    // Additional trust anchors to consider during path validation. Ordinarily,
-    // implementations of CertVerifier use trust anchors from the configured
-    // system store. This is implementation-specific plumbing for passing
-    // additional anchors through.
-    CertificateList additional_trust_anchors;
-
-    // Additional temporary certs to consider as intermediates during path
-    // validation. Ordinarily, implementations of CertVerifier use intermediate
-    // certs from the configured system store. This is implementation-specific
-    // plumbing for passing additional intermediates through.
-    CertificateList additional_untrusted_authorities;
   };
 
   class Request {
@@ -241,7 +229,8 @@
   // Update the CertVerifyProc with a new set of parameters.
   virtual void UpdateVerifyProcData(
       scoped_refptr<CertNetFetcher> cert_net_fetcher,
-      const net::CertVerifyProcFactory::ImplParams& impl_params) = 0;
+      const net::CertVerifyProc::ImplParams& impl_params,
+      const net::CertVerifyProc::InstanceParams& instance_params) = 0;
 };
 
 }  // namespace net
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc
index f6c4dac..a052bc1 100644
--- a/net/cert/cert_verify_proc.cc
+++ b/net/cert/cert_verify_proc.cc
@@ -368,14 +368,12 @@
   return true;
 }
 
-base::Value::Dict CertVerifyParams(
-    X509Certificate* cert,
-    const std::string& hostname,
-    const std::string& ocsp_response,
-    const std::string& sct_list,
-    int flags,
-    CRLSet* crl_set,
-    const CertificateList& additional_trust_anchors) {
+base::Value::Dict CertVerifyParams(X509Certificate* cert,
+                                   const std::string& hostname,
+                                   const std::string& ocsp_response,
+                                   const std::string& sct_list,
+                                   int flags,
+                                   CRLSet* crl_set) {
   base::Value::Dict dict;
   dict.Set("certificates", NetLogX509CertificateList(cert));
   if (!ocsp_response.empty()) {
@@ -391,19 +389,6 @@
   if (crl_set->IsExpired())
     dict.Set("crlset_is_expired", true);
 
-  if (!additional_trust_anchors.empty()) {
-    base::Value::List certs;
-    for (auto& anchor : additional_trust_anchors) {
-      std::string pem_encoded;
-      if (X509Certificate::GetPEMEncodedFromDER(
-              x509_util::CryptoBufferAsStringPiece(anchor->cert_buffer()),
-              &pem_encoded)) {
-        certs.Append(std::move(pem_encoded));
-      }
-    }
-    dict.Set("additional_trust_anchors", std::move(certs));
-  }
-
   return dict;
 }
 
@@ -429,10 +414,11 @@
 // static
 scoped_refptr<CertVerifyProc> CertVerifyProc::CreateBuiltinVerifyProc(
     scoped_refptr<CertNetFetcher> cert_net_fetcher,
-    scoped_refptr<CRLSet> crl_set) {
-  return CreateCertVerifyProcBuiltin(std::move(cert_net_fetcher),
-                                     std::move(crl_set),
-                                     CreateSslSystemTrustStore());
+    scoped_refptr<CRLSet> crl_set,
+    const InstanceParams instance_params) {
+  return CreateCertVerifyProcBuiltin(
+      std::move(cert_net_fetcher), std::move(crl_set),
+      CreateSslSystemTrustStore(), instance_params);
 }
 #endif
 
@@ -441,13 +427,15 @@
 scoped_refptr<CertVerifyProc> CertVerifyProc::CreateBuiltinWithChromeRootStore(
     scoped_refptr<CertNetFetcher> cert_net_fetcher,
     scoped_refptr<CRLSet> crl_set,
-    const ChromeRootStoreData* root_store_data) {
+    const ChromeRootStoreData* root_store_data,
+    const InstanceParams instance_params) {
   std::unique_ptr<TrustStoreChrome> chrome_root =
       root_store_data ? std::make_unique<TrustStoreChrome>(*root_store_data)
                       : std::make_unique<TrustStoreChrome>();
   return CreateCertVerifyProcBuiltin(
       std::move(cert_net_fetcher), std::move(crl_set),
-      CreateSslSystemTrustStoreChromeRoot(std::move(chrome_root)));
+      CreateSslSystemTrustStoreChromeRoot(std::move(chrome_root)),
+      instance_params);
 }
 #endif
 
@@ -463,7 +451,6 @@
                            const std::string& ocsp_response,
                            const std::string& sct_list,
                            int flags,
-                           const CertificateList& additional_trust_anchors,
                            CertVerifyResult* verify_result,
                            const NetLogWithSource& net_log) {
   CHECK(cert);
@@ -471,7 +458,7 @@
 
   net_log.BeginEvent(NetLogEventType::CERT_VERIFY_PROC, [&] {
     return CertVerifyParams(cert, hostname, ocsp_response, sct_list, flags,
-                            crl_set(), additional_trust_anchors);
+                            crl_set());
   });
   // CertVerifyProc's contract allows ::VerifyInternal() to wait on File I/O
   // (such as the Windows registry or smart cards on all platforms) or may re-
@@ -486,7 +473,7 @@
   verify_result->verified_cert = cert;
 
   int rv = VerifyInternal(cert, hostname, ocsp_response, sct_list, flags,
-                          additional_trust_anchors, verify_result, net_log);
+                          verify_result, net_log);
 
   CHECK(verify_result->verified_cert);
 
@@ -833,7 +820,7 @@
   return validity_duration > base::Days(398);
 }
 
-CertVerifyProcFactory::ImplParams::ImplParams() {
+CertVerifyProc::ImplParams::ImplParams() {
   crl_set = net::CRLSet::BuiltinCRLSet();
 #if BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL)
   use_chrome_root_store =
@@ -841,13 +828,23 @@
 #endif
 }
 
-CertVerifyProcFactory::ImplParams::~ImplParams() = default;
+CertVerifyProc::ImplParams::~ImplParams() = default;
 
-CertVerifyProcFactory::ImplParams::ImplParams(const ImplParams&) = default;
-CertVerifyProcFactory::ImplParams& CertVerifyProcFactory::ImplParams::operator=(
+CertVerifyProc::ImplParams::ImplParams(const ImplParams&) = default;
+CertVerifyProc::ImplParams& CertVerifyProc::ImplParams::operator=(
     const ImplParams& other) = default;
-CertVerifyProcFactory::ImplParams::ImplParams(ImplParams&&) = default;
-CertVerifyProcFactory::ImplParams& CertVerifyProcFactory::ImplParams::operator=(
+CertVerifyProc::ImplParams::ImplParams(ImplParams&&) = default;
+CertVerifyProc::ImplParams& CertVerifyProc::ImplParams::operator=(
     ImplParams&& other) = default;
 
+CertVerifyProc::InstanceParams::InstanceParams() = default;
+CertVerifyProc::InstanceParams::~InstanceParams() = default;
+
+CertVerifyProc::InstanceParams::InstanceParams(const InstanceParams&) = default;
+CertVerifyProc::InstanceParams& CertVerifyProc::InstanceParams::operator=(
+    const InstanceParams& other) = default;
+CertVerifyProc::InstanceParams::InstanceParams(InstanceParams&&) = default;
+CertVerifyProc::InstanceParams& CertVerifyProc::InstanceParams::operator=(
+    InstanceParams&& other) = default;
+
 }  // namespace net
diff --git a/net/cert/cert_verify_proc.h b/net/cert/cert_verify_proc.h
index faeff3a..e4c1e5e 100644
--- a/net/cert/cert_verify_proc.h
+++ b/net/cert/cert_verify_proc.h
@@ -69,6 +69,57 @@
     VERIFY_FLAGS_LAST = VERIFY_DISABLE_NETWORK_FETCHES
   };
 
+  // The set factory parameters that are variable over time, but are expected to
+  // be consistent between multiple verifiers that are created. For example,
+  // CertNetFetcher is not in this struct as it is expected that different
+  // verifiers will have different net fetchers. (There is no technical
+  // restriction against creating different verifiers with different ImplParams,
+  // structuring the parameters this way just makes some APIs more convenient
+  // for the common case.)
+  struct NET_EXPORT ImplParams {
+    ImplParams();
+    ~ImplParams();
+    ImplParams(const ImplParams&);
+    ImplParams& operator=(const ImplParams& other);
+    ImplParams(ImplParams&&);
+    ImplParams& operator=(ImplParams&& other);
+
+    scoped_refptr<CRLSet> crl_set;
+#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
+    absl::optional<net::ChromeRootStoreData> root_store_data;
+#endif
+#if BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL)
+    bool use_chrome_root_store;
+#endif
+  };
+
+  // The set of parameters that are variable over time and can differ between
+  // different verifiers created by a CertVerifierProcFactory.
+  struct NET_EXPORT InstanceParams {
+    InstanceParams();
+    ~InstanceParams();
+    InstanceParams(const InstanceParams&);
+    InstanceParams& operator=(const InstanceParams& other);
+    InstanceParams(InstanceParams&&);
+    InstanceParams& operator=(InstanceParams&& other);
+
+    // TODO(crbug.com/1477317): store these as ParsedCertificateList here so
+    // that it only needs to be done once since the same InstanceParams can be
+    // used to create a CertVerifyProc multiple times.
+
+    // Additional trust anchors to consider during path validation. Ordinarily,
+    // implementations of CertVerifier use trust anchors from the configured
+    // system store. This is implementation-specific plumbing for passing
+    // additional anchors through.
+    CertificateList additional_trust_anchors;
+
+    // Additional temporary certs to consider as intermediates during path
+    // validation. Ordinarily, implementations of CertVerifier use intermediate
+    // certs from the configured system store. This is implementation-specific
+    // plumbing for passing additional intermediates through.
+    CertificateList additional_untrusted_authorities;
+  };
+
   // These values are persisted to logs. Entries should not be renumbered and
   // numeric values should never be reused.
   enum class NameNormalizationResult {
@@ -92,7 +143,8 @@
   // Creates and returns a CertVerifyProcBuiltin using the SSL SystemTrustStore.
   static scoped_refptr<CertVerifyProc> CreateBuiltinVerifyProc(
       scoped_refptr<CertNetFetcher> cert_net_fetcher,
-      scoped_refptr<CRLSet> crl_set);
+      scoped_refptr<CRLSet> crl_set,
+      const InstanceParams instance_params);
 #endif
 
 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
@@ -102,7 +154,8 @@
   static scoped_refptr<CertVerifyProc> CreateBuiltinWithChromeRootStore(
       scoped_refptr<CertNetFetcher> cert_net_fetcher,
       scoped_refptr<CRLSet> crl_set,
-      const ChromeRootStoreData* root_store_data);
+      const ChromeRootStoreData* root_store_data,
+      const InstanceParams instance_params);
 #endif
 
   CertVerifyProc(const CertVerifyProc&) = delete;
@@ -127,24 +180,14 @@
   // If VERIFY_REV_CHECKING_ENABLED is set in |flags|, online certificate
   // revocation checking is performed (i.e. OCSP and downloading CRLs). CRLSet
   // based revocation checking is always enabled, regardless of this flag.
-  //
-  // |additional_trust_anchors| lists certificates that can be trusted when
-  // building a certificate chain, in addition to the anchors known to the
-  // implementation.
   int Verify(X509Certificate* cert,
              const std::string& hostname,
              const std::string& ocsp_response,
              const std::string& sct_list,
              int flags,
-             const CertificateList& additional_trust_anchors,
              CertVerifyResult* verify_result,
              const NetLogWithSource& net_log);
 
-  // Returns true if the implementation supports passing additional trust
-  // anchors to the Verify() call. The |additional_trust_anchors| parameter
-  // passed to Verify() is ignored when this returns false.
-  virtual bool SupportsAdditionalTrustAnchors() const = 0;
-
  protected:
   explicit CertVerifyProc(scoped_refptr<CRLSet> crl_set);
   virtual ~CertVerifyProc();
@@ -191,7 +234,6 @@
                              const std::string& ocsp_response,
                              const std::string& sct_list,
                              int flags,
-                             const CertificateList& additional_trust_anchors,
                              CertVerifyResult* verify_result,
                              const NetLogWithSource& net_log) = 0;
 
@@ -216,35 +258,13 @@
 class NET_EXPORT CertVerifyProcFactory
     : public base::RefCountedThreadSafe<CertVerifyProcFactory> {
  public:
-  // The set of factory parameters that are variable over time, but are
-  // expected to be consistent between multiple verifiers that are created. For
-  // example, CertNetFetcher is not in this struct as it is expected that
-  // different verifiers will have different net fetchers. (There is no
-  // technical restriction against creating different verifiers with different
-  // ImplParams, structuring the parameters this way just makes some APIs more
-  // convenient for the common case.)
-  struct NET_EXPORT ImplParams {
-    ImplParams();
-    ~ImplParams();
-    ImplParams(const ImplParams&);
-    ImplParams& operator=(const ImplParams& other);
-    ImplParams(ImplParams&&);
-    ImplParams& operator=(ImplParams&& other);
-
-    scoped_refptr<CRLSet> crl_set;
-#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
-    absl::optional<net::ChromeRootStoreData> root_store_data;
-#endif
-#if BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL)
-    bool use_chrome_root_store;
-#endif
-  };
 
   // Create a new CertVerifyProc that uses the passed in CRLSet and
   // ChromeRootStoreData.
   virtual scoped_refptr<CertVerifyProc> CreateCertVerifyProc(
       scoped_refptr<CertNetFetcher> cert_net_fetcher,
-      const ImplParams& impl_params) = 0;
+      const CertVerifyProc::ImplParams& impl_params,
+      const CertVerifyProc::InstanceParams& instance_params) = 0;
 
  protected:
   virtual ~CertVerifyProcFactory() = default;
diff --git a/net/cert/cert_verify_proc_android.cc b/net/cert/cert_verify_proc_android.cc
index deb95a03..8ac8541 100644
--- a/net/cert/cert_verify_proc_android.cc
+++ b/net/cert/cert_verify_proc_android.cc
@@ -352,17 +352,12 @@
 
 CertVerifyProcAndroid::~CertVerifyProcAndroid() = default;
 
-bool CertVerifyProcAndroid::SupportsAdditionalTrustAnchors() const {
-  return false;
-}
-
 int CertVerifyProcAndroid::VerifyInternal(
     X509Certificate* cert,
     const std::string& hostname,
     const std::string& ocsp_response,
     const std::string& sct_list,
     int flags,
-    const CertificateList& additional_trust_anchors,
     CertVerifyResult* verify_result,
     const NetLogWithSource& net_log) {
   std::vector<std::string> cert_bytes;
diff --git a/net/cert/cert_verify_proc_android.h b/net/cert/cert_verify_proc_android.h
index 5fed25d..f874bff 100644
--- a/net/cert/cert_verify_proc_android.h
+++ b/net/cert/cert_verify_proc_android.h
@@ -22,8 +22,6 @@
   CertVerifyProcAndroid(const CertVerifyProcAndroid&) = delete;
   CertVerifyProcAndroid& operator=(const CertVerifyProcAndroid&) = delete;
 
-  bool SupportsAdditionalTrustAnchors() const override;
-
  protected:
   ~CertVerifyProcAndroid() override;
 
@@ -33,7 +31,6 @@
                      const std::string& ocsp_response,
                      const std::string& sct_list,
                      int flags,
-                     const CertificateList& additional_trust_anchors,
                      CertVerifyResult* verify_result,
                      const NetLogWithSource& net_log) override;
 
diff --git a/net/cert/cert_verify_proc_android_unittest.cc b/net/cert/cert_verify_proc_android_unittest.cc
index 899ebf6..6500d1fe 100644
--- a/net/cert/cert_verify_proc_android_unittest.cc
+++ b/net/cert/cert_verify_proc_android_unittest.cc
@@ -80,7 +80,6 @@
   }
 
   scoped_refptr<MockCertNetFetcher> fetcher_;
-  const CertificateList empty_cert_list_;
   std::unique_ptr<CertBuilder> root_;
   std::unique_ptr<CertBuilder> intermediate_;
   std::unique_ptr<CertBuilder> leaf_;
@@ -102,8 +101,8 @@
   CertVerifyResult verify_result;
   EXPECT_EQ(OK, proc->Verify(LeafWithIntermediate().get(), kHostname,
                              /*ocsp_response=*/std::string(),
-                             /*sct_list=*/std::string(), 0, empty_cert_list_,
-                             &verify_result, NetLogWithSource()));
+                             /*sct_list=*/std::string(), 0, &verify_result,
+                             NetLogWithSource()));
 }
 
 // Tests that if the certificate does not contain an AIA URL, no AIA fetch
@@ -118,8 +117,8 @@
   EXPECT_EQ(
       ERR_CERT_AUTHORITY_INVALID,
       proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
-                   /*sct_list=*/std::string(), 0, empty_cert_list_,
-                   &verify_result, NetLogWithSource()));
+                   /*sct_list=*/std::string(), 0, &verify_result,
+                   NetLogWithSource()));
 }
 
 // Tests that if a certificate contains one file:// URL and one http:// URL,
@@ -149,8 +148,8 @@
   CertVerifyResult verify_result;
   EXPECT_EQ(OK, proc->Verify(LeafOnly().get(), kHostname,
                              /*ocsp_response=*/std::string(),
-                             /*sct_list=*/std::string(), 0, empty_cert_list_,
-                             &verify_result, NetLogWithSource()));
+                             /*sct_list=*/std::string(), 0, &verify_result,
+                             NetLogWithSource()));
 }
 
 // Tests that if an AIA request returns the wrong intermediate, certificate
@@ -172,8 +171,8 @@
   EXPECT_EQ(
       ERR_CERT_AUTHORITY_INVALID,
       proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
-                   /*sct_list=*/std::string(), 0, empty_cert_list_,
-                   &verify_result, NetLogWithSource()));
+                   /*sct_list=*/std::string(), 0, &verify_result,
+                   NetLogWithSource()));
 }
 
 // Tests that if an AIA request returns an error, certificate verification
@@ -192,8 +191,8 @@
   EXPECT_EQ(
       ERR_CERT_AUTHORITY_INVALID,
       proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
-                   /*sct_list=*/std::string(), 0, empty_cert_list_,
-                   &verify_result, NetLogWithSource()));
+                   /*sct_list=*/std::string(), 0, &verify_result,
+                   NetLogWithSource()));
 }
 
 // Tests that if an AIA request returns an unparseable cert, certificate
@@ -212,8 +211,8 @@
   EXPECT_EQ(
       ERR_CERT_AUTHORITY_INVALID,
       proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
-                   /*sct_list=*/std::string(), 0, empty_cert_list_,
-                   &verify_result, NetLogWithSource()));
+                   /*sct_list=*/std::string(), 0, &verify_result,
+                   NetLogWithSource()));
 }
 
 // Tests that if a certificate has two HTTP AIA URLs, they are both fetched. If
@@ -248,8 +247,8 @@
   CertVerifyResult verify_result;
   EXPECT_EQ(OK, proc->Verify(LeafOnly().get(), kHostname,
                              /*ocsp_response=*/std::string(),
-                             /*sct_list=*/std::string(), 0, empty_cert_list_,
-                             &verify_result, NetLogWithSource()));
+                             /*sct_list=*/std::string(), 0, &verify_result,
+                             NetLogWithSource()));
 }
 
 // Tests that if an intermediate is fetched via AIA, and the intermediate itself
@@ -279,8 +278,8 @@
   EXPECT_EQ(
       ERR_CERT_AUTHORITY_INVALID,
       proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
-                   /*sct_list=*/std::string(), 0, empty_cert_list_,
-                   &verify_result, NetLogWithSource()));
+                   /*sct_list=*/std::string(), 0, &verify_result,
+                   NetLogWithSource()));
 }
 
 // Tests that if a certificate contains six AIA URLs, only the first five are
@@ -308,8 +307,8 @@
   EXPECT_EQ(
       ERR_CERT_AUTHORITY_INVALID,
       proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
-                   /*sct_list=*/std::string(), 0, empty_cert_list_,
-                   &verify_result, NetLogWithSource()));
+                   /*sct_list=*/std::string(), 0, &verify_result,
+                   NetLogWithSource()));
 }
 
 // Tests that if the supplied chain contains an intermediate with an AIA URL,
@@ -333,8 +332,8 @@
   EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID,
             proc->Verify(LeafWithIntermediate().get(), kHostname,
                          /*ocsp_response=*/std::string(),
-                         /*sct_list=*/std::string(), 0, empty_cert_list_,
-                         &verify_result, NetLogWithSource()));
+                         /*sct_list=*/std::string(), 0, &verify_result,
+                         NetLogWithSource()));
 }
 
 }  // namespace net
diff --git a/net/cert/cert_verify_proc_builtin.cc b/net/cert/cert_verify_proc_builtin.cc
index 89f7980a..4f692d5 100644
--- a/net/cert/cert_verify_proc_builtin.cc
+++ b/net/cert/cert_verify_proc_builtin.cc
@@ -79,6 +79,14 @@
   return results;
 }
 
+base::Value::Dict NetLogAdditionalCert(const CRYPTO_BUFFER* cert_handle,
+                                       const bssl::CertificateTrust& trust,
+                                       const bssl::CertErrors& errors) {
+  base::Value::Dict results = NetLogCertParams(cert_handle, errors);
+  results.Set("trust", trust.ToDebugString());
+  return results;
+}
+
 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
 base::Value::Dict NetLogChromeRootStoreVersion(
     int64_t chrome_root_store_version) {
@@ -170,9 +178,12 @@
 class CertVerifyProcTrustStore {
  public:
   // |system_trust_store| must outlive this object.
-  explicit CertVerifyProcTrustStore(SystemTrustStore* system_trust_store)
-      : system_trust_store_(system_trust_store) {
-    trust_store_.AddTrustStore(&additional_trust_store_);
+  explicit CertVerifyProcTrustStore(
+      SystemTrustStore* system_trust_store,
+      bssl::TrustStoreInMemory* additional_trust_store)
+      : system_trust_store_(system_trust_store),
+        additional_trust_store_(additional_trust_store) {
+    trust_store_.AddTrustStore(additional_trust_store_);
     trust_store_.AddTrustStore(system_trust_store_->GetTrustStore());
     // When running in test mode, also layer in the test-only root certificates.
     //
@@ -187,10 +198,6 @@
 
   bssl::TrustStore* trust_store() { return &trust_store_; }
 
-  void AddTrustAnchor(std::shared_ptr<const bssl::ParsedCertificate> cert) {
-    additional_trust_store_.AddTrustAnchor(std::move(cert));
-  }
-
   bool IsKnownRoot(const bssl::ParsedCertificate* trust_anchor) const {
     if (TestRootCerts::HasInstance() &&
         TestRootCerts::GetInstance()->IsKnownRoot(
@@ -202,12 +209,12 @@
 
   bool IsAdditionalTrustAnchor(
       const bssl::ParsedCertificate* trust_anchor) const {
-    return additional_trust_store_.Contains(trust_anchor);
+    return additional_trust_store_->Contains(trust_anchor);
   }
 
  private:
   raw_ptr<SystemTrustStore> system_trust_store_;
-  bssl::TrustStoreInMemory additional_trust_store_;
+  raw_ptr<bssl::TrustStoreInMemory> additional_trust_store_;
   bssl::TrustStoreCollection trust_store_;
 };
 
@@ -413,13 +420,20 @@
   base::TimeTicks deadline_;
 };
 
+std::shared_ptr<const bssl::ParsedCertificate> ParseCertificateFromBuffer(
+    CRYPTO_BUFFER* cert_handle,
+    bssl::CertErrors* errors) {
+  return bssl::ParsedCertificate::Create(
+      bssl::UpRef(cert_handle), x509_util::DefaultParseCertificateOptions(),
+      errors);
+}
+
 class CertVerifyProcBuiltin : public CertVerifyProc {
  public:
   CertVerifyProcBuiltin(scoped_refptr<CertNetFetcher> net_fetcher,
                         scoped_refptr<CRLSet> crl_set,
-                        std::unique_ptr<SystemTrustStore> system_trust_store);
-
-  bool SupportsAdditionalTrustAnchors() const override;
+                        std::unique_ptr<SystemTrustStore> system_trust_store,
+                        const CertVerifyProc::InstanceParams& instance_params);
 
  protected:
   ~CertVerifyProcBuiltin() override;
@@ -430,38 +444,69 @@
                      const std::string& ocsp_response,
                      const std::string& sct_list,
                      int flags,
-                     const CertificateList& additional_trust_anchors,
                      CertVerifyResult* verify_result,
                      const NetLogWithSource& net_log) override;
 
   const scoped_refptr<CertNetFetcher> net_fetcher_;
   const std::unique_ptr<SystemTrustStore> system_trust_store_;
+  bssl::TrustStoreInMemory additional_trust_store_;
 };
 
 CertVerifyProcBuiltin::CertVerifyProcBuiltin(
     scoped_refptr<CertNetFetcher> net_fetcher,
     scoped_refptr<CRLSet> crl_set,
-    std::unique_ptr<SystemTrustStore> system_trust_store)
+    std::unique_ptr<SystemTrustStore> system_trust_store,
+    const CertVerifyProc::InstanceParams& instance_params)
     : CertVerifyProc(std::move(crl_set)),
       net_fetcher_(std::move(net_fetcher)),
       system_trust_store_(std::move(system_trust_store)) {
   DCHECK(system_trust_store_);
+
+  NetLogWithSource net_log =
+      NetLogWithSource::Make(net::NetLogSourceType::CERT_VERIFY_PROC_CREATED);
+  net_log.BeginEvent(NetLogEventType::CERT_VERIFY_PROC_CREATED);
+
+  // Parse the additional trust anchors and setup trust store.
+  for (const auto& x509_cert : instance_params.additional_trust_anchors) {
+    bssl::CertErrors parsing_errors;
+    std::shared_ptr<const bssl::ParsedCertificate> cert =
+        ParseCertificateFromBuffer(x509_cert->cert_buffer(), &parsing_errors);
+    if (cert) {
+      additional_trust_store_.AddTrustAnchor(std::move(cert));
+    }
+    net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_CERT, [&] {
+      return NetLogAdditionalCert(x509_cert->cert_buffer(),
+                                  bssl::CertificateTrust::ForTrustAnchor(),
+                                  parsing_errors);
+    });
+  }
+
+  for (const auto& x509_cert :
+       instance_params.additional_untrusted_authorities) {
+    bssl::CertErrors parsing_errors;
+    std::shared_ptr<const bssl::ParsedCertificate> cert =
+        ParseCertificateFromBuffer(x509_cert->cert_buffer(), &parsing_errors);
+    // Only add the untrusted cert if it isn't already present in
+    // `additional_trust_store_`. If the same cert was already added as a
+    // trust anchor then adding it again as an untrusted cert can lead to it
+    // not being treated as a trust anchor since TrustStoreInMemory doesn't
+    // expect to contain duplicates.
+    if (cert && !additional_trust_store_.Contains(cert.get())) {
+      additional_trust_store_.AddCertificateWithUnspecifiedTrust(
+          std::move(cert));
+    }
+    net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_CERT, [&] {
+      return NetLogAdditionalCert(x509_cert->cert_buffer(),
+                                  bssl::CertificateTrust::ForUnspecified(),
+                                  parsing_errors);
+    });
+  }
+
+  net_log.EndEvent(NetLogEventType::CERT_VERIFY_PROC_CREATED);
 }
 
 CertVerifyProcBuiltin::~CertVerifyProcBuiltin() = default;
 
-bool CertVerifyProcBuiltin::SupportsAdditionalTrustAnchors() const {
-  return true;
-}
-
-std::shared_ptr<const bssl::ParsedCertificate> ParseCertificateFromBuffer(
-    CRYPTO_BUFFER* cert_handle,
-    bssl::CertErrors* errors) {
-  return bssl::ParsedCertificate::Create(
-      bssl::UpRef(cert_handle), x509_util::DefaultParseCertificateOptions(),
-      errors);
-}
-
 void AddIntermediatesToIssuerSource(X509Certificate* x509_cert,
                                     bssl::CertIssuerSourceStatic* intermediates,
                                     const NetLogWithSource& net_log) {
@@ -474,8 +519,9 @@
     net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_INPUT_CERT, [&] {
       return NetLogCertParams(intermediate.get(), errors);
     });
-    if (cert)
+    if (cert) {
       intermediates->AddCert(std::move(cert));
+    }
   }
 }
 
@@ -749,7 +795,6 @@
     const std::string& ocsp_response,
     const std::string& sct_list,
     int flags,
-    const CertificateList& additional_trust_anchors,
     CertVerifyResult* verify_result,
     const NetLogWithSource& net_log) {
   // VerifyInternal() is expected to carry out verifications using the current
@@ -774,6 +819,10 @@
   }
 #endif
 
+  // TODO(crbug.com/1477317): Netlog extra configuration information stored
+  // inside CertVerifyProcBuiltin (e.g. certs in additional_trust_store and
+  // system trust store)
+
   // Parse the target certificate.
   std::shared_ptr<const bssl::ParsedCertificate> target;
   {
@@ -795,22 +844,8 @@
   bssl::CertIssuerSourceStatic intermediates;
   AddIntermediatesToIssuerSource(input_cert, &intermediates, net_log);
 
-  // Parse the additional trust anchors and setup trust store.
-  CertVerifyProcTrustStore trust_store(system_trust_store_.get());
-  for (const auto& x509_cert : additional_trust_anchors) {
-    bssl::CertErrors parsing_errors;
-    std::shared_ptr<const bssl::ParsedCertificate> cert =
-        ParseCertificateFromBuffer(x509_cert->cert_buffer(), &parsing_errors);
-    if (cert)
-      trust_store.AddTrustAnchor(std::move(cert));
-    // TODO(crbug.com/634484): this duplicates the logging of the
-    // additional_trust_anchors maybe should only log if there is a parse
-    // error/warning?
-    net_log.AddEvent(
-        NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_TRUST_ANCHOR, [&] {
-          return NetLogCertParams(x509_cert->cert_buffer(), parsing_errors);
-        });
-  }
+  CertVerifyProcTrustStore trust_store(system_trust_store_.get(),
+                                       &additional_trust_store_);
 
   // Get the global dependencies.
   const EVRootCAMetadata* ev_metadata = EVRootCAMetadata::GetInstance();
@@ -924,10 +959,11 @@
 scoped_refptr<CertVerifyProc> CreateCertVerifyProcBuiltin(
     scoped_refptr<CertNetFetcher> net_fetcher,
     scoped_refptr<CRLSet> crl_set,
-    std::unique_ptr<SystemTrustStore> system_trust_store) {
+    std::unique_ptr<SystemTrustStore> system_trust_store,
+    const CertVerifyProc::InstanceParams& instance_params) {
   return base::MakeRefCounted<CertVerifyProcBuiltin>(
-      std::move(net_fetcher), std::move(crl_set),
-      std::move(system_trust_store));
+      std::move(net_fetcher), std::move(crl_set), std::move(system_trust_store),
+      instance_params);
 }
 
 base::TimeDelta GetCertVerifyProcBuiltinTimeLimitForTesting() {
diff --git a/net/cert/cert_verify_proc_builtin.h b/net/cert/cert_verify_proc_builtin.h
index 34fd9a1..60f78a2e 100644
--- a/net/cert/cert_verify_proc_builtin.h
+++ b/net/cert/cert_verify_proc_builtin.h
@@ -10,11 +10,11 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/time/time.h"
 #include "net/base/net_export.h"
+#include "net/cert/cert_verify_proc.h"
 
 namespace net {
 
 class CertNetFetcher;
-class CertVerifyProc;
 class CRLSet;
 class SystemTrustStore;
 
@@ -24,7 +24,8 @@
 NET_EXPORT scoped_refptr<CertVerifyProc> CreateCertVerifyProcBuiltin(
     scoped_refptr<CertNetFetcher> net_fetcher,
     scoped_refptr<CRLSet> crl_set,
-    std::unique_ptr<SystemTrustStore> system_trust_store);
+    std::unique_ptr<SystemTrustStore> system_trust_store,
+    const CertVerifyProc::InstanceParams& instance_params);
 
 // Returns the time limit used by CertVerifyProcBuiltin. Intended for test use.
 NET_EXPORT_PRIVATE base::TimeDelta
diff --git a/net/cert/cert_verify_proc_builtin_unittest.cc b/net/cert/cert_verify_proc_builtin_unittest.cc
index b76d3ff..8696c34 100644
--- a/net/cert/cert_verify_proc_builtin_unittest.cc
+++ b/net/cert/cert_verify_proc_builtin_unittest.cc
@@ -99,17 +99,15 @@
                          scoped_refptr<X509Certificate> cert,
                          const std::string& hostname,
                          int flags,
-                         const CertificateList& additional_trust_anchors,
                          CertVerifyResult* verify_result,
                          NetLogSource* out_source) {
   base::ScopedAllowBaseSyncPrimitivesForTesting scoped_allow_blocking;
   NetLogWithSource net_log(NetLogWithSource::Make(
       net::NetLog::Get(), net::NetLogSourceType::CERT_VERIFIER_TASK));
-  int error =
-      verify_proc->Verify(cert.get(), hostname,
-                          /*ocsp_response=*/std::string(),
-                          /*sct_list=*/std::string(), flags,
-                          additional_trust_anchors, verify_result, net_log);
+  int error = verify_proc->Verify(cert.get(), hostname,
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string(), flags,
+                                  verify_result, net_log);
   *out_source = net_log.source();
   return error;
 }
@@ -131,7 +129,7 @@
   }
 
 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
-  int64_t chrome_root_store_version() override { return 0; }
+  int64_t chrome_root_store_version() const override { return 0; }
 #endif
 
  private:
@@ -165,11 +163,8 @@
  public:
   void SetUp() override {
     cert_net_fetcher_ = base::MakeRefCounted<CertNetFetcherURLRequest>();
-    auto mock_system_trust_store = std::make_unique<MockSystemTrustStore>();
-    mock_system_trust_store_ = mock_system_trust_store.get();
-    verify_proc_ = CreateCertVerifyProcBuiltin(
-        cert_net_fetcher_, CRLSet::EmptyCRLSetForTesting(),
-        std::move(mock_system_trust_store));
+
+    InitializeVerifyProc({});
 
     context_ = CreateTestURLRequestContextBuilder()->Build();
 
@@ -178,10 +173,19 @@
 
   void TearDown() override { cert_net_fetcher_->Shutdown(); }
 
+  void InitializeVerifyProc(const CertificateList& additional_trust_anchors) {
+    auto mock_system_trust_store = std::make_unique<MockSystemTrustStore>();
+    mock_system_trust_store_ = mock_system_trust_store.get();
+    CertVerifyProc::InstanceParams instance_params;
+    instance_params.additional_trust_anchors = additional_trust_anchors;
+    verify_proc_ = CreateCertVerifyProcBuiltin(
+        cert_net_fetcher_, CRLSet::EmptyCRLSetForTesting(),
+        std::move(mock_system_trust_store), instance_params);
+  }
+
   void Verify(scoped_refptr<X509Certificate> cert,
               const std::string& hostname,
               int flags,
-              const CertificateList& additional_trust_anchors,
               CertVerifyResult* verify_result,
               NetLogSource* out_source,
               CompletionOnceCallback callback) {
@@ -189,8 +193,7 @@
         FROM_HERE,
         {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
         base::BindOnce(&VerifyOnWorkerThread, verify_proc_, std::move(cert),
-                       hostname, flags, additional_trust_anchors, verify_result,
-                       out_source),
+                       hostname, flags, verify_result, out_source),
         std::move(callback));
   }
 
@@ -242,6 +245,8 @@
 
 TEST_F(CertVerifyProcBuiltinTest, ShouldBypassHSTS) {
   auto [leaf, root] = CertBuilder::CreateSimpleChain2();
+  InitializeVerifyProc(
+      /*additional_trust_anchors=*/{root->GetX509Certificate()});
 
   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
   ASSERT_TRUE(test_server.InitializeAndListen());
@@ -267,7 +272,6 @@
         test_server.base_url().host()));
     Verify(chain.get(), "www.example.com",
            CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
-           /*additional_trust_anchors=*/{root->GetX509Certificate()},
            &verify_result, &verify_net_log_source, verify_callback.callback());
 
     int error = verify_callback.WaitForResult();
@@ -278,6 +282,8 @@
 
 TEST_F(CertVerifyProcBuiltinTest, SimpleSuccess) {
   auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
+  InitializeVerifyProc(
+      /*additional_trust_anchors=*/{root->GetX509Certificate()});
 
   scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
   ASSERT_TRUE(chain.get());
@@ -286,9 +292,8 @@
   CertVerifyResult verify_result;
   NetLogSource verify_net_log_source;
   TestCompletionCallback callback;
-  Verify(chain.get(), "www.example.com", /*flags=*/0,
-         /*additional_trust_anchors=*/{root->GetX509Certificate()},
-         &verify_result, &verify_net_log_source, callback.callback());
+  Verify(chain.get(), "www.example.com", /*flags=*/0, &verify_result,
+         &verify_net_log_source, callback.callback());
 
   int error = callback.WaitForResult();
   EXPECT_THAT(error, IsOk());
@@ -299,6 +304,8 @@
 
 TEST_F(CertVerifyProcBuiltinTest, CRLNotCheckedForKnownRoots) {
   auto [leaf, root] = CertBuilder::CreateSimpleChain2();
+  InitializeVerifyProc(
+      /*additional_trust_anchors=*/{root->GetX509Certificate()});
 
   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
   ASSERT_TRUE(test_server.InitializeAndListen());
@@ -319,7 +326,6 @@
     TestCompletionCallback verify_callback;
     Verify(chain.get(), "www.example.com",
            CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
-           /*additional_trust_anchors=*/{root->GetX509Certificate()},
            &verify_result, &verify_net_log_source, verify_callback.callback());
 
     int error = verify_callback.WaitForResult();
@@ -335,7 +341,6 @@
     TestCompletionCallback verify_callback;
     Verify(chain.get(), "www.example.com",
            CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
-           /*additional_trust_anchors=*/{root->GetX509Certificate()},
            &verify_result, &verify_net_log_source, verify_callback.callback());
 
     int error = verify_callback.WaitForResult();
@@ -353,6 +358,8 @@
 // checking, additional CRL fetches will not be attempted.
 TEST_F(CertVerifyProcBuiltinTest, RevocationCheckDeadlineCRL) {
   auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
+  InitializeVerifyProc(
+      /*additional_trust_anchors=*/{root->GetX509Certificate()});
 
   const base::TimeDelta timeout_increment =
       CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
@@ -401,7 +408,6 @@
   TestCompletionCallback verify_callback;
   Verify(chain.get(), "www.example.com",
          CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
-         /*additional_trust_anchors=*/{root->GetX509Certificate()},
          &verify_result, &verify_net_log_source, verify_callback.callback());
 
   for (int i = 0; i < expected_request_count; i++) {
@@ -428,6 +434,8 @@
 // checking, additional OCSP fetches will not be attempted.
 TEST_F(CertVerifyProcBuiltinTest, RevocationCheckDeadlineOCSP) {
   auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
+  InitializeVerifyProc(
+      /*additional_trust_anchors=*/{root->GetX509Certificate()});
 
   const base::TimeDelta timeout_increment =
       CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
@@ -475,7 +483,6 @@
   TestCompletionCallback verify_callback;
   Verify(chain.get(), "www.example.com",
          CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
-         /*additional_trust_anchors=*/{root->GetX509Certificate()},
          &verify_result, &verify_net_log_source, verify_callback.callback());
 
   for (int i = 0; i < expected_request_count; i++) {
@@ -500,6 +507,8 @@
 // is done.
 TEST_F(CertVerifyProcBuiltinTest, EVNoOCSPRevocationChecks) {
   auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
+  InitializeVerifyProc(
+      /*additional_trust_anchors=*/{root->GetX509Certificate()});
 
   // Add test EV policy to leaf and intermediate.
   static const char kEVTestCertPolicy[] = "1.2.3.4";
@@ -537,7 +546,6 @@
   TestCompletionCallback verify_callback;
   Verify(chain.get(), "www.example.com",
          /*flags=*/0,
-         /*additional_trust_anchors=*/{root->GetX509Certificate()},
          &verify_result, &verify_net_log_source, verify_callback.callback());
 
   // EV doesn't do revocation checking, therefore verification result
@@ -574,6 +582,8 @@
 
 TEST_F(CertVerifyProcBuiltinTest, DeadlineExceededDuringSyncGetIssuers) {
   auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
+  InitializeVerifyProc(
+      /*additional_trust_anchors=*/{root->GetX509Certificate()});
 
   BlockingTrustStore trust_store;
   AddTrustStore(&trust_store);
@@ -592,7 +602,6 @@
   TestCompletionCallback verify_callback;
   Verify(chain.get(), "www.example.com",
          /*flags=*/0,
-         /*additional_trust_anchors=*/{root->GetX509Certificate()},
          &verify_result, &verify_net_log_source, verify_callback.callback());
 
   // Wait for trust_store.SyncGetIssuersOf to be called.
@@ -663,8 +672,8 @@
   CertVerifyResult verify_result;
   NetLogSource verify_net_log_source;
   TestCompletionCallback callback;
-  Verify(chain.get(), "www.example.com", flags, CertificateList(),
-         &verify_result, &verify_net_log_source, callback.callback());
+  Verify(chain.get(), "www.example.com", flags, &verify_result,
+         &verify_net_log_source, callback.callback());
   int error = callback.WaitForResult();
   // Unknown signature algorithm in the leaf cert should result in the cert
   // being invalid.
@@ -687,8 +696,8 @@
   CertVerifyResult verify_result;
   NetLogSource verify_net_log_source;
   TestCompletionCallback callback;
-  Verify(chain.get(), "www.example.com", flags, CertificateList(),
-         &verify_result, &verify_net_log_source, callback.callback());
+  Verify(chain.get(), "www.example.com", flags, &verify_result,
+         &verify_net_log_source, callback.callback());
   int error = callback.WaitForResult();
   // Invalid signature algorithm in the leaf cert should result in the
   // cert being invalid.
@@ -709,8 +718,8 @@
   CertVerifyResult verify_result;
   NetLogSource verify_net_log_source;
   TestCompletionCallback callback;
-  Verify(chain.get(), "www.example.com", flags, CertificateList(),
-         &verify_result, &verify_net_log_source, callback.callback());
+  Verify(chain.get(), "www.example.com", flags, &verify_result,
+         &verify_net_log_source, callback.callback());
   int error = callback.WaitForResult();
   // Unknown signature algorithm in the intermediate cert should result in the
   // cert being invalid.
@@ -734,8 +743,8 @@
   CertVerifyResult verify_result;
   NetLogSource verify_net_log_source;
   TestCompletionCallback callback;
-  Verify(chain.get(), "www.example.com", flags, CertificateList(),
-         &verify_result, &verify_net_log_source, callback.callback());
+  Verify(chain.get(), "www.example.com", flags, &verify_result,
+         &verify_net_log_source, callback.callback());
   int error = callback.WaitForResult();
   // Invalid signature algorithm in the intermediate cert should result in the
   // cert being invalid.
@@ -756,8 +765,8 @@
   CertVerifyResult verify_result;
   NetLogSource verify_net_log_source;
   TestCompletionCallback callback;
-  Verify(chain.get(), "www.example.com", flags, CertificateList(),
-         &verify_result, &verify_net_log_source, callback.callback());
+  Verify(chain.get(), "www.example.com", flags, &verify_result,
+         &verify_net_log_source, callback.callback());
   int error = callback.WaitForResult();
   // Unknown signature algorithm in the root cert should have no effect on
   // verification.
@@ -790,8 +799,8 @@
   CertVerifyResult verify_result;
   NetLogSource verify_net_log_source;
   TestCompletionCallback callback;
-  Verify(chain.get(), "www.example.com", flags, CertificateList(),
-         &verify_result, &verify_net_log_source, callback.callback());
+  Verify(chain.get(), "www.example.com", flags, &verify_result,
+         &verify_net_log_source, callback.callback());
   int error = callback.WaitForResult();
   // Invalid signature algorithm in the root cert should have no effect on
   // verification.
@@ -869,8 +878,8 @@
   CertVerifyResult verify_result;
   NetLogSource verify_net_log_source;
   TestCompletionCallback callback;
-  Verify(chain.get(), "www.example.com", flags, CertificateList(),
-         &verify_result, &verify_net_log_source, callback.callback());
+  Verify(chain.get(), "www.example.com", flags, &verify_result,
+         &verify_net_log_source, callback.callback());
   int error = callback.WaitForResult();
 
   auto events = net_log_observer.GetEntriesForSource(verify_net_log_source);
diff --git a/net/cert/cert_verify_proc_ios.cc b/net/cert/cert_verify_proc_ios.cc
index 440e725..f4356c2 100644
--- a/net/cert/cert_verify_proc_ios.cc
+++ b/net/cert/cert_verify_proc_ios.cc
@@ -386,10 +386,6 @@
 #endif  // !defined(__IPHONE_12_0) || __IPHONE_OS_VERSION_MIN_REQUIRED <
         // __IPHONE_12_0
 
-bool CertVerifyProcIOS::SupportsAdditionalTrustAnchors() const {
-  return false;
-}
-
 CertVerifyProcIOS::~CertVerifyProcIOS() = default;
 
 int CertVerifyProcIOS::VerifyInternal(
@@ -398,7 +394,6 @@
     const std::string& ocsp_response,
     const std::string& sct_list,
     int flags,
-    const CertificateList& additional_trust_anchors,
     CertVerifyResult* verify_result,
     const NetLogWithSource& net_log) {
   ScopedCFTypeRef<CFArrayRef> trust_policies;
diff --git a/net/cert/cert_verify_proc_ios.h b/net/cert/cert_verify_proc_ios.h
index 87e4a1e..a5a5308 100644
--- a/net/cert/cert_verify_proc_ios.h
+++ b/net/cert/cert_verify_proc_ios.h
@@ -26,8 +26,6 @@
   // indicated that the certificate is not trusted.
   static CertStatus GetCertFailureStatusFromError(CFErrorRef error);
 
-  bool SupportsAdditionalTrustAnchors() const override;
-
  protected:
   ~CertVerifyProcIOS() override;
 
@@ -44,7 +42,6 @@
                      const std::string& ocsp_response,
                      const std::string& sct_list,
                      int flags,
-                     const CertificateList& additional_trust_anchors,
                      CertVerifyResult* verify_result,
                      const NetLogWithSource& net_log) override;
 };
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index 03bc456..df95b9d 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -136,9 +136,6 @@
   MockCertVerifyProc(const MockCertVerifyProc&) = delete;
   MockCertVerifyProc& operator=(const MockCertVerifyProc&) = delete;
 
-  // CertVerifyProc implementation:
-  bool SupportsAdditionalTrustAnchors() const override { return false; }
-
  protected:
   ~MockCertVerifyProc() override = default;
 
@@ -148,7 +145,6 @@
                      const std::string& ocsp_response,
                      const std::string& sct_list,
                      int flags,
-                     const CertificateList& additional_trust_anchors,
                      CertVerifyResult* verify_result,
                      const NetLogWithSource& net_log) override;
 
@@ -156,15 +152,13 @@
   const int error_ = OK;
 };
 
-int MockCertVerifyProc::VerifyInternal(
-    X509Certificate* cert,
-    const std::string& hostname,
-    const std::string& ocsp_response,
-    const std::string& sct_list,
-    int flags,
-    const CertificateList& additional_trust_anchors,
-    CertVerifyResult* verify_result,
-    const NetLogWithSource& net_log) {
+int MockCertVerifyProc::VerifyInternal(X509Certificate* cert,
+                                       const std::string& hostname,
+                                       const std::string& ocsp_response,
+                                       const std::string& sct_list,
+                                       int flags,
+                                       CertVerifyResult* verify_result,
+                                       const NetLogWithSource& net_log) {
   *verify_result = result_;
   verify_result->verified_cert = cert;
   return error_;
@@ -203,7 +197,13 @@
 scoped_refptr<CertVerifyProc> CreateCertVerifyProc(
     CertVerifyProcType type,
     scoped_refptr<CertNetFetcher> cert_net_fetcher,
-    scoped_refptr<CRLSet> crl_set) {
+    scoped_refptr<CRLSet> crl_set,
+    CertificateList additional_trust_anchors,
+    CertificateList additional_untrusted_authorities) {
+  CertVerifyProc::InstanceParams instance_params;
+  instance_params.additional_trust_anchors = additional_trust_anchors;
+  instance_params.additional_untrusted_authorities =
+      additional_untrusted_authorities;
   switch (type) {
 #if BUILDFLAG(IS_ANDROID)
     case CERT_VERIFY_PROC_ANDROID:
@@ -215,16 +215,17 @@
 #endif
 #if BUILDFLAG(IS_FUCHSIA)
     case CERT_VERIFY_PROC_BUILTIN:
-      return CreateCertVerifyProcBuiltin(std::move(cert_net_fetcher),
-                                         std::move(crl_set),
-                                         CreateSslSystemTrustStore());
+      return CreateCertVerifyProcBuiltin(
+          std::move(cert_net_fetcher), std::move(crl_set),
+          CreateSslSystemTrustStore(), instance_params);
 #endif
 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
     case CERT_VERIFY_PROC_BUILTIN_CHROME_ROOTS:
       return CreateCertVerifyProcBuiltin(
           std::move(cert_net_fetcher), std::move(crl_set),
           CreateSslSystemTrustStoreChromeRoot(
-              std::make_unique<net::TrustStoreChrome>()));
+              std::make_unique<net::TrustStoreChrome>()),
+          instance_params);
 #endif
     default:
       return nullptr;
@@ -292,51 +293,57 @@
 
   // CertNetFetcher may be initialized by subclasses that want to use net
   // fetching by calling SetUpWithCertNetFetcher instead of SetUp.
-  void SetUpWithCertNetFetcher(scoped_refptr<CertNetFetcher> cert_net_fetcher,
-                               scoped_refptr<CRLSet> crl_set) {
+  void SetUpWithCertNetFetcher(
+      scoped_refptr<CertNetFetcher> cert_net_fetcher,
+      scoped_refptr<CRLSet> crl_set,
+      CertificateList additional_trust_anchors,
+      CertificateList additional_untrusted_authorities) {
     CertVerifyProcType type = verify_proc_type();
-    verify_proc_ = CreateCertVerifyProc(type, std::move(cert_net_fetcher),
-                                        std::move(crl_set));
+    verify_proc_ = CreateCertVerifyProc(
+        type, std::move(cert_net_fetcher), std::move(crl_set),
+        additional_trust_anchors, additional_untrusted_authorities);
     ASSERT_TRUE(verify_proc_);
   }
 
   virtual void SetUpCertVerifyProc(scoped_refptr<CRLSet> crl_set) {
-    SetUpWithCertNetFetcher(nullptr, std::move(crl_set));
+    SetUpWithCertNetFetcher(nullptr, std::move(crl_set),
+                            /*additional_trust_anchors=*/{},
+                            /*additional_untrusted_authorities=*/{});
+  }
+
+  virtual void SetUpWithAdditionalCerts(
+      CertificateList additional_trust_anchors,
+      CertificateList additional_untrusted_authorities) {
+    SetUpWithCertNetFetcher(nullptr, CRLSet::BuiltinCRLSet(),
+                            additional_trust_anchors,
+                            additional_untrusted_authorities);
   }
 
   int Verify(X509Certificate* cert,
              const std::string& hostname,
              int flags,
-             const CertificateList& additional_trust_anchors,
              CertVerifyResult* verify_result,
              const NetLogWithSource& net_log) {
     return verify_proc_->Verify(cert, hostname, /*ocsp_response=*/std::string(),
                                 /*sct_list=*/std::string(), flags,
-                                additional_trust_anchors, verify_result,
-                                net_log);
+                                verify_result, net_log);
   }
 
   int Verify(X509Certificate* cert,
              const std::string& hostname,
              int flags,
-             const CertificateList& additional_trust_anchors,
              CertVerifyResult* verify_result) {
-    return Verify(cert, hostname, flags, additional_trust_anchors,
-                  verify_result, NetLogWithSource());
+    return Verify(cert, hostname, flags, verify_result, NetLogWithSource());
   }
 
   int Verify(X509Certificate* cert, const std::string& hostname) {
     CertVerifyResult verify_result;
     int flags = 0;
-    return Verify(cert, hostname, flags, CertificateList(), &verify_result);
+    return Verify(cert, hostname, flags, &verify_result);
   }
 
   CertVerifyProcType verify_proc_type() const { return GetParam(); }
 
-  bool SupportsAdditionalTrustAnchors() const {
-    return verify_proc_->SupportsAdditionalTrustAnchors();
-  }
-
   // Returns true if the RSA/DSA keysize will be considered weak on the current
   // platform. IsInvalidRsaDsaKeySize should be checked prior, since some very
   // weak keys may be considered invalid.
@@ -535,8 +542,7 @@
 
   CertVerifyResult verify_result;
   int flags = 0;
-  int error = Verify(cert.get(), "www.example.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(cert.get(), "www.example.com", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV);
 }
@@ -557,8 +563,7 @@
 
   CertVerifyResult verify_result;
   int flags = 0;
-  int error = Verify(cert.get(), "www.example.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(cert.get(), "www.example.com", flags, &verify_result);
   if (ScopedTestRootCanTrustTargetCert(verify_proc_type())) {
     EXPECT_THAT(error, IsOk());
     ASSERT_TRUE(verify_result.verified_cert);
@@ -588,8 +593,7 @@
 
   CertVerifyResult verify_result;
   int flags = 0;
-  int error = Verify(cert.get(), "www.example.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(cert.get(), "www.example.com", flags, &verify_result);
   if (ScopedTestRootCanTrustTargetCert(verify_proc_type())) {
     EXPECT_THAT(error, IsOk());
     ASSERT_TRUE(verify_result.verified_cert);
@@ -647,8 +651,7 @@
       ScopedTestRoot scoped_test_root({root_cert});
       CertVerifyResult verify_result;
       int flags = 0;
-      int error = Verify(cert.get(), "www.example.com", flags,
-                         CertificateList(), &verify_result);
+      int error = Verify(cert.get(), "www.example.com", flags, &verify_result);
       EXPECT_THAT(error, IsOk());
       ASSERT_TRUE(verify_result.verified_cert);
       // Verified chain should include the intermediate and the root.
@@ -660,8 +663,7 @@
       ScopedTestRoot scoped_test_root({intermediate_cert, root_cert});
       CertVerifyResult verify_result;
       int flags = 0;
-      int error = Verify(cert.get(), "www.example.com", flags,
-                         CertificateList(), &verify_result);
+      int error = Verify(cert.get(), "www.example.com", flags, &verify_result);
       EXPECT_THAT(error, IsOk());
       ASSERT_TRUE(verify_result.verified_cert);
       // Verified chain should only go to the trusted intermediate, not the
@@ -691,8 +693,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(chain.get(), "www.fake.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(chain.get(), "www.fake.com", flags, &verify_result);
 
   // This actually fails because Chrome only looks for hostnames in
   // SubjectAltNames now and no SubjectAltName is present.
@@ -717,8 +718,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(chain.get(), "www.fake.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(chain.get(), "www.fake.com", flags, &verify_result);
 
   // SubjectAltName is valid and Chrome does not use the common name.
   EXPECT_THAT(error, IsOk());
@@ -740,8 +740,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(chain.get(), "www.fake.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(chain.get(), "www.fake.com", flags, &verify_result);
 
   // SubjectAltName is invalid.
   EXPECT_THAT(error, IsError(ERR_CERT_COMMON_NAME_INVALID));
@@ -779,8 +778,8 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(cert_with_bad_target.get(), "127.0.0.1", flags,
-                     CertificateList(), &verify_result);
+  int error =
+      Verify(cert_with_bad_target.get(), "127.0.0.1", flags, &verify_result);
 
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID);
   EXPECT_THAT(error, IsError(ERR_CERT_INVALID));
@@ -818,7 +817,7 @@
   int flags = 0;
   CertVerifyResult verify_result;
   int error = Verify(cert_with_bad_intermediate.get(), "127.0.0.1", flags,
-                     CertificateList(), &verify_result, net_log);
+                     &verify_result, net_log);
 
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0u, verify_result.cert_status);
@@ -862,8 +861,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  int error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsError(ERR_CERT_DATE_INVALID));
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_DATE_INVALID);
 }
@@ -895,9 +893,8 @@
       ScopedTestRoot scoped_root(root->GetX509Certificate());
 
       CertVerifyResult verify_result;
-      int error =
-          Verify(leaf->GetX509CertificateChain().get(), "www.example.com", 0,
-                 CertificateList(), &verify_result);
+      int error = Verify(leaf->GetX509CertificateChain().get(),
+                         "www.example.com", 0, &verify_result);
 
       if (IsInvalidKeyType(ee_type) || IsInvalidKeyType(signer_type)) {
         EXPECT_NE(OK, error);
@@ -952,8 +949,8 @@
 
   CertVerifyResult verify_result;
   int flags = 0;
-  int error = Verify(cert_chain.get(), "www.example.com", flags,
-                     CertificateList(), &verify_result);
+  int error =
+      Verify(cert_chain.get(), "www.example.com", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
 
   // The extra root should be discarded.
@@ -984,15 +981,14 @@
 
   CertVerifyResult verify_result;
   int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED;
-  int error = Verify(cert_chain.get(), "mail.google.com", flags,
-                     CertificateList(), &verify_result);
+  int error =
+      Verify(cert_chain.get(), "mail.google.com", flags, &verify_result);
   EXPECT_NE(OK, error);
 
   // Now turn off revocation checking.  Certificate verification should still
   // fail.
   flags = 0;
-  error = Verify(cert_chain.get(), "mail.google.com", flags, CertificateList(),
-                 &verify_result);
+  error = Verify(cert_chain.get(), "mail.google.com", flags, &verify_result);
   EXPECT_NE(OK, error);
 }
 
@@ -1015,13 +1011,13 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(leaf_cert.get(), "test.example.com", flags,
-                     CertificateList(), &verify_result);
+  int error =
+      Verify(leaf_cert.get(), "test.example.com", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
 
-  error = Verify(leaf_cert.get(), "foo.test2.example.com", flags,
-                 CertificateList(), &verify_result);
+  error =
+      Verify(leaf_cert.get(), "foo.test2.example.com", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
 }
@@ -1042,8 +1038,8 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(leaf_cert.get(), "test.example.com", flags,
-                     CertificateList(), &verify_result);
+  int error =
+      Verify(leaf_cert.get(), "test.example.com", flags, &verify_result);
   EXPECT_THAT(error, IsError(ERR_CERT_NAME_CONSTRAINT_VIOLATION));
   EXPECT_EQ(CERT_STATUS_NAME_CONSTRAINT_VIOLATION,
             verify_result.cert_status & CERT_STATUS_NAME_CONSTRAINT_VIOLATION);
@@ -1121,8 +1117,7 @@
 
     return verify_proc->Verify(
         chain.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-        /*sct_list=*/std::string(), flags, CertificateList(), &verify_result,
-        NetLogWithSource());
+        /*sct_list=*/std::string(), flags, &verify_result, NetLogWithSource());
   }
 
  private:
@@ -1435,8 +1430,7 @@
     CertVerifyResult verify_result;
     int error = verify_proc->Verify(
         cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-        /*sct_list=*/std::string(), 0, CertificateList(), &verify_result,
-        NetLogWithSource());
+        /*sct_list=*/std::string(), 0, &verify_result, NetLogWithSource());
     EXPECT_THAT(error, IsOk());
     EXPECT_EQ(0u, verify_result.cert_status & CERT_STATUS_ALL_ERRORS);
   }
@@ -1450,8 +1444,7 @@
     CertVerifyResult verify_result;
     int error = verify_proc->Verify(
         cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-        /*sct_list=*/std::string(), 0, CertificateList(), &verify_result,
-        NetLogWithSource());
+        /*sct_list=*/std::string(), 0, &verify_result, NetLogWithSource());
     EXPECT_THAT(error, IsError(ERR_CERT_VALIDITY_TOO_LONG));
     // TODO(mattm): generate a dedicated cert or use CertBuilder so that this
     // test doesn't also hit CERT_STATUS_NON_UNIQUE_NAME.
@@ -1471,8 +1464,7 @@
     CertVerifyResult verify_result;
     int error = verify_proc->Verify(
         cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-        /*sct_list=*/std::string(), 0, CertificateList(), &verify_result,
-        NetLogWithSource());
+        /*sct_list=*/std::string(), 0, &verify_result, NetLogWithSource());
     EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
     // TODO(mattm): generate a dedicated cert or use CertBuilder so that this
     // test doesn't also hit CERT_STATUS_NON_UNIQUE_NAME.
@@ -1490,8 +1482,8 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(cert_chain.get(), "smallstrategies.com", flags,
-                     CertificateList(), &verify_result);
+  int error =
+      Verify(cert_chain.get(), "smallstrategies.com", flags, &verify_result);
   EXPECT_THAT(error, IsOk())
       << "This test relies on a real certificate that "
       << "expires on Nov 29 2024. If failing on/after "
@@ -1521,8 +1513,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(cert_chain.get(), "127.0.0.1", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(cert_chain.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
 
   EXPECT_EQ(3u, verify_result.public_key_hashes.size());
@@ -1572,9 +1563,8 @@
   // this is just matching how the test was originally written, and we'll
   // delete this sometime soon anyway so there's not much benefit to thinking
   // about it too hard.)
-  int error =
-      Verify(leaf->GetX509CertificateFullChain().get(), "www.example.com",
-             flags, CertificateList(), &verify_result);
+  int error = Verify(leaf->GetX509CertificateFullChain().get(),
+                     "www.example.com", flags, &verify_result);
 
   EXPECT_NE(error, OK);
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM);
@@ -1608,8 +1598,7 @@
   CertVerifyResult verify_result;
   EXPECT_EQ(static_cast<X509Certificate*>(nullptr),
             verify_result.verified_cert.get());
-  int error = Verify(google_full_chain.get(), "127.0.0.1", 0, CertificateList(),
-                     &verify_result);
+  int error = Verify(google_full_chain.get(), "127.0.0.1", 0, &verify_result);
   EXPECT_THAT(error, IsOk());
   ASSERT_NE(static_cast<X509Certificate*>(nullptr),
             verify_result.verified_cert.get());
@@ -1647,8 +1636,8 @@
   auto verify_proc = base::MakeRefCounted<MockCertVerifyProc>(dummy_result);
   error = verify_proc->Verify(cert.get(), kIntranetHostname,
                               /*ocsp_response=*/std::string(),
-                              /*sct_list=*/std::string(), 0, CertificateList(),
-                              &verify_result, NetLogWithSource());
+                              /*sct_list=*/std::string(), 0, &verify_result,
+                              NetLogWithSource());
   EXPECT_THAT(error, IsOk());
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME);
 
@@ -1658,8 +1647,8 @@
   verify_proc = base::MakeRefCounted<MockCertVerifyProc>(dummy_result);
   error = verify_proc->Verify(cert.get(), kIntranetHostname,
                               /*ocsp_response=*/std::string(),
-                              /*sct_list=*/std::string(), 0, CertificateList(),
-                              &verify_result, NetLogWithSource());
+                              /*sct_list=*/std::string(), 0, &verify_result,
+                              NetLogWithSource());
   EXPECT_THAT(error, IsOk());
   EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME);
 }
@@ -1715,8 +1704,7 @@
     CertVerifyResult test_result_1;
     error = verify_proc->Verify(
         cert, "www.example.com", /*ocsp_response=*/std::string(),
-        /*sct_list=*/std::string(), 0, CertificateList(), &test_result_1,
-        NetLogWithSource());
+        /*sct_list=*/std::string(), 0, &test_result_1, NetLogWithSource());
     EXPECT_THAT(error, IsError(ERR_CERT_SYMANTEC_LEGACY));
     EXPECT_TRUE(test_result_1.cert_status & CERT_STATUS_SYMANTEC_LEGACY);
 
@@ -1732,8 +1720,7 @@
     CertVerifyResult test_result_2;
     error = verify_proc->Verify(
         cert, "www.example.com", /*ocsp_response=*/std::string(),
-        /*sct_list=*/std::string(), 0, CertificateList(), &test_result_2,
-        NetLogWithSource());
+        /*sct_list=*/std::string(), 0, &test_result_2, NetLogWithSource());
     EXPECT_THAT(error, IsOk());
     EXPECT_FALSE(test_result_2.cert_status & CERT_STATUS_AUTHORITY_INVALID);
 
@@ -1742,8 +1729,8 @@
     error = verify_proc->Verify(
         cert, "www.example.com", /*ocsp_response=*/std::string(),
         /*sct_list=*/std::string(),
-        CertVerifyProc::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT, CertificateList(),
-        &test_result_3, NetLogWithSource());
+        CertVerifyProc::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT, &test_result_3,
+        NetLogWithSource());
     EXPECT_THAT(error, IsOk());
     EXPECT_FALSE(test_result_3.cert_status & CERT_STATUS_SYMANTEC_LEGACY);
   }
@@ -1766,8 +1753,8 @@
   CertVerifyResult test_result_1;
   error = verify_proc->Verify(cert.get(), "www.example.com",
                               /*ocsp_response=*/std::string(),
-                              /*sct_list=*/std::string(), 0, CertificateList(),
-                              &test_result_1, NetLogWithSource());
+                              /*sct_list=*/std::string(), 0, &test_result_1,
+                              NetLogWithSource());
   EXPECT_THAT(error, IsError(ERR_CERT_SYMANTEC_LEGACY));
   EXPECT_TRUE(test_result_1.cert_status & CERT_STATUS_SYMANTEC_LEGACY);
 
@@ -1782,8 +1769,8 @@
   CertVerifyResult test_result_2;
   error = verify_proc->Verify(cert.get(), "www.example.com",
                               /*ocsp_response=*/std::string(),
-                              /*sct_list=*/std::string(), 0, CertificateList(),
-                              &test_result_2, NetLogWithSource());
+                              /*sct_list=*/std::string(), 0, &test_result_2,
+                              NetLogWithSource());
   EXPECT_THAT(error, IsOk());
   EXPECT_FALSE(test_result_2.cert_status & CERT_STATUS_AUTHORITY_INVALID);
 
@@ -1792,8 +1779,8 @@
   error = verify_proc->Verify(
       cert.get(), "www.example.com", /*ocsp_response=*/std::string(),
       /*sct_list=*/std::string(),
-      CertVerifyProc::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT, CertificateList(),
-      &test_result_3, NetLogWithSource());
+      CertVerifyProc::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT, &test_result_3,
+      NetLogWithSource());
   EXPECT_THAT(error, IsOk());
   EXPECT_FALSE(test_result_3.cert_status & CERT_STATUS_SYMANTEC_LEGACY);
 }
@@ -1824,8 +1811,7 @@
 
   CertVerifyResult verify_result;
   EXPECT_FALSE(verify_result.verified_cert);
-  int error = Verify(google_full_chain.get(), "127.0.0.1", 0, CertificateList(),
-                     &verify_result);
+  int error = Verify(google_full_chain.get(), "127.0.0.1", 0, &verify_result);
   EXPECT_THAT(error, IsOk());
   ASSERT_TRUE(verify_result.verified_cert);
 
@@ -1875,8 +1861,7 @@
 
   CertVerifyResult verify_result;
   EXPECT_FALSE(verify_result.verified_cert);
-  int error = Verify(google_full_chain.get(), "127.0.0.1", 0, CertificateList(),
-                     &verify_result);
+  int error = Verify(google_full_chain.get(), "127.0.0.1", 0, &verify_result);
   EXPECT_THAT(error, IsOk());
   ASSERT_TRUE(verify_result.verified_cert);
 
@@ -1894,7 +1879,7 @@
 }
 
 TEST_P(CertVerifyProcInternalTest, AdditionalTrustAnchors) {
-  if (!SupportsAdditionalTrustAnchors()) {
+  if (!VerifyProcTypeIsBuiltin()) {
     LOG(INFO) << "Skipping this test in this platform.";
     return;
   }
@@ -1915,8 +1900,7 @@
   // list.
   int flags = 0;
   CertVerifyResult verify_result;
-  int error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  int error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
   EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status);
   EXPECT_FALSE(verify_result.is_issued_by_additional_trust_anchor);
@@ -1924,20 +1908,81 @@
   // Now add the |ca_cert| to the |trust_anchors|, and verification should pass.
   CertificateList trust_anchors;
   trust_anchors.push_back(ca_cert);
-  error = Verify(cert.get(), "127.0.0.1", flags, trust_anchors, &verify_result);
+  SetUpWithAdditionalCerts(trust_anchors, {});
+  error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
   EXPECT_TRUE(verify_result.is_issued_by_additional_trust_anchor);
 
   // Clearing the |trust_anchors| makes verification fail again (the cache
   // should be skipped).
-  error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  SetUpWithAdditionalCerts({}, {});
+  error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
   EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status);
   EXPECT_FALSE(verify_result.is_issued_by_additional_trust_anchor);
 }
 
+TEST_P(CertVerifyProcInternalTest, AdditionalIntermediates) {
+  if (!VerifyProcTypeIsBuiltin()) {
+    LOG(INFO) << "Skipping this test in this platform.";
+    return;
+  }
+
+  auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
+  scoped_refptr<X509Certificate> leaf_cert = leaf->GetX509Certificate();
+  scoped_refptr<X509Certificate> intermediate_cert =
+      intermediate->GetX509Certificate();
+  scoped_refptr<X509Certificate> root_cert = root->GetX509Certificate();
+  constexpr char kHostname[] = "www.example.com";
+
+  ScopedTestRoot trust_root(root_cert);
+  // Leaf should not verify without intermediate found
+  EXPECT_THAT(Verify(leaf_cert.get(), kHostname),
+              IsError(ERR_CERT_AUTHORITY_INVALID));
+
+  // Leaf should verify after intermediate is passed in to CertVerifyProc. Chain
+  // should be {leaf, intermediate, root}.
+  SetUpWithAdditionalCerts({}, {intermediate->GetX509Certificate()});
+  CertVerifyResult verify_result;
+  int error = Verify(leaf_cert.get(), kHostname, /*flags=*/0, &verify_result);
+  EXPECT_THAT(error, IsOk());
+  ASSERT_TRUE(verify_result.verified_cert);
+  EXPECT_EQ(verify_result.verified_cert->intermediate_buffers().size(), 2U);
+  EXPECT_TRUE(x509_util::CryptoBufferEqual(
+      verify_result.verified_cert->intermediate_buffers().back().get(),
+      root_cert->cert_buffer()));
+  EXPECT_TRUE(x509_util::CryptoBufferEqual(
+      verify_result.verified_cert->intermediate_buffers().front().get(),
+      intermediate_cert->cert_buffer()));
+}
+
+TEST_P(CertVerifyProcInternalTest, AdditionalTrustAnchorDuplicateIntermediate) {
+  if (!VerifyProcTypeIsBuiltin()) {
+    LOG(INFO) << "Skipping this test in this platform.";
+    return;
+  }
+
+  auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
+  constexpr char kHostname[] = "www.example.com";
+
+  // Leaf should not verify without anything set up.
+  EXPECT_THAT(Verify(leaf->GetX509Certificate().get(), kHostname),
+              IsError(ERR_CERT_AUTHORITY_INVALID));
+
+  // Leaf should verify with intermediate and root added.
+  CertificateList trust_anchors, intermediates;
+  intermediates.push_back(intermediate->GetX509Certificate());
+  trust_anchors.push_back(root->GetX509Certificate());
+  SetUpWithAdditionalCerts(trust_anchors, intermediates);
+  EXPECT_THAT(Verify(leaf->GetX509Certificate().get(), kHostname), IsOk());
+
+  // Leaf should still verify after root is also in intermediates list.
+  intermediates.push_back(root->GetX509Certificate());
+  SetUpWithAdditionalCerts(trust_anchors, intermediates);
+  EXPECT_THAT(Verify(leaf->GetX509Certificate().get(), kHostname), IsOk());
+}
+
 // Tests that certificates issued by user-supplied roots are not flagged as
 // issued by a known root. This should pass whether or not the platform supports
 // detecting known roots.
@@ -1952,8 +1997,7 @@
   // Verification should pass.
   int flags = 0;
   CertVerifyResult verify_result;
-  int error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  int error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
   // But should not be marked as a known root.
@@ -1981,8 +2025,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  int error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
 
@@ -1996,8 +2039,7 @@
   ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
 
   SetUpCertVerifyProc(crl_set);
-  error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
 
   // Second, test revocation by serial number of a cert directly under the
@@ -2009,8 +2051,7 @@
   ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
 
   SetUpCertVerifyProc(crl_set);
-  error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
 }
 
@@ -2034,8 +2075,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error =
-      Verify(leaf.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  int error = Verify(leaf.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
 
   // Test revocation by serial number of a certificate not under the root.
@@ -2047,8 +2087,7 @@
   ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
 
   SetUpCertVerifyProc(crl_set);
-  error =
-      Verify(leaf.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  error = Verify(leaf.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
 }
 
@@ -2072,8 +2111,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error =
-      Verify(leaf.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  int error = Verify(leaf.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
 
   // Test revocation of the root itself.
@@ -2085,8 +2123,7 @@
   ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
 
   SetUpCertVerifyProc(crl_set);
-  error =
-      Verify(leaf.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  error = Verify(leaf.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
 
   EXPECT_EQ(3u, verify_result.public_key_hashes.size());
@@ -2117,8 +2154,7 @@
 
   // Confirm that verifying the certificate chain with an empty CRLSet succeeds.
   SetUpCertVerifyProc(CRLSet::EmptyCRLSetForTesting());
-  int error =
-      Verify(leaf.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  int error = Verify(leaf.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
 
   std::string crl_set_bytes;
@@ -2131,8 +2167,7 @@
   ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
 
   SetUpCertVerifyProc(crl_set);
-  error =
-      Verify(leaf.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  error = Verify(leaf.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
 
   // Revoke the root by subject. Verification should now fail.
@@ -2142,8 +2177,7 @@
   ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
 
   SetUpCertVerifyProc(crl_set);
-  error =
-      Verify(leaf.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  error = Verify(leaf.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
 
   // Revoke the leaf by subject, but only if the SPKI doesn't match the given
@@ -2154,8 +2188,7 @@
   ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
 
   SetUpCertVerifyProc(crl_set);
-  error =
-      Verify(leaf.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  error = Verify(leaf.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
 }
 
@@ -2178,8 +2211,7 @@
   SetUpCertVerifyProc(crl_set);
   int flags = 0;
   CertVerifyResult verify_result;
-  int error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  int error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
 
@@ -2192,8 +2224,7 @@
   ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
 
   SetUpCertVerifyProc(crl_set);
-  error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   if (SupportsCRLSet()) {
     EXPECT_THAT(error, IsError(ERR_CERT_KNOWN_INTERCEPTION_BLOCKED));
     EXPECT_TRUE(verify_result.cert_status &
@@ -2223,8 +2254,7 @@
   SetUpCertVerifyProc(crl_set);
   int flags = 0;
   CertVerifyResult verify_result;
-  int error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  int error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
 
@@ -2237,8 +2267,7 @@
   ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
 
   SetUpCertVerifyProc(crl_set);
-  error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   if (SupportsCRLSet()) {
     EXPECT_THAT(error, IsError(ERR_CERT_KNOWN_INTERCEPTION_BLOCKED));
     EXPECT_TRUE(verify_result.cert_status &
@@ -2255,8 +2284,7 @@
   ASSERT_TRUE(second_cert);
 
   SetUpCertVerifyProc(crl_set);
-  error = Verify(second_cert.get(), "127.0.0.1", flags, CertificateList(),
-                 &verify_result);
+  error = Verify(second_cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
 }
@@ -2279,8 +2307,7 @@
   SetUpCertVerifyProc(crl_set);
   int flags = 0;
   CertVerifyResult verify_result;
-  int error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  int error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
 
@@ -2293,8 +2320,7 @@
   ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
 
   SetUpCertVerifyProc(crl_set);
-  error =
-      Verify(cert.get(), "127.0.0.1", flags, CertificateList(), &verify_result);
+  error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_TRUE(verify_result.cert_status &
               CERT_STATUS_KNOWN_INTERCEPTION_DETECTED);
@@ -2385,8 +2411,7 @@
     SetUpCertVerifyProc(crl_set);
     int flags = 0;
     CertVerifyResult verify_result;
-    int error = Verify(cert.get(), "127.0.0.1", flags, CertificateList(),
-                       &verify_result);
+    int error = Verify(cert.get(), "127.0.0.1", flags, &verify_result);
 
     if (!testcase.expect_valid) {
       EXPECT_NE(OK, error);
@@ -2432,8 +2457,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(chain.get(), "www.example.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(chain.get(), "www.example.com", flags, &verify_result);
   // Current time is before certificate's notBefore. Verification should fail.
   EXPECT_THAT(error, IsError(ERR_CERT_DATE_INVALID));
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_DATE_INVALID);
@@ -2452,8 +2476,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(chain.get(), "www.example.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(chain.get(), "www.example.com", flags, &verify_result);
   // Current time is before certificate's notBefore. Verification should fail.
   EXPECT_THAT(error, IsError(ERR_CERT_DATE_INVALID));
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_DATE_INVALID);
@@ -2472,8 +2495,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(chain.get(), "www.example.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(chain.get(), "www.example.com", flags, &verify_result);
   // Current time is before certificate's notBefore. Verification should fail.
   EXPECT_THAT(error, IsError(ERR_CERT_DATE_INVALID));
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_DATE_INVALID);
@@ -2492,8 +2514,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(chain.get(), "www.example.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(chain.get(), "www.example.com", flags, &verify_result);
   // Current time is between notBefore and notAfter. Verification should
   // succeed.
   EXPECT_THAT(error, IsOk());
@@ -2512,8 +2533,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(chain.get(), "www.example.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(chain.get(), "www.example.com", flags, &verify_result);
   // Current time is between notBefore and notAfter. Verification should
   // succeed.
   EXPECT_THAT(error, IsOk());
@@ -2532,8 +2552,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(chain.get(), "www.example.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(chain.get(), "www.example.com", flags, &verify_result);
   // Current time is after certificate's notAfter. Verification should fail.
   EXPECT_THAT(error, IsError(ERR_CERT_DATE_INVALID));
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_DATE_INVALID);
@@ -2560,8 +2579,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(cert.get(), "www.example.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(cert.get(), "www.example.com", flags, &verify_result);
 
   // The intermediate was signed by a different root with a different key but
   // with the same name as the trusted one, and the intermediate has no
@@ -2600,8 +2618,7 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(cert.get(), "www.example.com", flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(cert.get(), "www.example.com", flags, &verify_result);
 
   // The leaf was signed by a different intermediate with a different key but
   // with the same name as the one in the chain, and the leaf has no
@@ -2668,7 +2685,7 @@
   int flags = 0;
   CertVerifyResult verify_result;
   int error = Verify(leaf->GetX509CertificateChain().get(), "www.example.com",
-                     flags, CertificateList(), &verify_result);
+                     flags, &verify_result);
 
   switch (verify_proc_type()) {
     case CERT_VERIFY_PROC_IOS:
@@ -2701,7 +2718,7 @@
   int flags = 0;
   CertVerifyResult verify_result;
   int error = Verify(leaf->GetX509CertificateChain().get(), "www.example.com",
-                     flags, CertificateList(), &verify_result);
+                     flags, &verify_result);
 
   EXPECT_THAT(error, IsOk());
   ExpectNormalizationHistogram(error);
@@ -2724,7 +2741,7 @@
   int flags = 0;
   CertVerifyResult verify_result;
   int error = Verify(leaf->GetX509CertificateChain().get(), "www.example.com",
-                     flags, CertificateList(), &verify_result);
+                     flags, &verify_result);
 
   EXPECT_THAT(error, IsOk());
   ExpectByteEqualHistogram();
@@ -2793,7 +2810,9 @@
 
   void SetUpCertVerifyProc(scoped_refptr<CRLSet> crl_set) override {
     EXPECT_TRUE(cert_net_fetcher_);
-    SetUpWithCertNetFetcher(cert_net_fetcher_, std::move(crl_set));
+    SetUpWithCertNetFetcher(cert_net_fetcher_, std::move(crl_set),
+                            /*additional_trust_anchors=*/{},
+                            /*additional_untrusted_authorities=*/{});
   }
 
   void TearDown() override {
@@ -3003,8 +3022,7 @@
 
   // Verifying the chain should fail as the intermediate is missing, and
   // cannot be fetched via AIA.
-  error =
-      Verify(leaf.get(), kHostname, flags, CertificateList(), &verify_result);
+  error = Verify(leaf.get(), kHostname, flags, &verify_result);
   EXPECT_NE(OK, error);
 
   EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
@@ -3049,9 +3067,9 @@
     // If VERIFY_DISABLE_NETWORK_FETCHES is specified, AIA should not be
     // attempted and verifying the chain should fail since the intermediate
     // can't be found.
-    int error = Verify(leaf.get(), kHostname,
-                       CertVerifyProc::VERIFY_DISABLE_NETWORK_FETCHES,
-                       CertificateList(), &verify_result);
+    int error =
+        Verify(leaf.get(), kHostname,
+               CertVerifyProc::VERIFY_DISABLE_NETWORK_FETCHES, &verify_result);
     EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
     EXPECT_EQ(0u, verify_result.verified_cert->intermediate_buffers().size());
   }
@@ -3060,8 +3078,7 @@
     CertVerifyResult verify_result;
     // Verifying the chain should succeed as the missing intermediate can be
     // fetched via AIA.
-    int error = Verify(leaf.get(), kHostname, /*flags=*/0, CertificateList(),
-                       &verify_result);
+    int error = Verify(leaf.get(), kHostname, /*flags=*/0, &verify_result);
     EXPECT_THAT(error, IsOk());
   }
 }
@@ -3110,8 +3127,7 @@
 
   // Verifying the chain should succeed as the missing intermediate can be
   // fetched via AIA.
-  error =
-      Verify(leaf.get(), kHostname, flags, CertificateList(), &verify_result);
+  error = Verify(leaf.get(), kHostname, flags, &verify_result);
 
   if (verify_proc_type() == CERT_VERIFY_PROC_ANDROID) {
     // Android doesn't support PEM - https://crbug.com/725180
@@ -3164,8 +3180,7 @@
 
   // Verifying the chain should succeed as the missing intermediate can be
   // fetched via AIA.
-  error =
-      Verify(leaf.get(), kHostname, flags, CertificateList(), &verify_result);
+  error = Verify(leaf.get(), kHostname, flags, &verify_result);
 
   if (verify_proc_type() == CERT_VERIFY_PROC_ANDROID) {
     // Android doesn't support PEM - https://crbug.com/725180
@@ -3224,8 +3239,7 @@
 
   const int flags = 0;
   CertVerifyResult verify_result;
-  int error = Verify(chain_sha1.get(), kHostname, flags, CertificateList(),
-                     &verify_result);
+  int error = Verify(chain_sha1.get(), kHostname, flags, &verify_result);
 
   if (VerifyProcTypeIsBuiltin()) {
     // Should have built a chain through the SHA256 intermediate. This was only
@@ -3277,8 +3291,7 @@
   // Verify with hard-fail revocation checking for local anchors.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   EXPECT_THAT(error, IsError(ERR_CERT_NO_REVOCATION_MECHANISM));
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
@@ -3306,8 +3319,7 @@
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS |
                     CertVerifyProc::VERIFY_DISABLE_NETWORK_FETCHES;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should succeed, VERIFY_DISABLE_NETWORK_FETCHES takes priority.
   EXPECT_THAT(error, IsOk());
@@ -3342,8 +3354,7 @@
   // Verify with hard-fail revocation checking for local anchors.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should pass, leaf and intermediate were covered by CRLs and were not
   // revoked.
@@ -3382,8 +3393,7 @@
   // Verify with hard-fail revocation checking for local anchors.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should pass, leaf and intermediate were covered by CRLs and were not
   // revoked.
@@ -3417,8 +3427,7 @@
   // Verify with hard-fail revocation checking for local anchors.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should fail, leaf is revoked.
   EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
@@ -3451,8 +3460,7 @@
   // Verify with hard-fail revocation checking for local anchors.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should fail, intermediate is revoked.
   EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
@@ -3488,8 +3496,7 @@
   // Verify with hard-fail revocation checking for local anchors.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should fail since no revocation information was available for the leaf.
   EXPECT_THAT(error, IsError(ERR_CERT_UNABLE_TO_CHECK_REVOCATION));
@@ -3525,8 +3532,7 @@
   // Verify with hard-fail revocation checking for local anchors.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should fail since no revocation information was available for the
   // intermediate.
@@ -3553,8 +3559,7 @@
   // Verify with soft-fail revocation checking.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   EXPECT_THAT(error, IsOk());
   EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_NO_REVOCATION_MECHANISM);
@@ -3591,8 +3596,7 @@
   // Verify with soft-fail revocation checking.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   EXPECT_THAT(error, IsOk());
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
@@ -3629,8 +3633,7 @@
   // Verify with soft-fail revocation checking.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   EXPECT_THAT(error, IsOk());
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
@@ -3662,8 +3665,7 @@
   // Verify with soft-fail revocation checking.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should fail, leaf is revoked.
   EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
@@ -3698,8 +3700,7 @@
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED |
                     CertVerifyProc::VERIFY_DISABLE_NETWORK_FETCHES;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should succeed, VERIFY_DISABLE_NETWORK_FETCHES takes priority.
   EXPECT_THAT(error, IsOk());
@@ -3732,8 +3733,7 @@
   // Verify with soft-fail revocation checking.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should fail, intermediate is revoked.
   EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
@@ -3768,8 +3768,7 @@
   // Verify with soft-fail revocation checking.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should fail, leaf is revoked.
   EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
@@ -3810,8 +3809,7 @@
   // Verify with soft-fail revocation checking.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Verification should succeed: MD5 signature algorithm is not supported
   // and soft-fail checking will ignore the inability to get revocation
@@ -3849,8 +3847,7 @@
   // Verify with soft-fail revocation checking.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should succeed due to soft-fail revocation checking.
   EXPECT_THAT(error, IsOk());
@@ -3886,8 +3883,7 @@
   // Verify with soft-fail revocation checking.
   const int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED;
   CertVerifyResult verify_result;
-  int error =
-      Verify(chain.get(), kHostname, flags, CertificateList(), &verify_result);
+  int error = Verify(chain.get(), kHostname, flags, &verify_result);
 
   // Should succeed due to soft-fail revocation checking.
   EXPECT_THAT(error, IsOk());
@@ -3930,7 +3926,7 @@
   CertVerifyResult verify_result;
   int flags = 0;
   int error = Verify(chain.get(), ocsp_test_server.host_port_pair().host(),
-                     flags, CertificateList(), &verify_result);
+                     flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV);
   EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
@@ -3972,7 +3968,7 @@
   CertVerifyResult verify_result;
   int flags = 0;
   int error = Verify(chain.get(), ocsp_test_server.host_port_pair().host(),
-                     flags, CertificateList(), &verify_result);
+                     flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV);
   EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
@@ -4014,7 +4010,7 @@
   CertVerifyResult verify_result;
   int flags = 0;
   int error = Verify(chain.get(), ocsp_test_server.host_port_pair().host(),
-                     flags, CertificateList(), &verify_result);
+                     flags, &verify_result);
   EXPECT_THAT(error, IsOk());
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV);
   EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
@@ -4037,7 +4033,7 @@
     int flags = 0;
     return CertVerifyProcInternalTest::Verify(
         chain_.front()->GetX509CertificateChain().get(), "www.example.com",
-        flags, CertificateList(), &verify_result);
+        flags, &verify_result);
   }
 
   int Verify() {
@@ -4998,7 +4994,7 @@
     int flags = 0;
     return CertVerifyProcInternalTest::Verify(
         chain_.front()->GetX509Certificate().get(), "www.example.com", flags,
-        CertificateList(), &verify_result);
+        &verify_result);
   }
 
   int Verify() {
@@ -5302,9 +5298,9 @@
     ScopedTestRoot test_root(cert_->GetX509Certificate(), trust);
     CertVerifyResult verify_result;
     int flags = 0;
-    return CertVerifyProcInternalTest::Verify(
-        cert_->GetX509Certificate().get(), "www.example.com", flags,
-        CertificateList(), &verify_result);
+    return CertVerifyProcInternalTest::Verify(cert_->GetX509Certificate().get(),
+                                              "www.example.com", flags,
+                                              &verify_result);
   }
 
   int Verify() {
@@ -5593,8 +5589,7 @@
   CertVerifyResult verify_result;
   int error = verify_proc->Verify(
       cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-      /*sct_list=*/std::string(), flags, CertificateList(), &verify_result,
-      NetLogWithSource());
+      /*sct_list=*/std::string(), flags, &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM));
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM);
 
@@ -5603,8 +5598,7 @@
   verify_result.Reset();
   error = verify_proc->Verify(
       cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-      /*sct_list=*/std::string(), flags, CertificateList(), &verify_result,
-      NetLogWithSource());
+      /*sct_list=*/std::string(), flags, &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM));
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM);
 }
@@ -5624,8 +5618,7 @@
   CertVerifyResult verify_result;
   int error = verify_proc->Verify(
       cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-      /*sct_list=*/std::string(), flags, CertificateList(), &verify_result,
-      NetLogWithSource());
+      /*sct_list=*/std::string(), flags, &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM));
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT);
 
@@ -5634,8 +5627,7 @@
   verify_result.Reset();
   error = verify_proc->Verify(
       cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-      /*sct_list=*/std::string(), flags, CertificateList(), &verify_result,
-      NetLogWithSource());
+      /*sct_list=*/std::string(), flags, &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsOk());
   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT);
 }
@@ -5718,8 +5710,8 @@
   auto proc = base::MakeRefCounted<MockCertVerifyProc>(CertVerifyResult());
   int error = proc->Verify(ee_chain.get(), "127.0.0.1",
                            /*ocsp_response=*/std::string(),
-                           /*sct_list=*/std::string(), flags, CertificateList(),
-                           &verify_result, NetLogWithSource());
+                           /*sct_list=*/std::string(), flags, &verify_result,
+                           NetLogWithSource());
   EXPECT_EQ(!!(data.expected_algorithms & EXPECT_SHA1), verify_result.has_sha1);
   EXPECT_EQ(!!(data.expected_algorithms & EXPECT_STATUS_INVALID),
             !!(verify_result.cert_status & CERT_STATUS_INVALID));
@@ -5844,8 +5836,7 @@
     CertVerifyResult verify_result;
     int error = verify_proc->Verify(
         cert.get(), hostname, /*ocsp_response=*/std::string(),
-        /*sct_list=*/std::string(), 0, CertificateList(), &verify_result,
-        NetLogWithSource());
+        /*sct_list=*/std::string(), 0, &verify_result, NetLogWithSource());
     if (valid) {
       EXPECT_THAT(error, IsOk());
       EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_COMMON_NAME_INVALID);
@@ -5956,8 +5947,7 @@
   CertVerifyResult verify_result;
   int error = verify_proc->Verify(
       cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-      /*sct_list=*/std::string(), flags, CertificateList(), &verify_result,
-      NetLogWithSource());
+      /*sct_list=*/std::string(), flags, &verify_result, NetLogWithSource());
   EXPECT_EQ(OK, error);
   histograms.ExpectUniqueSample(kTrustAnchorVerifyHistogram,
                                 kGTSRootR4HistogramID, 1);
@@ -6004,8 +5994,7 @@
   CertVerifyResult verify_result;
   int error = verify_proc->Verify(
       cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-      /*sct_list=*/std::string(), flags, CertificateList(), &verify_result,
-      NetLogWithSource());
+      /*sct_list=*/std::string(), flags, &verify_result, NetLogWithSource());
   EXPECT_EQ(OK, error);
 
   // Only GTS Root R3 should be recorded.
@@ -6042,11 +6031,10 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error =
-      verify_proc->Verify(leaf->GetX509Certificate().get(), "www.example.com",
-                          /*ocsp_response=*/std::string(),
-                          /*sct_list=*/std::string(), flags, CertificateList(),
-                          &verify_result, NetLogWithSource());
+  int error = verify_proc->Verify(
+      leaf->GetX509Certificate().get(), "www.example.com",
+      /*ocsp_response=*/std::string(),
+      /*sct_list=*/std::string(), flags, &verify_result, NetLogWithSource());
   EXPECT_EQ(OK, error);
   const base::HistogramBase::Sample kUnknownRootHistogramID = 0;
   histograms.ExpectUniqueSample(kTrustAnchorVerifyHistogram,
@@ -6073,11 +6061,10 @@
 
   int flags = 0;
   CertVerifyResult verify_result;
-  int error =
-      verify_proc->Verify(cert.get(), "127.0.0.1",
-                          /*ocsp_response=*/"invalid OCSP data",
-                          /*sct_list=*/std::string(), flags, CertificateList(),
-                          &verify_result, NetLogWithSource());
+  int error = verify_proc->Verify(cert.get(), "127.0.0.1",
+                                  /*ocsp_response=*/"invalid OCSP data",
+                                  /*sct_list=*/std::string(), flags,
+                                  &verify_result, NetLogWithSource());
   EXPECT_EQ(OK, error);
 
   EXPECT_EQ(bssl::OCSPVerifyResult::PROVIDED,
@@ -6107,8 +6094,7 @@
   CertVerifyResult verify_result;
   int error = verify_proc->Verify(
       cert.get(), "127.0.0.1", /*ocsp_response=*/"invalid OCSP data",
-      /*sct_list=*/std::string(), flags, CertificateList(), &verify_result,
-      NetLogWithSource());
+      /*sct_list=*/std::string(), flags, &verify_result, NetLogWithSource());
   EXPECT_EQ(OK, error);
 
   EXPECT_EQ(bssl::OCSPVerifyResult::PARSE_RESPONSE_ERROR,
diff --git a/net/cert/internal/system_trust_store.cc b/net/cert/internal/system_trust_store.cc
index d1410747..b912ddf 100644
--- a/net/cert/internal/system_trust_store.cc
+++ b/net/cert/internal/system_trust_store.cc
@@ -63,7 +63,7 @@
   }
 
 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
-  int64_t chrome_root_store_version() override { return 0; }
+  int64_t chrome_root_store_version() const override { return 0; }
 #endif
 
  private:
@@ -97,7 +97,7 @@
     return trust_store_chrome_->Contains(trust_anchor);
   }
 
-  int64_t chrome_root_store_version() override {
+  int64_t chrome_root_store_version() const override {
     return trust_store_chrome_->version();
   }
 
diff --git a/net/cert/internal/system_trust_store.h b/net/cert/internal/system_trust_store.h
index aa7b4a3..75722b6 100644
--- a/net/cert/internal/system_trust_store.h
+++ b/net/cert/internal/system_trust_store.h
@@ -41,7 +41,7 @@
 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
   // Returns the current version of the Chrome Root Store being used. If
   // Chrome Root Store is not in use, returns 0.
-  virtual int64_t chrome_root_store_version() = 0;
+  virtual int64_t chrome_root_store_version() const = 0;
 #endif
 };
 
diff --git a/net/cert/multi_threaded_cert_verifier.cc b/net/cert/multi_threaded_cert_verifier.cc
index 056fc35c..77bbe3f 100644
--- a/net/cert/multi_threaded_cert_verifier.cc
+++ b/net/cert/multi_threaded_cert_verifier.cc
@@ -11,22 +11,16 @@
 #include "base/memory/weak_ptr.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/thread_restrictions.h"
-#include "crypto/crypto_buildflags.h"
 #include "net/base/net_errors.h"
 #include "net/base/trace_constants.h"
 #include "net/base/tracing.h"
 #include "net/cert/cert_verify_proc.h"
 #include "net/cert/cert_verify_result.h"
-#include "net/cert/crl_set.h"
 #include "net/cert/x509_certificate.h"
 #include "net/log/net_log_event_type.h"
 #include "net/log/net_log_source_type.h"
 #include "net/log/net_log_with_source.h"
 
-#if BUILDFLAG(USE_NSS_CERTS)
-#include "net/cert/x509_util_nss.h"
-#endif
-
 namespace net {
 
 // Allows DoVerifyOnWorkerThread to wait on a base::WaitableEvent.
@@ -71,16 +65,15 @@
     const std::string& ocsp_response,
     const std::string& sct_list,
     int flags,
-    const CertificateList& additional_trust_anchors,
     const NetLogWithSource& net_log) {
   TRACE_EVENT0(NetTracingCategory(), "DoVerifyOnWorkerThread");
   auto verify_result = std::make_unique<ResultHelper>();
   verify_result->net_log = net_log;
   MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives
       allow_base_sync_primitives;
-  verify_result->error = verify_proc->Verify(
-      cert.get(), hostname, ocsp_response, sct_list, flags,
-      additional_trust_anchors, &verify_result->result, net_log);
+  verify_result->error =
+      verify_proc->Verify(cert.get(), hostname, ocsp_response, sct_list, flags,
+                          &verify_result->result, net_log);
   return verify_result;
 }
 
@@ -152,8 +145,7 @@
       {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
       base::BindOnce(&DoVerifyOnWorkerThread, verify_proc, params.certificate(),
                      params.hostname(), params.ocsp_response(),
-                     params.sct_list(), flags, config.additional_trust_anchors,
-                     net_log),
+                     params.sct_list(), flags, net_log),
       base::BindOnce(&MultiThreadedCertVerifier::InternalRequest::OnJobComplete,
                      weak_factory_.GetWeakPtr()));
 }
@@ -232,48 +224,17 @@
 
 void MultiThreadedCertVerifier::UpdateVerifyProcData(
     scoped_refptr<CertNetFetcher> cert_net_fetcher,
-    const net::CertVerifyProcFactory::ImplParams& impl_params) {
+    const net::CertVerifyProc::ImplParams& impl_params,
+    const net::CertVerifyProc::InstanceParams& instance_params) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   verify_proc_ = verify_proc_factory_->CreateCertVerifyProc(
-      std::move(cert_net_fetcher), impl_params);
+      std::move(cert_net_fetcher), impl_params, instance_params);
   CHECK(verify_proc_);
   NotifyCertVerifierChanged();
 }
 
 void MultiThreadedCertVerifier::SetConfig(const CertVerifier::Config& config) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  LOG_IF(DFATAL, verify_proc_ &&
-                     !verify_proc_->SupportsAdditionalTrustAnchors() &&
-                     !config.additional_trust_anchors.empty())
-      << "Attempted to set a CertVerifier::Config with additional trust "
-         "anchors, but |verify_proc_| does not support additional trust "
-         "anchors.";
-
-// TODO(https://crbug.com/978854): Pass these into the actual CertVerifyProc
-// rather than relying on global side-effects.
-#if !BUILDFLAG(USE_NSS_CERTS)
-  // Not yet implemented.
-  DCHECK(config.additional_untrusted_authorities.empty());
-#else
-  // Construct a temporary list and then swap that into the member variable, to
-  // be polite to any verifications that might be in progress in a background
-  // thread. This ensures that, at least for certs that are present in both the
-  // old and new config, there will not be a time when the refcount drops to
-  // zero. For the case where a cert was in the old config and is not in the
-  // new config, it might be removed while a verification is still going on
-  // that might be able to use it. Oh well. Ideally the list should be passed
-  // into CertVerifyProc as noted by the TODO(https://crbug.com/978854), since
-  // the workers could then keep a reference to the appropriate certs as long
-  // as they need.
-  net::ScopedCERTCertificateList temp_certs;
-  for (const auto& cert : config.additional_untrusted_authorities) {
-    ScopedCERTCertificate nss_cert =
-        x509_util::CreateCERTCertificateFromX509Certificate(cert.get());
-    if (nss_cert)
-      temp_certs.push_back(std::move(nss_cert));
-  }
-  temp_certs_ = std::move(temp_certs);
-#endif
 
   config_ = config;
 }
diff --git a/net/cert/multi_threaded_cert_verifier.h b/net/cert/multi_threaded_cert_verifier.h
index 368368c..33efec6 100644
--- a/net/cert/multi_threaded_cert_verifier.h
+++ b/net/cert/multi_threaded_cert_verifier.h
@@ -15,14 +15,9 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/observer_list.h"
 #include "base/threading/thread_checker.h"
-#include "crypto/crypto_buildflags.h"
 #include "net/base/net_export.h"
 #include "net/cert/cert_verifier.h"
 
-#if BUILDFLAG(USE_NSS_CERTS)
-#include "net/cert/scoped_nss_types.h"
-#endif
-
 namespace net {
 
 class CertVerifyProc;
@@ -57,7 +52,8 @@
   void RemoveObserver(Observer* observer) override;
   void UpdateVerifyProcData(
       scoped_refptr<CertNetFetcher> cert_net_fetcher,
-      const net::CertVerifyProcFactory::ImplParams& impl_params) override;
+      const net::CertVerifyProc::ImplParams& impl_params,
+      const net::CertVerifyProc::InstanceParams& instance_params) override;
 
  private:
   class InternalRequest;
@@ -76,14 +72,6 @@
   // don't call them later, as required by the CertVerifier contract.
   base::LinkedList<InternalRequest> request_list_;
 
-#if BUILDFLAG(USE_NSS_CERTS)
-  // Holds NSS temporary certificates that will be exposed as untrusted
-  // authorities by SystemCertStoreNSS.
-  // TODO(https://crbug.com/978854): Pass these into the actual CertVerifyProc
-  // rather than relying on global side-effects.
-  net::ScopedCERTCertificateList temp_certs_;
-#endif
-
   THREAD_CHECKER(thread_checker_);
 };
 
diff --git a/net/cert/multi_threaded_cert_verifier_unittest.cc b/net/cert/multi_threaded_cert_verifier_unittest.cc
index 05fcc9f..7423c7a 100644
--- a/net/cert/multi_threaded_cert_verifier_unittest.cc
+++ b/net/cert/multi_threaded_cert_verifier_unittest.cc
@@ -45,13 +45,12 @@
 class MockCertVerifyProc : public CertVerifyProc {
  public:
   MockCertVerifyProc() : CertVerifyProc(CRLSet::BuiltinCRLSet()) {}
-  MOCK_METHOD8(VerifyInternal,
+  MOCK_METHOD7(VerifyInternal,
                int(X509Certificate*,
                    const std::string&,
                    const std::string&,
                    const std::string&,
                    int,
-                   const CertificateList&,
                    CertVerifyResult*,
                    const NetLogWithSource&));
   MOCK_CONST_METHOD0(SupportsAdditionalTrustAnchors, bool());
@@ -62,7 +61,7 @@
 
 ACTION(SetCertVerifyResult) {
   X509Certificate* cert = arg0;
-  CertVerifyResult* result = arg6;
+  CertVerifyResult* result = arg5;
   result->Reset();
   result->verified_cert = cert;
   result->cert_status = CERT_STATUS_COMMON_NAME_INVALID;
@@ -70,7 +69,7 @@
 
 ACTION(SetCertVerifyRevokedResult) {
   X509Certificate* cert = arg0;
-  CertVerifyResult* result = arg6;
+  CertVerifyResult* result = arg5;
   result->Reset();
   result->verified_cert = cert;
   result->cert_status = CERT_STATUS_REVOKED;
@@ -83,7 +82,8 @@
 
   scoped_refptr<net::CertVerifyProc> CreateCertVerifyProc(
       scoped_refptr<CertNetFetcher> cert_net_fetcher,
-      const ImplParams& impl_params) override {
+      const CertVerifyProc::ImplParams& impl_params,
+      const CertVerifyProc::InstanceParams& instance_params) override {
     return mock_verify_proc_;
   }
 
@@ -105,7 +105,7 @@
                 mock_new_verify_proc_))) {
     EXPECT_CALL(*mock_verify_proc_, SupportsAdditionalTrustAnchors())
         .WillRepeatedly(Return(true));
-    EXPECT_CALL(*mock_verify_proc_, VerifyInternal(_, _, _, _, _, _, _, _))
+    EXPECT_CALL(*mock_verify_proc_, VerifyInternal(_, _, _, _, _, _, _))
         .WillRepeatedly(
             DoAll(SetCertVerifyResult(), Return(ERR_CERT_COMMON_NAME_INVALID)));
   }
@@ -276,7 +276,7 @@
     verifier_->SetConfig(config);
 
     EXPECT_CALL(*mock_verify_proc_,
-                VerifyInternal(_, _, _, _, test_config.expected_flag, _, _, _))
+                VerifyInternal(_, _, _, _, test_config.expected_flag, _, _))
         .WillRepeatedly(
             DoAll(SetCertVerifyRevokedResult(), Return(ERR_CERT_REVOKED)));
 
@@ -307,7 +307,7 @@
   EXPECT_CALL(
       *mock_verify_proc_,
       VerifyInternal(_, _, _, _, CertVerifyProc::VERIFY_DISABLE_NETWORK_FETCHES,
-                     _, _, _))
+                     _, _))
       .WillRepeatedly(
           DoAll(SetCertVerifyRevokedResult(), Return(ERR_CERT_REVOKED)));
 
@@ -340,10 +340,10 @@
 
   EXPECT_EQ(observer_counter.change_count(), 0u);
 
-  EXPECT_CALL(*mock_new_verify_proc_, VerifyInternal(_, _, _, _, _, _, _, _))
+  EXPECT_CALL(*mock_new_verify_proc_, VerifyInternal(_, _, _, _, _, _, _))
       .WillRepeatedly(
           DoAll(SetCertVerifyRevokedResult(), Return(ERR_CERT_REVOKED)));
-  verifier_->UpdateVerifyProcData(nullptr, {});
+  verifier_->UpdateVerifyProcData(nullptr, {}, {});
 
   EXPECT_EQ(observer_counter.change_count(), 1u);
 
@@ -383,7 +383,7 @@
       &verify_result, callback.callback(), &request, NetLogWithSource());
   ASSERT_THAT(error, IsError(ERR_IO_PENDING));
   EXPECT_TRUE(request);
-  verifier_->UpdateVerifyProcData(nullptr, {});
+  verifier_->UpdateVerifyProcData(nullptr, {}, {});
   error = callback.WaitForResult();
   EXPECT_TRUE(IsCertificateError(error));
   EXPECT_THAT(error, IsError(ERR_CERT_COMMON_NAME_INVALID));
diff --git a/net/cert/nss_cert_database_unittest.cc b/net/cert/nss_cert_database_unittest.cc
index 4792cc6a..8be2e31 100644
--- a/net/cert/nss_cert_database_unittest.cc
+++ b/net/cert/nss_cert_database_unittest.cc
@@ -207,10 +207,6 @@
 
   std::unique_ptr<NSSCertDatabase> cert_db_;
   std::unique_ptr<MockNSSCertDatabaseObserver> observer_;
-  // When building with libstdc++, |empty_cert_list_| does not have a default
-  // constructor.  Initialize it explicitly so that CertDatabaseNSSTest gets a
-  // default constructor.
-  const CertificateList empty_cert_list_ = CertificateList();
   crypto::ScopedTestNSSDB test_nssdb_;
   crypto::ScopedPK11Slot public_slot_;
   scoped_refptr<CRLSet> crl_set_;
@@ -853,13 +849,14 @@
   ASSERT_TRUE(x509_found_server_cert);
   scoped_refptr<CertVerifyProc> verify_proc(
       CertVerifyProc::CreateBuiltinWithChromeRootStore(
-          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr));
+          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr,
+          /*instance_params=*/{}));
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = verify_proc->Verify(
-      x509_found_server_cert.get(), "127.0.0.1",
-      /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
-      empty_cert_list_, &verify_result, NetLogWithSource());
+  int error = verify_proc->Verify(x509_found_server_cert.get(), "127.0.0.1",
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string(), flags,
+                                  &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
   EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status);
 
@@ -891,13 +888,14 @@
   ASSERT_TRUE(x509_puny_cert);
   scoped_refptr<CertVerifyProc> verify_proc(
       CertVerifyProc::CreateBuiltinWithChromeRootStore(
-          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr));
+          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr,
+          /*instance_params=*/{}));
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = verify_proc->Verify(
-      x509_puny_cert.get(), "xn--wgv71a119e.com",
-      /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
-      empty_cert_list_, &verify_result, NetLogWithSource());
+  int error = verify_proc->Verify(x509_puny_cert.get(), "xn--wgv71a119e.com",
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string(), flags,
+                                  &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
   EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status);
 
@@ -930,13 +928,14 @@
   ASSERT_TRUE(x509_puny_cert);
   scoped_refptr<CertVerifyProc> verify_proc(
       CertVerifyProc::CreateBuiltinWithChromeRootStore(
-          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr));
+          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr,
+          /*instance_params=*/{}));
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = verify_proc->Verify(
-      x509_puny_cert.get(), "xn--wgv71a119e.com",
-      /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
-      empty_cert_list_, &verify_result, NetLogWithSource());
+  int error = verify_proc->Verify(x509_puny_cert.get(), "xn--wgv71a119e.com",
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string(), flags,
+                                  &verify_result, NetLogWithSource());
   if (base::FeatureList::IsEnabled(features::kTrustStoreTrustedLeafSupport)) {
     EXPECT_THAT(error, IsOk());
     EXPECT_EQ(0U, verify_result.cert_status);
@@ -979,13 +978,14 @@
   ASSERT_TRUE(x509_server_cert);
   scoped_refptr<CertVerifyProc> verify_proc(
       CertVerifyProc::CreateBuiltinWithChromeRootStore(
-          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr));
+          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr,
+          /*instance_params=*/{}));
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = verify_proc->Verify(
-      x509_server_cert.get(), "127.0.0.1",
-      /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
-      empty_cert_list_, &verify_result, NetLogWithSource());
+  int error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1",
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string(), flags,
+                                  &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
 }
@@ -1022,13 +1022,14 @@
   ASSERT_TRUE(x509_server_cert);
   scoped_refptr<CertVerifyProc> verify_proc(
       CertVerifyProc::CreateBuiltinWithChromeRootStore(
-          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr));
+          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr,
+          /*instance_params=*/{}));
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = verify_proc->Verify(
-      x509_server_cert.get(), "127.0.0.1",
-      /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
-      empty_cert_list_, &verify_result, NetLogWithSource());
+  int error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1",
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string(), flags,
+                                  &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
   EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status);
 }
@@ -1081,13 +1082,14 @@
   // Server cert should verify.
   scoped_refptr<CertVerifyProc> verify_proc(
       CertVerifyProc::CreateBuiltinWithChromeRootStore(
-          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr));
+          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr,
+          /*instance_params=*/{}));
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = verify_proc->Verify(
-      x509_server_cert.get(), "www.example.com",
-      /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
-      empty_cert_list_, &verify_result, NetLogWithSource());
+  int error = verify_proc->Verify(x509_server_cert.get(), "www.example.com",
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string(), flags,
+                                  &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
 
@@ -1110,11 +1112,10 @@
 
   // Server cert should fail to verify.
   CertVerifyResult verify_result2;
-  error =
-      verify_proc->Verify(x509_server_cert.get(), "www.example.com",
-                          /*ocsp_response=*/std::string(),
-                          /*sct_list=*/std::string(), flags, empty_cert_list_,
-                          &verify_result2, NetLogWithSource());
+  error = verify_proc->Verify(x509_server_cert.get(), "www.example.com",
+                              /*ocsp_response=*/std::string(),
+                              /*sct_list=*/std::string(), flags,
+                              &verify_result2, NetLogWithSource());
   EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
   EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result2.cert_status);
 }
@@ -1148,13 +1149,14 @@
   // Server cert should verify.
   scoped_refptr<CertVerifyProc> verify_proc(
       CertVerifyProc::CreateBuiltinWithChromeRootStore(
-          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr));
+          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr,
+          /*instance_params=*/{}));
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = verify_proc->Verify(
-      x509_server_cert.get(), "www.example.com",
-      /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
-      empty_cert_list_, &verify_result, NetLogWithSource());
+  int error = verify_proc->Verify(x509_server_cert.get(), "www.example.com",
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string(), flags,
+                                  &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
 
@@ -1164,11 +1166,10 @@
 
   // Server cert should fail to verify.
   CertVerifyResult verify_result2;
-  error =
-      verify_proc->Verify(x509_server_cert.get(), "www.example.com",
-                          /*ocsp_response=*/std::string(),
-                          /*sct_list=*/std::string(), flags, empty_cert_list_,
-                          &verify_result2, NetLogWithSource());
+  error = verify_proc->Verify(x509_server_cert.get(), "www.example.com",
+                              /*ocsp_response=*/std::string(),
+                              /*sct_list=*/std::string(), flags,
+                              &verify_result2, NetLogWithSource());
   EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
   EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result2.cert_status);
 }
@@ -1213,13 +1214,14 @@
   // Server cert should verify.
   scoped_refptr<CertVerifyProc> verify_proc(
       CertVerifyProc::CreateBuiltinWithChromeRootStore(
-          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr));
+          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr,
+          /*instance_params=*/{}));
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = verify_proc->Verify(
-      x509_server_cert.get(), "www.example.com",
-      /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
-      empty_cert_list_, &verify_result, NetLogWithSource());
+  int error = verify_proc->Verify(x509_server_cert.get(), "www.example.com",
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string(), flags,
+                                  &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result.cert_status);
 
@@ -1229,11 +1231,10 @@
 
   // Server cert should fail to verify.
   CertVerifyResult verify_result2;
-  error =
-      verify_proc->Verify(x509_server_cert.get(), "www.example.com",
-                          /*ocsp_response=*/std::string(),
-                          /*sct_list=*/std::string(), flags, empty_cert_list_,
-                          &verify_result2, NetLogWithSource());
+  error = verify_proc->Verify(x509_server_cert.get(), "www.example.com",
+                              /*ocsp_response=*/std::string(),
+                              /*sct_list=*/std::string(), flags,
+                              &verify_result2, NetLogWithSource());
   EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
   EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result2.cert_status);
 }
@@ -1278,13 +1279,14 @@
   // Server cert should not verify.
   scoped_refptr<CertVerifyProc> verify_proc(
       CertVerifyProc::CreateBuiltinWithChromeRootStore(
-          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr));
+          /*cert_net_fetcher=*/nullptr, crl_set_, /*root_store_data=*/nullptr,
+          /*instance_params=*/{}));
   int flags = 0;
   CertVerifyResult verify_result;
-  int error = verify_proc->Verify(
-      x509_server_cert.get(), "www.example.com",
-      /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
-      empty_cert_list_, &verify_result, NetLogWithSource());
+  int error = verify_proc->Verify(x509_server_cert.get(), "www.example.com",
+                                  /*ocsp_response=*/std::string(),
+                                  /*sct_list=*/std::string(), flags,
+                                  &verify_result, NetLogWithSource());
   EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
   EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status);
 
@@ -1294,11 +1296,10 @@
 
   // Server cert should verify.
   CertVerifyResult verify_result2;
-  error =
-      verify_proc->Verify(x509_server_cert.get(), "www.example.com",
-                          /*ocsp_response=*/std::string(),
-                          /*sct_list=*/std::string(), flags, empty_cert_list_,
-                          &verify_result2, NetLogWithSource());
+  error = verify_proc->Verify(x509_server_cert.get(), "www.example.com",
+                              /*ocsp_response=*/std::string(),
+                              /*sct_list=*/std::string(), flags,
+                              &verify_result2, NetLogWithSource());
   EXPECT_THAT(error, IsOk());
   EXPECT_EQ(0U, verify_result2.cert_status);
 }
diff --git a/net/cert/test_root_certs_unittest.cc b/net/cert/test_root_certs_unittest.cc
index ce501d05..a2bf28b 100644
--- a/net/cert/test_root_certs_unittest.cc
+++ b/net/cert/test_root_certs_unittest.cc
@@ -39,16 +39,17 @@
   if (base::FeatureList::IsEnabled(features::kChromeRootStoreUsed)) {
     return CertVerifyProc::CreateBuiltinWithChromeRootStore(
         /*cert_net_fetcher=*/nullptr, CRLSet::BuiltinCRLSet().get(),
-        /*root_store_data=*/nullptr);
+        /*root_store_data=*/nullptr, /*instance_params=*/{});
   }
 #endif
 #if BUILDFLAG(CHROME_ROOT_STORE_ONLY)
   return CertVerifyProc::CreateBuiltinWithChromeRootStore(
       /*cert_net_fetcher=*/nullptr, CRLSet::BuiltinCRLSet().get(),
-      /*root_store_data=*/nullptr);
+      /*root_store_data=*/nullptr, /*instance_params=*/{});
 #elif BUILDFLAG(IS_FUCHSIA)
-  return CertVerifyProc::CreateBuiltinVerifyProc(/*cert_net_fetcher=*/nullptr,
-                                                 CRLSet::BuiltinCRLSet().get());
+  return CertVerifyProc::CreateBuiltinVerifyProc(
+      /*cert_net_fetcher=*/nullptr, CRLSet::BuiltinCRLSet().get(),
+      /*instance_params=*/{});
 #else
   return CertVerifyProc::CreateSystemVerifyProc(/*cert_net_fetcher=*/nullptr,
                                                 CRLSet::BuiltinCRLSet().get());
@@ -93,10 +94,10 @@
   int flags = 0;
   CertVerifyResult bad_verify_result;
   scoped_refptr<CertVerifyProc> verify_proc(CreateCertVerifyProc());
-  int bad_status = verify_proc->Verify(
-      test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-      /*sct_list=*/std::string(), flags, CertificateList(), &bad_verify_result,
-      NetLogWithSource());
+  int bad_status = verify_proc->Verify(test_cert.get(), "127.0.0.1",
+                                       /*ocsp_response=*/std::string(),
+                                       /*sct_list=*/std::string(), flags,
+                                       &bad_verify_result, NetLogWithSource());
   EXPECT_NE(OK, bad_status);
   EXPECT_NE(0u, bad_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID);
   EXPECT_FALSE(bad_verify_result.is_issued_by_known_root);
@@ -113,7 +114,7 @@
   CertVerifyResult good_verify_result;
   int good_status = verify_proc->Verify(
       test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-      /*sct_list=*/std::string(), flags, CertificateList(), &good_verify_result,
+      /*sct_list=*/std::string(), flags, &good_verify_result,
       NetLogWithSource());
   EXPECT_THAT(good_status, IsOk());
   EXPECT_EQ(0u, good_verify_result.cert_status);
@@ -128,8 +129,8 @@
   CertVerifyResult restored_verify_result;
   int restored_status = verify_proc->Verify(
       test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-      /*sct_list=*/std::string(), flags, CertificateList(),
-      &restored_verify_result, NetLogWithSource());
+      /*sct_list=*/std::string(), flags, &restored_verify_result,
+      NetLogWithSource());
   EXPECT_NE(OK, restored_status);
   EXPECT_NE(0u,
             restored_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID);
@@ -161,7 +162,7 @@
   int good_status =
       verify_proc->Verify(leaf->GetX509Certificate().get(), "www.example.com",
                           /*ocsp_response=*/std::string(),
-                          /*sct_list=*/std::string(), flags, CertificateList(),
+                          /*sct_list=*/std::string(), flags,
                           &good_verify_result, NetLogWithSource());
   EXPECT_THAT(good_status, IsOk());
   EXPECT_EQ(0u, good_verify_result.cert_status);
@@ -180,7 +181,7 @@
   int restored_status =
       verify_proc->Verify(leaf->GetX509Certificate().get(), "www.example.com",
                           /*ocsp_response=*/std::string(),
-                          /*sct_list=*/std::string(), flags, CertificateList(),
+                          /*sct_list=*/std::string(), flags,
                           &restored_verify_result, NetLogWithSource());
   EXPECT_THAT(restored_status, IsOk());
   EXPECT_EQ(0u, restored_verify_result.cert_status);
@@ -207,10 +208,10 @@
 
     // Test that the good certificate fails verification, because the root
     // certificate should not yet be trusted.
-    bad_status = verify_proc->Verify(
-        test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-        /*sct_list=*/std::string(), flags, CertificateList(),
-        &bad_verify_result, NetLogWithSource());
+    bad_status = verify_proc->Verify(test_cert.get(), "127.0.0.1",
+                                     /*ocsp_response=*/std::string(),
+                                     /*sct_list=*/std::string(), flags,
+                                     &bad_verify_result, NetLogWithSource());
     EXPECT_NE(OK, bad_status);
     EXPECT_NE(0u,
               bad_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID);
@@ -228,8 +229,8 @@
       CertVerifyResult good_verify_result;
       int good_status = verify_proc->Verify(
           test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-          /*sct_list=*/std::string(), flags, CertificateList(),
-          &good_verify_result, NetLogWithSource());
+          /*sct_list=*/std::string(), flags, &good_verify_result,
+          NetLogWithSource());
       EXPECT_THAT(good_status, IsOk());
       EXPECT_EQ(0u, good_verify_result.cert_status);
 
@@ -250,8 +251,8 @@
     CertVerifyResult good_verify_result;
     int good_status = verify_proc->Verify(
         test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-        /*sct_list=*/std::string(), flags, CertificateList(),
-        &good_verify_result, NetLogWithSource());
+        /*sct_list=*/std::string(), flags, &good_verify_result,
+        NetLogWithSource());
     EXPECT_THAT(good_status, IsOk());
     EXPECT_EQ(0u, good_verify_result.cert_status);
   }
@@ -263,8 +264,8 @@
   CertVerifyResult restored_verify_result;
   int restored_status = verify_proc->Verify(
       test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
-      /*sct_list=*/std::string(), flags, CertificateList(),
-      &restored_verify_result, NetLogWithSource());
+      /*sct_list=*/std::string(), flags, &restored_verify_result,
+      NetLogWithSource());
   EXPECT_NE(OK, restored_status);
   EXPECT_NE(0u,
             restored_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID);
diff --git a/net/cert_net/cert_net_fetcher_url_request.cc b/net/cert_net/cert_net_fetcher_url_request.cc
index baae518..b912bf7 100644
--- a/net/cert_net/cert_net_fetcher_url_request.cc
+++ b/net/cert_net/cert_net_fetcher_url_request.cc
@@ -479,7 +479,7 @@
   }
 
   // Start the URLRequest.
-  read_buffer_ = base::MakeRefCounted<IOBuffer>(kReadBufferSizeInBytes);
+  read_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSizeInBytes);
   NetworkTrafficAnnotationTag traffic_annotation =
       DefineNetworkTrafficAnnotation("certificate_verifier_url_request",
                                      R"(
diff --git a/net/data/cache_tests/dirty_entry5/contents.txt b/net/data/cache_tests/dirty_entry5/contents.txt
index 28ff786..8e9fab7 100644
--- a/net/data/cache_tests/dirty_entry5/contents.txt
+++ b/net/data/cache_tests/dirty_entry5/contents.txt
@@ -153,7 +153,7 @@
 
   const int kSize = 20;
   ASSERT_EQ(net::OK, OpenEntry(key1, &entry));
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   memset(buf->data(), 0, kSize);
   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buf, kSize, false));
   entry->Close();
@@ -163,4 +163,4 @@
 
   ASSERT_EQ(net::OK, DoomEntry(key3));
 
-(*) and trick the code into deleting the dirty flag.
\ No newline at end of file
+(*) and trick the code into deleting the dirty flag.
diff --git a/net/data/cache_tests/good_2_0/contents.txt b/net/data/cache_tests/good_2_0/contents.txt
index 4b987fc5..11f3dfb 100644
--- a/net/data/cache_tests/good_2_0/contents.txt
+++ b/net/data/cache_tests/good_2_0/contents.txt
@@ -14,8 +14,7 @@
   ASSERT_THAT(CreateEntry(kKey, &entry), IsOk());
 
   const int kBufSize = 1234;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, /*no_nulls=*/false);
 
   EXPECT_EQ(kBufSize, WriteData(entry, /*index=*/1, /*offset=*/0, buffer.get(),
diff --git a/net/data/cache_tests/good_2_1/contents.txt b/net/data/cache_tests/good_2_1/contents.txt
index fddaf89..b5b2295 100644
--- a/net/data/cache_tests/good_2_1/contents.txt
+++ b/net/data/cache_tests/good_2_1/contents.txt
@@ -16,7 +16,7 @@
 
   const int kBufSize = 1234;
   scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+      base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, /*no_nulls=*/false);
 
   EXPECT_EQ(kBufSize, WriteData(entry, /*index=*/1, /*offset=*/0, buffer.get(),
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc
index 5475c22..f4c7155 100644
--- a/net/disk_cache/backend_unittest.cc
+++ b/net/disk_cache/backend_unittest.cc
@@ -226,8 +226,7 @@
 void DiskCacheBackendTest::CreateKeyAndCheck(disk_cache::Backend* cache,
                                              std::string key) {
   const int kBufSize = 4 * 1024;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, true);
   TestEntryResultCompletionCallback cb_entry;
   disk_cache::EntryResult result =
@@ -272,8 +271,7 @@
   disk_cache::Entry* entry = entry_result.ReleaseEntry();
 
   const int kSize = 25000;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   int rv = net::OK;
@@ -316,8 +314,7 @@
   disk_cache::Entry* entry1 = nullptr;
   disk_cache::Entry* entry2 = nullptr;
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   ASSERT_THAT(CreateEntry("zeroth", &entry0), IsOk());
@@ -731,8 +728,7 @@
 
   // Extravagant size payload to make reproducing races easier.
   const int kBufSize = 256 * 1024;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, true);
 
   SetSimpleCacheMode();
@@ -776,8 +772,7 @@
   // Tests index recovery in APP_CACHE mode. (This is harder to test for
   // DISK_CACHE since post-cleanup callbacks aren't permitted there).
   const int kBufSize = 4 * 1024;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, true);
 
   SetSimpleCacheMode();
@@ -856,8 +851,7 @@
   InitCache();
 
   // Fill in to about 80-90% full.
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kEntrySize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kEntrySize);
   CacheTestFillBuffer(buffer->data(), kEntrySize, false);
 
   for (int i = 0; i < 0.9 * (kLimit / kEntrySize); ++i) {
@@ -888,8 +882,7 @@
   base::FilePath filename = cache_path_.AppendASCII("f_000001");
 
   const int kSize = 50;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer1->data(), kSize, false);
   ASSERT_TRUE(base::WriteFile(
       filename,
@@ -902,8 +895,7 @@
   entry->Close();
 
   // And verify that the first file is still there.
-  scoped_refptr<net::IOBuffer> buffer2(
-      base::MakeRefCounted<net::IOBuffer>(kSize));
+  auto buffer2(base::MakeRefCounted<net::IOBufferWithSize>(kSize));
   ASSERT_EQ(kSize, base::ReadFile(filename, buffer2->data(), kSize));
   EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize));
 }
@@ -1138,8 +1130,7 @@
   disk_cache::Entry* entry;
   ASSERT_THAT(CreateEntry(first, &entry), IsOk());
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(cache_size);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(cache_size);
   memset(buffer->data(), 0, cache_size);
   EXPECT_EQ(cache_size / 10,
             WriteData(entry, 0, 0, buffer.get(), cache_size / 10, false))
@@ -1340,8 +1331,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 50;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   memset(buffer1->data(), 0, kSize);
   base::strlcpy(buffer1->data(), "And the data to save", kSize);
   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer1.get(), kSize, false));
@@ -1350,8 +1340,7 @@
 
   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
 
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   memset(buffer2->data(), 0, kSize);
   EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer2.get(), kSize));
   entry->Close();
@@ -1378,8 +1367,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 50;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   memset(buffer->data(), 0, kSize);
   base::strlcpy(buffer->data(), "And the data to save", kSize);
   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
@@ -1423,8 +1411,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 50;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   memset(buffer->data(), 0, kSize);
   base::strlcpy(buffer->data(), "And the data to save", kSize);
   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
@@ -1551,8 +1538,7 @@
   disk_cache::Entry* entry;
   ASSERT_THAT(CreateEntry(first, &entry), IsOk());
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   memset(buffer->data(), 0, kSize);
   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
 
@@ -1601,8 +1587,7 @@
   SetMaxSize(kSize * 40);
   InitCache();
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   memset(buffer->data(), 0, kSize);
   disk_cache::Entry* entry;
 
@@ -1871,8 +1856,7 @@
   const std::string second("second");
   disk_cache::Entry *entry1, *entry2;
   const int kSize = 50;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
 
   ASSERT_THAT(CreateEntry(first, &entry1), IsOk());
   memset(buffer1->data(), 0, kSize);
@@ -1908,8 +1892,7 @@
   ASSERT_THAT(CreateEntry(key, &entry1), IsOk());
 
   const int kSize = 50;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   memset(buffer1->data(), 0, kSize);
   base::strlcpy(buffer1->data(), "And the data to save", kSize);
   EXPECT_EQ(kSize, WriteData(entry1, 0, 0, buffer1.get(), kSize, false));
@@ -2096,7 +2079,7 @@
   SetMemoryOnlyMode();
   InitCache();
 
-  scoped_refptr<net::IOBuffer> buffer = base::MakeRefCounted<net::IOBuffer>(64);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(64);
   CacheTestFillBuffer(buffer->data(), 64, false /* no_nulls */);
 
   std::vector<disk_cache::ScopedEntryPtr> entries;
@@ -3344,8 +3327,7 @@
   ASSERT_THAT(CreateEntry(key3, &entry3), IsOk());
 
   const int kBufSize = 20000;
-  scoped_refptr<net::IOBuffer> buf =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   memset(buf->data(), 0, kBufSize);
   EXPECT_EQ(100, WriteData(entry2, 0, 0, buf.get(), 100, false));
   EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf.get(), kBufSize, false));
@@ -3452,8 +3434,7 @@
   SetMaxSize(kMaxSize);
   InitSparseCache(nullptr, nullptr);
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kWriteSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kWriteSize);
   CacheTestFillBuffer(buffer->data(), kWriteSize, false);
 
   std::string key_prefix("prefix");
@@ -3496,8 +3477,7 @@
   SetMaxSize(kMaxSize);
   InitCache();
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kWriteSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kWriteSize);
   CacheTestFillBuffer(buffer->data(), kWriteSize, false);
 
   // Create an entry to be our sparse entry that gets written later.
@@ -3538,8 +3518,7 @@
   SetMaxSize(kMaxSize);
   InitCache();
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kWriteSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kWriteSize);
   CacheTestFillBuffer(buffer->data(), kWriteSize, false);
 
   // Create an entry to be the final entry that gets written later.
@@ -3824,8 +3803,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 200;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, true);
 
   for (int i = 0; i < 10; i++) {
@@ -4122,8 +4100,7 @@
   InitCache();
   disk_cache::Entry* entry;
   const int kSize = 50;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
   ASSERT_THAT(CreateEntry("key", &entry), IsOk());
   ASSERT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, false));
@@ -4149,8 +4126,7 @@
   InitCache();
   disk_cache::Entry* entry;
   const int kSize = 50;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
   ASSERT_THAT(CreateEntry("key", &entry), IsOk());
   ASSERT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, false));
@@ -4247,8 +4223,7 @@
   ASSERT_THAT(CreateEntry(key, &corrupted_entry), IsOk());
   ASSERT_TRUE(corrupted_entry);
   const int kSize = 50;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
   ASSERT_EQ(kSize,
             WriteData(corrupted_entry, 0, 0, buffer.get(), kSize, false));
@@ -4319,12 +4294,9 @@
 
   // Write some data to the entries.
   const int kSize = 10;
-  scoped_refptr<net::IOBuffer> buf1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buf2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buf3 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buf2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buf3 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf1->data(), kSize, false);
   CacheTestFillBuffer(buf2->data(), kSize, false);
   CacheTestFillBuffer(buf3->data(), kSize, false);
@@ -4352,12 +4324,9 @@
       std::move(quit_closure).Run();
   };
 
-  scoped_refptr<net::IOBuffer> read_buf1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> read_buf2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> read_buf3 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto read_buf1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto read_buf2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto read_buf3 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
 
   // Read from the entries in order 2, 3, 1. They should be reprioritized to
   // 3, 1, 2.
@@ -4563,12 +4532,10 @@
                                      disk_cache::FD_LIMIT_FAIL_REOPEN_FILE, 0);
 
   const int kSize = 25000;
-  scoped_refptr<net::IOBuffer> buf1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf1->data(), kSize, false);
 
-  scoped_refptr<net::IOBuffer> buf2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf2->data(), kSize, false);
 
   // Doom an entry and create a new one with same name, to test that both
@@ -4591,8 +4558,7 @@
   // actually need files.
   for (int i = 1; i < kLargeNumEntries; ++i) {
     EXPECT_EQ(kSize, WriteData(entries[i], 1, 0, buf1.get(), kSize, true));
-    scoped_refptr<net::IOBuffer> read_buf =
-        base::MakeRefCounted<net::IOBuffer>(kSize);
+    auto read_buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
     ASSERT_EQ(kSize, ReadData(entries[i], 1, 0, read_buf.get(), kSize));
     EXPECT_EQ(0, memcmp(read_buf->data(), buf1->data(), kSize));
   }
@@ -4609,13 +4575,11 @@
   EXPECT_EQ(kSize, WriteData(entries[0], 1, 0, buf1.get(), kSize, true));
   EXPECT_EQ(kSize, WriteData(alt_entry, 1, 0, buf2.get(), kSize, true));
 
-  scoped_refptr<net::IOBuffer> read_buf =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto read_buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   ASSERT_EQ(kSize, ReadData(entries[0], 1, 0, read_buf.get(), kSize));
   EXPECT_EQ(0, memcmp(read_buf->data(), buf1->data(), kSize));
 
-  scoped_refptr<net::IOBuffer> read_buf2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto read_buf2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   ASSERT_EQ(kSize, ReadData(alt_entry, 1, 0, read_buf2.get(), kSize));
   EXPECT_EQ(0, memcmp(read_buf2->data(), buf2->data(), kSize));
 
@@ -4657,7 +4621,7 @@
   SetMaxSize(kMaxSize);
   InitCache();
 
-  scoped_refptr<net::IOBuffer> buffer = base::MakeRefCounted<net::IOBuffer>(64);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(64);
   CacheTestFillBuffer(buffer->data(), 64, false);
 
   disk_cache::Entry* entry0 = nullptr;
@@ -4691,7 +4655,7 @@
   SetMemoryOnlyMode();
   InitCache();
 
-  scoped_refptr<net::IOBuffer> buffer = base::MakeRefCounted<net::IOBuffer>(64);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(64);
   CacheTestFillBuffer(buffer->data(), 64, false);
 
   disk_cache::Entry* entry = nullptr;
@@ -5152,8 +5116,7 @@
   // (See https://crbug.com/1015774).
   const char kKey[] = "for_lock";
   const int kBufSize = 2 * 1024;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, true);
 
   SetSimpleCacheMode();
@@ -5199,8 +5162,7 @@
   ASSERT_THAT(CreateEntry(kKey, &entry), IsOk());
 
   const int kBufSize = 24320;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, true);
 
   ASSERT_EQ(kBufSize, WriteSparseData(entry, 0, buffer.get(), kBufSize));
@@ -5238,8 +5200,7 @@
   ASSERT_THAT(CreateEntry(kKey, &entry), IsOk());
 
   const int kBufSize = 61188;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, true);
 
   net::TestCompletionCallback cb_write64;
@@ -5306,8 +5267,7 @@
   mem_cache_->SetClockForTesting(&clock);
 
   const int kBufSize = 4 * 1024;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, true);
 
   disk_cache::Entry* entry = nullptr;
@@ -5337,8 +5297,7 @@
   const char kKey[] = "http://example.org";
 
   const int kBufSize = 256;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, /*no_nulls=*/false);
 
   SetSimpleCacheMode();
@@ -5375,8 +5334,7 @@
   InitCache();
 
   const int kBufSize = 256;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, /*no_nulls=*/false);
 
   // Create an entry.
@@ -5415,8 +5373,7 @@
   const char kKey[] = "Key0";
 
   const int kBufSize = 256;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, /*no_nulls=*/false);
 
   SetCacheType(net::SHADER_CACHE);
diff --git a/net/disk_cache/blockfile/sparse_control.cc b/net/disk_cache/blockfile/sparse_control.cc
index 5c8a52d..8341de2 100644
--- a/net/disk_cache/blockfile/sparse_control.cc
+++ b/net/disk_cache/blockfile/sparse_control.cc
@@ -458,7 +458,7 @@
     return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
 
   // Read the actual bitmap.
-  buf = base::MakeRefCounted<net::IOBuffer>(map_len);
+  buf = base::MakeRefCounted<net::IOBufferWithSize>(map_len);
   rv = entry_->ReadData(kSparseIndex, sizeof(sparse_header_), buf.get(),
                         map_len, CompletionOnceCallback());
   if (rv != map_len)
diff --git a/net/disk_cache/disk_cache_fuzzer.cc b/net/disk_cache/disk_cache_fuzzer.cc
index 38ea90a..a0dcbdf5 100644
--- a/net/disk_cache/disk_cache_fuzzer.cc
+++ b/net/disk_cache/disk_cache_fuzzer.cc
@@ -109,8 +109,8 @@
 
     // Re-using this buffer for write operations may technically be against
     // IOBuffer rules but it shouldn't cause any actual problems.
-    buffer_ =
-        base::MakeRefCounted<net::IOBuffer>(static_cast<size_t>(kMaxEntrySize));
+    buffer_ = base::MakeRefCounted<net::IOBufferWithSize>(
+        static_cast<size_t>(kMaxEntrySize));
     CacheTestFillBuffer(buffer_->data(), kMaxEntrySize, false);
 
 #define CREATE_IO_CALLBACK(IO_TYPE) \
@@ -698,8 +698,7 @@
         uint32_t offset = wd.offset() % kMaxEntrySize;
         size_t size = wd.size() % kMaxEntrySize;
         bool async = wd.async();
-        scoped_refptr<net::IOBuffer> buffer =
-            base::MakeRefCounted<net::IOBuffer>(size);
+        auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(size);
 
         net::TestCompletionCallback tcb;
         net::CompletionOnceCallback cb =
@@ -762,8 +761,7 @@
           offset %= kMaxEntrySize;
         size_t size = rsd.size() % kMaxEntrySize;
         bool async = rsd.async();
-        scoped_refptr<net::IOBuffer> buffer =
-            base::MakeRefCounted<net::IOBuffer>(size);
+        auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(size);
 
         net::TestCompletionCallback tcb;
         net::CompletionOnceCallback cb =
diff --git a/net/disk_cache/disk_cache_perftest.cc b/net/disk_cache/disk_cache_perftest.cc
index eff5e46..4cf6492 100644
--- a/net/disk_cache/disk_cache_perftest.cc
+++ b/net/disk_cache/disk_cache_perftest.cc
@@ -183,9 +183,9 @@
   int pending_result_ = net::OK;
 
   scoped_refptr<net::IOBuffer> headers_buffer_ =
-      base::MakeRefCounted<net::IOBuffer>(kHeadersSize);
+      base::MakeRefCounted<net::IOBufferWithSize>(kHeadersSize);
   scoped_refptr<net::IOBuffer> body_buffer_ =
-      base::MakeRefCounted<net::IOBuffer>(kChunkSize);
+      base::MakeRefCounted<net::IOBufferWithSize>(kChunkSize);
 };
 
 void WriteHandler::Run() {
@@ -278,7 +278,7 @@
         cache_(cache),
         final_callback_(std::move(final_callback)) {
     for (auto& read_buffer : read_buffers_) {
-      read_buffer = base::MakeRefCounted<net::IOBuffer>(
+      read_buffer = base::MakeRefCounted<net::IOBufferWithSize>(
           std::max(kHeadersSize, kChunkSize));
     }
   }
@@ -587,10 +587,8 @@
 
   InitCache();
   // Write out the entries, and keep their objects around.
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kHeadersSize);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kBodySize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kHeadersSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kBodySize);
 
   CacheTestFillBuffer(buffer1->data(), kHeadersSize, false);
   CacheTestFillBuffer(buffer2->data(), kBodySize, false);
diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc
index 9a0618d8..9a56851 100644
--- a/net/disk_cache/entry_unittest.cc
+++ b/net/disk_cache/entry_unittest.cc
@@ -105,8 +105,7 @@
 // This part of the test runs on the background thread.
 void DiskCacheEntryTest::InternalSyncIOBackground(disk_cache::Entry* entry) {
   const int kSize1 = 10;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
   EXPECT_EQ(0, entry->ReadData(0, 0, buffer1.get(), kSize1,
                                net::CompletionOnceCallback()));
@@ -120,10 +119,8 @@
 
   const int kSize2 = 5000;
   const int kSize3 = 10000;
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize2);
-  scoped_refptr<net::IOBuffer> buffer3 =
-      base::MakeRefCounted<net::IOBuffer>(kSize3);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
+  auto buffer3 = base::MakeRefCounted<net::IOBufferWithSize>(kSize3);
   memset(buffer3->data(), 0, kSize3);
   CacheTestFillBuffer(buffer2->data(), kSize2, false);
   base::strlcpy(buffer2->data(), "The really big data goes here", kSize2);
@@ -220,12 +217,9 @@
   const int kSize1 = 10;
   const int kSize2 = 5000;
   const int kSize3 = 10000;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize2);
-  scoped_refptr<net::IOBuffer> buffer3 =
-      base::MakeRefCounted<net::IOBuffer>(kSize3);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
+  auto buffer3 = base::MakeRefCounted<net::IOBufferWithSize>(kSize3);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
   CacheTestFillBuffer(buffer2->data(), kSize2, false);
   CacheTestFillBuffer(buffer3->data(), kSize3, false);
@@ -354,10 +348,8 @@
 void DiskCacheEntryTest::ExternalSyncIOBackground(disk_cache::Entry* entry) {
   const int kSize1 = 17000;
   const int kSize2 = 25000;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize2);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
   CacheTestFillBuffer(buffer2->data(), kSize2, false);
   base::strlcpy(buffer1->data(), "the data", kSize1);
@@ -447,12 +439,9 @@
   const int kSize1 = 17000;
   const int kSize2 = 25000;
   const int kSize3 = 25000;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize2);
-  scoped_refptr<net::IOBuffer> buffer3 =
-      base::MakeRefCounted<net::IOBuffer>(kSize3);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
+  auto buffer3 = base::MakeRefCounted<net::IOBufferWithSize>(kSize3);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
   CacheTestFillBuffer(buffer2->data(), kSize2, false);
   CacheTestFillBuffer(buffer3->data(), kSize3, false);
@@ -575,8 +564,7 @@
   ASSERT_TRUE(nullptr != entry);
 
   const int kBufferSize = 1024;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufferSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
   CacheTestFillBuffer(buffer->data(), kBufferSize, false);
 
   net::ReleaseBufferCompletionCallback cb(buffer.get());
@@ -607,11 +595,10 @@
   const int kNumStreams = 3;
   scoped_refptr<net::IOBuffer> reference_buffers[kNumStreams];
   for (auto& reference_buffer : reference_buffers) {
-    reference_buffer = base::MakeRefCounted<net::IOBuffer>(kBufferSize);
+    reference_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
     CacheTestFillBuffer(reference_buffer->data(), kBufferSize, false);
   }
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kBufferSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
   for (int i = 0; i < kNumStreams; i++) {
     EXPECT_EQ(
         kBufferSize,
@@ -632,8 +619,7 @@
   const int kFinalReadSize = kBufferSize - kReadBufferSize;
   static_assert(kFinalReadSize < kReadBufferSize,
                 "should be exactly two reads");
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kReadBufferSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kReadBufferSize);
   for (int i = 0; i < kNumStreams; i++) {
     memset(buffer2->data(), 0, kReadBufferSize);
     EXPECT_EQ(kReadBufferSize,
@@ -744,8 +730,7 @@
   Time t3 = Time::Now();
   EXPECT_TRUE(t3 > t2);
   const int kSize = 200;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   EXPECT_EQ(kSize, ReadData(entry, stream_index, 0, buffer.get(), kSize));
   if (type_ == net::APP_CACHE) {
     EXPECT_TRUE(entry->GetLastUsed() < t2);
@@ -789,10 +774,8 @@
   ASSERT_THAT(CreateEntry(key1, &entry), IsOk());
 
   const int kSize = 20000;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer1->data(), kSize, false);
   memset(buffer2->data(), 0, kSize);
 
@@ -879,10 +862,8 @@
 
   const int kSize1 = 20000;
   const int kSize2 = 20000;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize2);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
 
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
   memset(buffer2->data(), 0, kSize2);
@@ -977,8 +958,7 @@
   // Let's verify the actual content.
   const int kSize = 20;
   const char zeros[kSize] = {};
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
 
   CacheTestFillBuffer(buffer->data(), kSize, false);
   EXPECT_EQ(kSize, ReadData(entry, stream_index, 500, buffer.get(), kSize));
@@ -1020,10 +1000,8 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 200;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer1->data(), kSize, true);
   CacheTestFillBuffer(buffer2->data(), kSize, true);
 
@@ -1135,10 +1113,8 @@
 
   const int kSize = 200;
   const char zeros[kSize] = {};
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer1->data(), kSize, true);
   CacheTestFillBuffer(buffer2->data(), kSize, true);
 
@@ -1246,8 +1222,7 @@
   std::string key2("the second key");
   ASSERT_THAT(CreateEntry(key2, &entry), IsOk());
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(size);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(size);
   CacheTestFillBuffer(buffer->data(), size, false);
 
   for (int i = 0; i < 15; i++) {
@@ -1298,12 +1273,9 @@
   const int kSize1 = 20000;
   const int kSize2 = 20000;
   const int kSize3 = 20000;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize2);
-  scoped_refptr<net::IOBuffer> buffer3 =
-      base::MakeRefCounted<net::IOBuffer>(kSize3);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
+  auto buffer3 = base::MakeRefCounted<net::IOBufferWithSize>(kSize3);
 
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
   memset(buffer2->data(), 0, kSize2);
@@ -1388,8 +1360,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 200;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   net::TestCompletionCallback cb;
@@ -1402,7 +1373,7 @@
   EXPECT_EQ(kSize, cb.WaitForResult());
 
   // And now test with a Read().
-  buffer = base::MakeRefCounted<net::IOBuffer>(kSize);
+  buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   EXPECT_EQ(
@@ -1427,8 +1398,7 @@
   entry->Close();
 
   const int kSize = 20000;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, true);
   buffer->data()[19999] = '\0';
 
@@ -1510,10 +1480,8 @@
 
   const int kSize1 = 2000;
   const int kSize2 = 2000;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize2);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
   memset(buffer2->data(), 0, kSize2);
 
@@ -1549,8 +1517,7 @@
 
   // Write to an external file.
   const int kSize = 20000;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
   entry->Close();
@@ -1577,7 +1544,7 @@
   InitCache();
 
   const int kSize = 4096;
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf->data(), kSize, false);
 
   std::string key("the first key");
@@ -1638,8 +1605,7 @@
                            int size) {
   net::TestCompletionCallback cb;
 
-  scoped_refptr<net::IOBuffer> buf_1 =
-      base::MakeRefCounted<net::IOBuffer>(size);
+  auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(size);
   memset(buf_1->data(), 0, size);
   int ret = entry->ReadSparseData(offset, buf_1.get(), size, cb.callback());
   EXPECT_EQ(size, cb.GetResult(ret));
@@ -1652,10 +1618,8 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 2048;
-  scoped_refptr<net::IOBuffer> buf_1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buf_2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf_1->data(), kSize, false);
 
   // Write at offset 0.
@@ -1695,10 +1659,8 @@
 
   // Write 1.2 MB so that we cover multiple entries.
   const int kSize = 1200 * 1024;
-  scoped_refptr<net::IOBuffer> buf_1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buf_2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf_1->data(), kSize, false);
 
   // Write at offset 0x20F0000 (33 MB - 64 KB).
@@ -1728,7 +1690,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 16 * 1024;
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf->data(), kSize, false);
 
   // Write at offset 0x20F0000 (33 MB - 64 KB), and 0x20F4400 (33 MB - 47 KB).
@@ -1821,13 +1783,11 @@
   disk_cache::Entry* entry;
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
-  scoped_refptr<net::IOBuffer> buf_2k =
-      base::MakeRefCounted<net::IOBuffer>(2 * 1024);
+  auto buf_2k = base::MakeRefCounted<net::IOBufferWithSize>(2 * 1024);
   CacheTestFillBuffer(buf_2k->data(), 2 * 1024, false);
 
   const int kSmallSize = 612;  // sub-1k
-  scoped_refptr<net::IOBuffer> buf_small =
-      base::MakeRefCounted<net::IOBuffer>(kSmallSize);
+  auto buf_small = base::MakeRefCounted<net::IOBufferWithSize>(kSmallSize);
   CacheTestFillBuffer(buf_small->data(), kSmallSize, false);
 
   // Sets some bits for blocks representing 1K ranges [1024, 3072),
@@ -1915,10 +1875,8 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 180;
-  scoped_refptr<net::IOBuffer> buf_1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buf_2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf_1->data(), kSize, false);
 
   // Do small writes (180 bytes) that get increasingly close to a 1024-byte
@@ -1978,10 +1936,8 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 180;
-  scoped_refptr<net::IOBuffer> buf_1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buf_2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf_1->data(), kSize, false);
 
   // Any starting offset is fine as long as it is 1024-bytes aligned.
@@ -2030,7 +1986,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 16 * 1024;
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf->data(), kSize, false);
 
   // Write at offset 0x20F0000 (33 MB - 64 KB).
@@ -2076,10 +2032,8 @@
   InitCache();
 
   const int kSize = 8192;
-  scoped_refptr<net::IOBuffer> buf_1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buf_2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf_1->data(), kSize, false);
 
   std::string key("the first key");
@@ -2110,7 +2064,7 @@
   InitCache();
 
   const int kSize = 8192;
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf->data(), kSize, false);
 
   disk_cache::Entry* entry;
@@ -2179,10 +2133,8 @@
   ASSERT_THAT(CreateEntry(key, &entry1), IsOk());
 
   const int kSize = 2048;
-  scoped_refptr<net::IOBuffer> buf_1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buf_2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf_1->data(), kSize, false);
 
   // Write at offset 0.
@@ -2224,7 +2176,7 @@
   ASSERT_THAT(CreateEntry(key2, &entry2), IsOk());
 
   const int kSize = 4 * 1024;
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf->data(), kSize, false);
 
   int64_t offset = 1024;
@@ -2315,7 +2267,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 4 * 1024;
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf->data(), kSize, false);
 
   int64_t offset = 1024;
@@ -2344,8 +2296,7 @@
   // of a sparse entry, at least to write a big range without leaving holes.
   const int kSize = 4 * 1024;
   const int kSmallSize = 128;
-  scoped_refptr<net::IOBuffer> buf1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf1->data(), kSize, false);
 
   // The first write is just to extend the entry. The third write occupies
@@ -2358,8 +2309,7 @@
   entry->Close();
   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
 
-  scoped_refptr<net::IOBuffer> buf2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   memset(buf2->data(), 0, kSize);
   EXPECT_EQ(0, ReadSparseData(entry, 8000, buf2.get(), kSize));
 
@@ -2458,7 +2408,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 2048;
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf->data(), kSize, false);
 
   EXPECT_EQ(net::ERR_INVALID_ARGUMENT,
@@ -2511,11 +2461,10 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 1024;
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf->data(), kSize, false);
 
-  scoped_refptr<net::IOBuffer> read_buf =
-      base::MakeRefCounted<net::IOBuffer>(kSize * 2);
+  auto read_buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize * 2);
   CacheTestFillBuffer(read_buf->data(), kSize * 2, false);
 
   const int64_t kOffset = max_index - kSize;
@@ -2571,7 +2520,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 1024;
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf->data(), kSize, false);
 
   // Try to write after --- fails.
@@ -2613,8 +2562,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 4 * 1024;
-  scoped_refptr<net::IOBuffer> buf1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf1->data(), kSize, false);
 
   const int k1Meg = 1024 * 1024;
@@ -2665,7 +2613,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 40 * 1024;
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf->data(), kSize, false);
 
   // This will open and write two "real" entries.
@@ -2901,8 +2849,7 @@
 
 TEST_F(DiskCacheEntryTest, SimpleCacheGiantEntry) {
   const int kBufSize = 32 * 1024;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
   CacheTestFillBuffer(buffer->data(), kBufSize, false);
 
   // Make sure SimpleCache can write up to 5MiB entry even with a 20MiB cache
@@ -3002,8 +2949,7 @@
     return false;
   }
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(data_size);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(data_size);
   memset(buffer->data(), 'A', data_size);
 
   EXPECT_EQ(data_size, WriteData(entry, 1, 0, buffer.get(), data_size, false));
@@ -3040,8 +2986,7 @@
   ScopedEntryPtr entry_closer(entry);
 
   EXPECT_GE(kLargeSize, entry->GetDataSize(1));
-  scoped_refptr<net::IOBuffer> read_buffer =
-      base::MakeRefCounted<net::IOBuffer>(kLargeSize);
+  auto read_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kLargeSize);
   EXPECT_EQ(net::ERR_CACHE_CHECKSUM_MISMATCH,
             ReadData(entry, 1, 0, read_buffer.get(), kLargeSize));
 }
@@ -3062,8 +3007,7 @@
   ScopedEntryPtr entry_closer(entry);
 
   EXPECT_GE(kLargeSize, entry->GetDataSize(1));
-  scoped_refptr<net::IOBuffer> read_buffer =
-      base::MakeRefCounted<net::IOBuffer>(kLargeSize);
+  auto read_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kLargeSize);
   EXPECT_EQ(net::ERR_CACHE_CHECKSUM_MISMATCH,
             ReadData(entry, 1, 0, read_buffer.get(), kLargeSize));
   entry->Doom();  // Should not crash.
@@ -3080,8 +3024,7 @@
 
   const char key[] = "the key";
   const int kSize1 = 10;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
 
   disk_cache::Entry* entry = nullptr;
@@ -3169,8 +3112,7 @@
 
   const char kKey[] = "the first key";
   const int kSize1 = 10;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
 
   disk_cache::Entry* entry = nullptr;
@@ -3352,14 +3294,10 @@
   int expected = 0;
   const int kSize1 = 10;
   const int kSize2 = 20;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
-  scoped_refptr<net::IOBuffer> buffer1_read =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize2);
-  scoped_refptr<net::IOBuffer> buffer2_read =
-      base::MakeRefCounted<net::IOBuffer>(kSize2);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
+  auto buffer1_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
+  auto buffer2_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
   CacheTestFillBuffer(buffer2->data(), kSize2, false);
 
@@ -3496,8 +3434,7 @@
 
   net::TestCompletionCallback cb;
   const int kSize1 = 10;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
 
   EntryResult result =
@@ -3565,8 +3502,7 @@
 
   net::TestCompletionCallback cb;
   const int kSize1 = 10;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
 
   EntryResult result =
@@ -3600,10 +3536,8 @@
 
   net::TestCompletionCallback cb;
   const int kSize1 = 10;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
-  scoped_refptr<net::IOBuffer> buffer1_read =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
+  auto buffer1_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
 
   EntryResult result =
@@ -3647,8 +3581,7 @@
   ScopedEntryPtr entry_closer(entry);
 
   const int kWriteSize = 512;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kWriteSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kWriteSize);
   EXPECT_TRUE(buffer1->HasOneRef());
   CacheTestFillBuffer(buffer1->data(), kWriteSize, false);
 
@@ -3675,8 +3608,7 @@
 
   net::TestCompletionCallback cb;
   const int kSize1 = 10;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize1);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
   CacheTestFillBuffer(buffer1->data(), kSize1, false);
 
   EntryResult result =
@@ -3764,10 +3696,8 @@
 
   // Do some I/O to make sure it's alive.
   const int kSize = 2048;
-  scoped_refptr<net::IOBuffer> buf_1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buf_2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf_1->data(), kSize, false);
 
   EXPECT_EQ(kSize, WriteData(entry2, /* index = */ 1, /* offset = */ 0,
@@ -3980,8 +3910,7 @@
   std::string key1("the first key");
   disk_cache::Entry* entry;
   ASSERT_THAT(CreateEntry(key1, &entry), IsOk());
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kWriteSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kWriteSize);
   CacheTestFillBuffer(buffer->data(), kWriteSize, false);
   EXPECT_EQ(kWriteSize,
             WriteData(entry, 1, 0, buffer.get(), kWriteSize, false));
@@ -4031,8 +3960,7 @@
   // the point of the test which coverred two concurrent disk ops, with
   // portions of work happening on the workpool.
   const int kBufferSize = 50000;
-  scoped_refptr<net::IOBuffer> write_buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufferSize);
+  auto write_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
   CacheTestFillBuffer(write_buffer->data(), kBufferSize, false);
 
   disk_cache::Entry* entry = nullptr;
@@ -4051,8 +3979,8 @@
 
   // Make a short read.
   const int kReadBufferSize = 512;
-  scoped_refptr<net::IOBuffer> read_buffer =
-      base::MakeRefCounted<net::IOBuffer>(kReadBufferSize);
+  auto read_buffer =
+      base::MakeRefCounted<net::IOBufferWithSize>(kReadBufferSize);
   CallbackTest read_callback(&helper, false);
   EXPECT_EQ(net::ERR_IO_PENDING,
             entry->ReadData(1, 0, read_buffer.get(), kReadBufferSize,
@@ -4061,8 +3989,8 @@
   ++expected;
 
   // Truncate the entry to the length of that read.
-  scoped_refptr<net::IOBuffer> truncate_buffer =
-      base::MakeRefCounted<net::IOBuffer>(kReadBufferSize);
+  auto truncate_buffer =
+      base::MakeRefCounted<net::IOBufferWithSize>(kReadBufferSize);
   CacheTestFillBuffer(truncate_buffer->data(), kReadBufferSize, false);
   CallbackTest truncate_callback(&helper, false);
   EXPECT_EQ(
@@ -4097,8 +4025,7 @@
   ScopedEntryPtr entry_closer(entry);
 
   const int kBufferSize = 1024;
-  scoped_refptr<net::IOBuffer> write_buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufferSize);
+  auto write_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
   CacheTestFillBuffer(write_buffer->data(), kBufferSize, false);
 
   MessageLoopHelper helper;
@@ -4112,8 +4039,7 @@
                              true));
   ++expected;
 
-  scoped_refptr<net::IOBuffer> read_buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufferSize);
+  auto read_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
   CallbackTest read_callback(&helper, false);
   EXPECT_EQ(net::ERR_IO_PENDING,
             entry->ReadData(1, 0, read_buffer.get(), kBufferSize,
@@ -4167,10 +4093,8 @@
   int size = 50000;
   ASSERT_TRUE(SimpleCacheMakeBadChecksumEntry(key, size));
 
-  scoped_refptr<net::IOBuffer> read_buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(size);
-  scoped_refptr<net::IOBuffer> read_buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(size);
+  auto read_buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(size);
+  auto read_buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(size);
 
   // Advance the first reader a little.
   disk_cache::Entry* entry = nullptr;
@@ -4205,8 +4129,7 @@
 
   const int kHalfSize = 200;
   const int kSize = 2 * kHalfSize;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer1->data(), kSize, false);
   disk_cache::Entry* entry = nullptr;
 
@@ -4223,16 +4146,14 @@
   // Read the first half of the data.
   int offset = 0;
   int buf_len = kHalfSize;
-  scoped_refptr<net::IOBuffer> buffer1_read1 =
-      base::MakeRefCounted<net::IOBuffer>(buf_len);
+  auto buffer1_read1 = base::MakeRefCounted<net::IOBufferWithSize>(buf_len);
   EXPECT_EQ(buf_len, ReadData(entry2, 1, offset, buffer1_read1.get(), buf_len));
   EXPECT_EQ(0, memcmp(buffer1->data(), buffer1_read1->data(), buf_len));
 
   // Read the second half of the data.
   offset = buf_len;
   buf_len = kHalfSize;
-  scoped_refptr<net::IOBuffer> buffer1_read2 =
-      base::MakeRefCounted<net::IOBuffer>(buf_len);
+  auto buffer1_read2 = base::MakeRefCounted<net::IOBufferWithSize>(buf_len);
   EXPECT_EQ(buf_len, ReadData(entry2, 1, offset, buffer1_read2.get(), buf_len));
   char* buffer1_data = buffer1->data() + offset;
   EXPECT_EQ(0, memcmp(buffer1_data, buffer1_read2->data(), buf_len));
@@ -4258,10 +4179,8 @@
 
   const int kHalfSize = 200;
   const int kSize = 2 * kHalfSize;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer1->data(), kSize, false);
   char* buffer1_data = buffer1->data() + kHalfSize;
   memcpy(buffer2->data(), buffer1_data, kHalfSize);
@@ -4286,8 +4205,7 @@
 
     ASSERT_THAT(OpenEntry(key, &entry), IsOk());
 
-    scoped_refptr<net::IOBuffer> buffer1_read1 =
-        base::MakeRefCounted<net::IOBuffer>(kSize);
+    auto buffer1_read1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
     EXPECT_EQ(kSize, ReadData(entry, i, 0, buffer1_read1.get(), kSize));
     EXPECT_EQ(0, memcmp(buffer1->data(), buffer1_read1->data(), kSize));
     // Check that we are not leaking.
@@ -4305,10 +4223,8 @@
   disk_cache::Entry* entry = nullptr;
   const std::string key("the key");
   const int kSize = 100;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buffer_read =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buffer_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
@@ -4352,7 +4268,7 @@
   EXPECT_TRUE((eof_record.flags & disk_cache::SimpleFileEOF::FLAG_HAS_CRC32) ==
               disk_cache::SimpleFileEOF::FLAG_HAS_CRC32);
 
-  buffer_read = base::MakeRefCounted<net::IOBuffer>(kSize);
+  buffer_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer_read.get(), kSize));
   EXPECT_EQ(0, memcmp(buffer->data(), buffer_read->data(), kSize));
 
@@ -4363,7 +4279,7 @@
   entry->Close();
 
   // Check that stream0 data has not been modified.
-  buffer_read = base::MakeRefCounted<net::IOBuffer>(kSize);
+  buffer_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
   EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer_read.get(), kSize));
   EXPECT_EQ(0, memcmp(buffer->data(), buffer_read->data(), kSize));
@@ -4384,10 +4300,8 @@
 
   const int kHalfSize = 200;
   const int kSize = 2 * kHalfSize;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kHalfSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kHalfSize);
   CacheTestFillBuffer(buffer1->data(), kSize, false);
   CacheTestFillBuffer(buffer2->data(), kHalfSize, false);
 
@@ -4411,8 +4325,7 @@
 
     ASSERT_THAT(OpenEntry(key, &entry), IsOk());
 
-    scoped_refptr<net::IOBuffer> buffer1_read1 =
-        base::MakeRefCounted<net::IOBuffer>(kSize);
+    auto buffer1_read1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
     EXPECT_EQ(kSize, ReadData(entry, i, 0, buffer1_read1.get(), kSize));
     EXPECT_EQ(0, memcmp(buffer1->data(), buffer1_read1->data(), kHalfSize));
     EXPECT_EQ(
@@ -4442,8 +4355,7 @@
     const std::string& key,
     int data_size) {
   // Use one buffer for simplicity.
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(data_size);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(data_size);
   CacheTestFillBuffer(buffer->data(), data_size, false);
 
   disk_cache::Entry* entry = nullptr;
@@ -4475,8 +4387,7 @@
   ResetCaches();
 
   const int kSize = 100;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   // Do some writes and reads, but don't change the result. We're OK
@@ -4490,8 +4401,7 @@
 
 void DiskCacheEntryTest::CloseSparseAfterBackendDestruction() {
   const int kSize = 100;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   disk_cache::Entry* entry = nullptr;
@@ -4533,8 +4443,7 @@
   const int kHalfSize = 8;
   const int kSize = kHalfSize * 2;
   const char key[] = "key";
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kHalfSize, false);
 
   disk_cache::Entry* entry;
@@ -4559,10 +4468,8 @@
   const int kHalfSize = 8;
   const int kSize = kHalfSize * 2;
   const char key[] = "key";
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer1->data(), kHalfSize, false);
 
   disk_cache::Entry* entry;
@@ -4595,10 +4502,8 @@
   const int kHalfSize = 8;
   const int kSize = kHalfSize * 2;
   const char key[] = "key";
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer1->data(), kHalfSize, false);
 
   disk_cache::Entry* entry;
@@ -4633,8 +4538,7 @@
   const int kHalfSize = 8;
   const int kSize = kHalfSize * 2;
   const char key[] = "key";
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kHalfSize, false);
 
   disk_cache::Entry* entry;
@@ -4660,10 +4564,8 @@
   const char key[] = "the first key";
 
   const int kSize = 200;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer1->data(), kSize, false);
   CacheTestFillBuffer(buffer2->data(), kSize, false);
 
@@ -4816,8 +4718,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
   EXPECT_NE(null, entry);
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
   net::TestCompletionCallback callback;
   int ret;
@@ -4900,8 +4801,7 @@
       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0));
   EXPECT_TRUE(base::PathExists(path_0));
 
-  scoped_refptr<net::IOBuffer> check_stream_data =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto check_stream_data = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   EXPECT_EQ(kSize, ReadData(entry, 0, 0, check_stream_data.get(), kSize));
   EXPECT_EQ(kSize, ReadData(entry, 1, 0, check_stream_data.get(), kSize));
   EXPECT_EQ(0, entry->GetDataSize(2));
@@ -4918,13 +4818,13 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const std::string stream_0_data = "data for stream zero";
-  scoped_refptr<net::IOBuffer> stream_0_iobuffer =
+  auto stream_0_iobuffer =
       base::MakeRefCounted<net::StringIOBuffer>(stream_0_data);
   EXPECT_EQ(static_cast<int>(stream_0_data.size()),
             WriteData(entry, 0, 0, stream_0_iobuffer.get(),
                       stream_0_data.size(), false));
   const std::string stream_1_data = "FOR STREAM ONE, QUITE DIFFERENT THINGS";
-  scoped_refptr<net::IOBuffer> stream_1_iobuffer =
+  auto stream_1_iobuffer =
       base::MakeRefCounted<net::StringIOBuffer>(stream_1_data);
   EXPECT_EQ(static_cast<int>(stream_1_data.size()),
             WriteData(entry, 1, 0, stream_1_iobuffer.get(),
@@ -4941,8 +4841,8 @@
   ScopedEntryPtr entry_closer(entry);
 
   EXPECT_EQ(static_cast<int>(stream_0_data.size()), entry->GetDataSize(0));
-  scoped_refptr<net::IOBuffer> check_stream_0_data =
-      base::MakeRefCounted<net::IOBuffer>(stream_0_data.size());
+  auto check_stream_0_data =
+      base::MakeRefCounted<net::IOBufferWithSize>(stream_0_data.size());
   EXPECT_EQ(
       static_cast<int>(stream_0_data.size()),
       ReadData(entry, 0, 0, check_stream_0_data.get(), stream_0_data.size()));
@@ -4951,8 +4851,8 @@
                                      stream_0_data.size()));
 
   EXPECT_EQ(static_cast<int>(stream_1_data.size()), entry->GetDataSize(1));
-  scoped_refptr<net::IOBuffer> check_stream_1_data =
-      base::MakeRefCounted<net::IOBuffer>(stream_1_data.size());
+  auto check_stream_1_data =
+      base::MakeRefCounted<net::IOBufferWithSize>(stream_1_data.size());
   EXPECT_EQ(
       static_cast<int>(stream_1_data.size()),
       ReadData(entry, 1, 0, check_stream_1_data.get(), stream_1_data.size()));
@@ -5067,8 +4967,7 @@
   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
 
   const int kSize = 1024;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   EXPECT_EQ(kSize, WriteSparseData(entry, 0, buffer.get(), kSize));
@@ -5128,12 +5027,9 @@
       "\xbc\x60\x64\x92\xbc\xa0\x5c\x15\x17\x93\x29\x2d\xe4\x21\xbd\x03";
 
   const int kSize = 256;
-  scoped_refptr<net::IOBuffer> buffer1 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
-  scoped_refptr<net::IOBuffer> read_buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
+  auto read_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer1->data(), kSize, false);
   CacheTestFillBuffer(buffer2->data(), kSize, false);
 
@@ -5168,8 +5064,7 @@
   // Testcase for what happens when we have a sparse stream and a left over
   // empty stream 2 file.
   const int kSize = 10;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   SetSimpleCacheMode();
@@ -5189,8 +5084,7 @@
 
   // Reopen, and try to get the sparse data back.
   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   EXPECT_EQ(kSize, ReadSparseData(entry, 5, buffer2.get(), kSize));
   EXPECT_EQ(0, memcmp(buffer->data(), buffer2->data(), kSize));
   entry->Close();
@@ -5199,8 +5093,7 @@
 TEST_F(DiskCacheEntryTest, SimpleCacheLazyStream2CreateFailure) {
   // Testcase for what happens when lazy-creation of stream 2 fails.
   const int kSize = 10;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   // Synchronous ops, for ease of disk state;
@@ -5231,13 +5124,11 @@
   // Test for a bug that occurred during development of  movement of CRC
   // computation off I/O thread.
   const int kSize = 10;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   const int kDoubleSize = kSize * 2;
-  scoped_refptr<net::IOBuffer> big_buffer =
-      base::MakeRefCounted<net::IOBuffer>(kDoubleSize);
+  auto big_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kDoubleSize);
   CacheTestFillBuffer(big_buffer->data(), kDoubleSize, false);
 
   SetSimpleCacheMode();
@@ -5263,8 +5154,7 @@
   entry->Close();
 
   ASSERT_THAT(OpenEntry(kKey, &entry), IsOk());
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   EXPECT_EQ(kSize, ReadData(entry, 1, 0, buffer2.get(), kSize));
   EXPECT_EQ(0, memcmp(buffer->data(), buffer2->data(), kSize));
   EXPECT_EQ(kSize, ReadData(entry, 1, kSize, buffer2.get(), kSize));
@@ -5346,11 +5236,9 @@
   const int kBigSize = 40 * 1024;
   const int kSmallSize = 9727;
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBigSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBigSize);
   CacheTestFillBuffer(buffer->data(), kBigSize, false);
-  scoped_refptr<net::IOBuffer> read_buf =
-      base::MakeRefCounted<net::IOBuffer>(kBigSize);
+  auto read_buf = base::MakeRefCounted<net::IOBufferWithSize>(kBigSize);
 
   ASSERT_EQ(kSmallSize, WriteData(entry, /* index = */ 0,
                                   /* offset = */ kBigSize, buffer.get(),
@@ -5402,8 +5290,7 @@
   ASSERT_TRUE(entry != nullptr);
 
   const int kSize = 1024;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   // Offset here needs to be > blockfile's kMaxBlockSize to hit
@@ -5462,8 +5349,7 @@
   // even if they happen after a bunch of shifting right.
   const int64_t kOffset = (1ll << 61);
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   EXPECT_EQ(blockfile ? net::ERR_CACHE_OPERATION_NOT_SUPPORTED : kSize,
@@ -5500,8 +5386,7 @@
 
 TEST_F(DiskCacheEntryTest, SimpleCacheCloseResurrection) {
   const int kSize = 10;
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buffer->data(), kSize, false);
 
   const char kKey[] = "key";
@@ -5545,8 +5430,7 @@
   base::RunLoop().RunUntilIdle();
 
   // Make sure |entry2| is still usable.
-  scoped_refptr<net::IOBuffer> buffer2 =
-      base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   memset(buffer2->data(), 0, kSize);
   EXPECT_EQ(kSize, ReadData(entry2, 1, 0, buffer2.get(), kSize));
   EXPECT_EQ(0, memcmp(buffer->data(), buffer2->data(), kSize));
@@ -5567,7 +5451,7 @@
 
   const int kSize = 61184;
 
-  scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
   CacheTestFillBuffer(buf->data(), kSize, false);
 
   // The write pattern here avoids the second write being handled by the
@@ -5590,7 +5474,7 @@
   enum { kEntrySize = 1024 };
 
   void SetUp() override {
-    payload_ = base::MakeRefCounted<net::IOBuffer>(kEntrySize);
+    payload_ = base::MakeRefCounted<net::IOBufferWithSize>(kEntrySize);
     CacheTestFillBuffer(payload_->data(), kEntrySize, false);
     DiskCacheEntryTest::SetUp();
   }
@@ -5640,8 +5524,7 @@
     // the checksum in that case.  Do it with identical contents, though,
     // so that the only difference between here and InitCacheAndCreateEntry()
     // would be whether the result has a checkum or not.
-    scoped_refptr<net::IOBuffer> second_half =
-        base::MakeRefCounted<net::IOBuffer>(kRemSize);
+    auto second_half = base::MakeRefCounted<net::IOBufferWithSize>(kRemSize);
     memcpy(second_half->data(), payload_->data() + kHalfSize, kRemSize);
     ASSERT_EQ(kRemSize, WriteData(entry, 1, kHalfSize, second_half.get(),
                                   kRemSize, false));
@@ -5651,8 +5534,7 @@
   void TryRead(const std::string& key, bool expect_preread_stream1) {
     disk_cache::Entry* entry = nullptr;
     ASSERT_THAT(OpenEntry(key, &entry), IsOk());
-    scoped_refptr<net::IOBuffer> read_buf =
-        base::MakeRefCounted<net::IOBuffer>(kEntrySize);
+    auto read_buf = base::MakeRefCounted<net::IOBufferWithSize>(kEntrySize);
     net::TestCompletionCallback cb;
     int rv = entry->ReadData(1, 0, read_buf.get(), kEntrySize, cb.callback());
 
@@ -5786,8 +5668,7 @@
 
   disk_cache::Entry* entry = nullptr;
   ASSERT_THAT(OpenEntry(kKey, &entry), IsOk());
-  scoped_refptr<net::IOBuffer> read_buf =
-      base::MakeRefCounted<net::IOBuffer>(kEntrySize);
+  auto read_buf = base::MakeRefCounted<net::IOBufferWithSize>(kEntrySize);
 
   // That this is entry->ReadData(...) rather than ReadData(entry, ...) is
   // meaningful here, as the latter is a helper in the test fixture that blocks
diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc
index 6aaeabb..b6e9905 100644
--- a/net/disk_cache/simple/simple_entry_impl.cc
+++ b/net/disk_cache/simple/simple_entry_impl.cc
@@ -480,7 +480,7 @@
     // here to avoid paying the price of the RefCountedThreadSafe atomic
     // operations.
     if (buf) {
-      op_buf = base::MakeRefCounted<IOBuffer>(buf_len);
+      op_buf = base::MakeRefCounted<net::IOBufferWithSize>(buf_len);
       std::copy(buf->data(), buf->data() + buf_len, op_buf->data());
     }
     op_callback = CompletionOnceCallback();
diff --git a/net/dns/dns_config_service_win.cc b/net/dns/dns_config_service_win.cc
index 1bc138b..0307025 100644
--- a/net/dns/dns_config_service_win.cc
+++ b/net/dns/dns_config_service_win.cc
@@ -9,6 +9,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <string_view>
 
 #include "base/compiler_specific.h"
 #include "base/files/file_path.h"
@@ -352,7 +353,7 @@
 
 }  // namespace
 
-std::string ParseDomainASCII(base::WStringPiece widestr) {
+std::string ParseDomainASCII(std::wstring_view widestr) {
   if (widestr.empty())
     return "";
 
@@ -379,7 +380,7 @@
   return converted;
 }
 
-std::vector<std::string> ParseSearchList(base::WStringPiece value) {
+std::vector<std::string> ParseSearchList(std::wstring_view value) {
   if (value.empty())
     return {};
 
@@ -389,7 +390,7 @@
   // Although nslookup and network connection property tab ignore such
   // fragments ("a,b,,c" becomes ["a", "b", "c"]), our reference is getaddrinfo
   // (which sees ["a", "b"]). WMI queries also return a matching search list.
-  for (base::WStringPiece t : base::SplitStringPiece(
+  for (std::wstring_view t : base::SplitStringPiece(
            value, L",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
     // Convert non-ASCII to punycode, although getaddrinfo does not properly
     // handle such suffixes.
diff --git a/net/dns/dns_config_service_win.h b/net/dns/dns_config_service_win.h
index d96729cc..0d9e499e 100644
--- a/net/dns/dns_config_service_win.h
+++ b/net/dns/dns_config_service_win.h
@@ -13,10 +13,10 @@
 
 #include <memory>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/memory/free_deleter.h"
-#include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 #include "net/dns/dns_config_service.h"
 #include "net/dns/public/win_dns_system_settings.h"
@@ -38,14 +38,14 @@
 
 // Converts a UTF-16 domain name to ASCII, possibly using punycode.
 // Returns empty string on failure.
-std::string NET_EXPORT_PRIVATE ParseDomainASCII(base::WStringPiece widestr);
+std::string NET_EXPORT_PRIVATE ParseDomainASCII(std::wstring_view widestr);
 
 // Parses |value| as search list (comma-delimited list of domain names) from
 // a registry key and stores it in |out|. Returns empty vector on failure. Empty
 // entries (e.g., "chromium.org,,org") terminate the list. Non-ascii hostnames
 // are converted to punycode.
 std::vector<std::string> NET_EXPORT_PRIVATE
-ParseSearchList(base::WStringPiece value);
+ParseSearchList(std::wstring_view value);
 
 // Fills in |dns_config| from |settings|. Exposed for tests. Returns nullopt if
 // a valid config could not be determined.
diff --git a/net/dns/dns_parse_domain_ascii_win_fuzzer.cc b/net/dns/dns_parse_domain_ascii_win_fuzzer.cc
index f37a74c..cb5326bca 100644
--- a/net/dns/dns_parse_domain_ascii_win_fuzzer.cc
+++ b/net/dns/dns_parse_domain_ascii_win_fuzzer.cc
@@ -2,21 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/dns/dns_config_service_win.h"
-
 #include <stddef.h>
 #include <stdint.h>
 
 #include <string>
+#include <string_view>
 
-#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
+#include "net/dns/dns_config_service_win.h"
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   if (size > 8 * 1024)
     return 0;
 
-  base::WStringPiece widestr(reinterpret_cast<const wchar_t*>(data), size / 2);
+  std::wstring_view widestr(reinterpret_cast<const wchar_t*>(data), size / 2);
   std::string result = net::internal::ParseDomainASCII(widestr);
 
   if (!result.empty())
diff --git a/net/dns/dns_response.cc b/net/dns/dns_response.cc
index 6f145e8..4126cd1 100644
--- a/net/dns/dns_response.cc
+++ b/net/dns/dns_response.cc
@@ -317,7 +317,7 @@
       std::accumulate(additional_records.begin(), additional_records.end(),
                       response_size, do_accumulation);
 
-  auto io_buffer = base::MakeRefCounted<IOBuffer>(response_size);
+  auto io_buffer = base::MakeRefCounted<IOBufferWithSize>(response_size);
   base::BigEndianWriter writer(io_buffer->data(), response_size);
   success &= WriteHeader(&writer, header);
   DCHECK(success);
@@ -358,14 +358,15 @@
 }
 
 DnsResponse::DnsResponse()
-    : io_buffer_(base::MakeRefCounted<IOBuffer>(dns_protocol::kMaxUDPSize + 1)),
+    : io_buffer_(base::MakeRefCounted<IOBufferWithSize>(
+          dns_protocol::kMaxUDPSize + 1)),
       io_buffer_size_(dns_protocol::kMaxUDPSize + 1) {}
 
 DnsResponse::DnsResponse(scoped_refptr<IOBuffer> buffer, size_t size)
     : io_buffer_(std::move(buffer)), io_buffer_size_(size) {}
 
 DnsResponse::DnsResponse(size_t length)
-    : io_buffer_(base::MakeRefCounted<IOBuffer>(length)),
+    : io_buffer_(base::MakeRefCounted<IOBufferWithSize>(length)),
       io_buffer_size_(length) {}
 
 DnsResponse::DnsResponse(const void* data, size_t length, size_t answer_offset)
diff --git a/net/dns/dns_test_util.cc b/net/dns/dns_test_util.cc
index 92510f81..59ecab0f 100644
--- a/net/dns/dns_test_util.cc
+++ b/net/dns/dns_test_util.cc
@@ -539,8 +539,8 @@
     if (result->response) {
       // Copy response in case |result| is destroyed before the transaction
       // completes.
-      auto buffer_copy =
-          base::MakeRefCounted<IOBuffer>(result->response->io_buffer_size());
+      auto buffer_copy = base::MakeRefCounted<IOBufferWithSize>(
+          result->response->io_buffer_size());
       memcpy(buffer_copy->data(), result->response->io_buffer()->data(),
              result->response->io_buffer_size());
       result_.response = DnsResponse(std::move(buffer_copy),
diff --git a/net/filter/gzip_source_stream_unittest.cc b/net/filter/gzip_source_stream_unittest.cc
index efd68e2..072371c 100644
--- a/net/filter/gzip_source_stream_unittest.cc
+++ b/net/filter/gzip_source_stream_unittest.cc
@@ -71,7 +71,8 @@
     CompressGzip(source_data_, source_data_len_, encoded_data_,
                  &encoded_data_len_, type != SourceStream::TYPE_DEFLATE);
 
-    output_buffer_ = base::MakeRefCounted<IOBuffer>(output_buffer_size_);
+    output_buffer_ =
+        base::MakeRefCounted<IOBufferWithSize>(output_buffer_size_);
     auto source = std::make_unique<MockSourceStream>();
     if (GetParam().read_result_type == ReadResultType::ONE_BYTE_AT_A_TIME)
       source->set_read_one_byte_at_a_time(true);
diff --git a/net/http/bidirectional_stream_unittest.cc b/net/http/bidirectional_stream_unittest.cc
index 3c6625a..91d16290 100644
--- a/net/http/bidirectional_stream_unittest.cc
+++ b/net/http/bidirectional_stream_unittest.cc
@@ -490,8 +490,7 @@
   request_info->url = default_url_;
   request_info->extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
                                         base::NumberToString(kBodyDataSize));
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->Start(std::move(request_info), http_session_.get());
@@ -543,10 +542,8 @@
   request_info2->url = default_url_;
   request_info2->end_stream_on_headers = true;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
-  scoped_refptr<IOBuffer> read_buffer2 =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
+  auto read_buffer2 = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   auto delegate2 =
@@ -631,8 +628,7 @@
   request_info->end_stream_on_headers = true;
   request_info->priority = LOWEST;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
 
@@ -691,8 +687,7 @@
   request_info->end_stream_on_headers = true;
   request_info->priority = LOWEST;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   // Create a MockTimer. Retain a raw pointer since the underlying
   // BidirectionalStreamImpl owns it.
   auto timer = std::make_unique<MockTimer>();
@@ -779,8 +774,7 @@
       net::HttpRequestHeaders::kContentLength,
       base::NumberToString(kBodyDataSize * 3));
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto timer = std::make_unique<MockTimer>();
   MockTimer* timer_ptr = timer.get();
   auto delegate = std::make_unique<TestDelegateBase>(
@@ -916,8 +910,7 @@
       net::HttpRequestHeaders::kContentLength,
       base::NumberToString(kBodyDataSize * 3));
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto timer = std::make_unique<MockTimer>();
   MockTimer* timer_ptr = timer.get();
   auto delegate = std::make_unique<TestDelegateBase>(
@@ -1007,8 +1000,7 @@
       net::HttpRequestHeaders::kContentLength,
       base::NumberToString(kBodyDataSize * 1));
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto timer = std::make_unique<MockTimer>();
   auto delegate = std::make_unique<TestDelegateBase>(
       read_buffer.get(), kReadBufferSize, std::move(timer));
@@ -1097,8 +1089,7 @@
   request_info->priority = LOWEST;
   request_info->end_stream_on_headers = true;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto timer = std::make_unique<MockTimer>();
   MockTimer* timer_ptr = timer.get();
   auto delegate = std::make_unique<TestDelegateBase>(
@@ -1158,8 +1149,7 @@
   request_info->priority = LOWEST;
   request_info->end_stream_on_headers = true;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto timer = std::make_unique<MockTimer>();
   MockTimer* timer_ptr = timer.get();
   auto delegate = std::make_unique<TestDelegateBase>(
@@ -1232,8 +1222,7 @@
 
   InitSession(reads, writes, SocketTag());
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto timer = std::make_unique<MockTimer>();
   MockTimer* timer_ptr = timer.get();
   auto delegate = std::make_unique<TestDelegateBase>(
@@ -1307,8 +1296,7 @@
       net::HttpRequestHeaders::kContentLength,
       base::NumberToString(kBodyDataSize * 3));
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->set_do_not_start_read(true);
@@ -1370,8 +1358,7 @@
       net::HttpRequestHeaders::kContentLength,
       base::NumberToString(kBodyDataSize * 3));
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->set_do_not_start_read(true);
@@ -1430,8 +1417,7 @@
       net::HttpRequestHeaders::kContentLength,
       base::NumberToString(kBodyDataSize * 3));
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->SetRunUntilCompletion(true);
@@ -1491,8 +1477,7 @@
   request_info->priority = LOWEST;
   request_info->end_stream_on_headers = true;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<DeleteStreamDelegate>(
       read_buffer.get(), kReadBufferSize,
       DeleteStreamDelegate::Phase::ON_HEADERS_RECEIVED);
@@ -1545,8 +1530,7 @@
   request_info->priority = LOWEST;
   request_info->end_stream_on_headers = true;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<DeleteStreamDelegate>(
       read_buffer.get(), kReadBufferSize,
       DeleteStreamDelegate::Phase::ON_DATA_READ);
@@ -1604,8 +1588,7 @@
   request_info->priority = LOWEST;
   request_info->end_stream_on_headers = true;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<DeleteStreamDelegate>(
       read_buffer.get(), kReadBufferSize,
       DeleteStreamDelegate::Phase::ON_TRAILERS_RECEIVED);
@@ -1655,8 +1638,7 @@
   request_info->priority = LOWEST;
   request_info->end_stream_on_headers = true;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<DeleteStreamDelegate>(
       read_buffer.get(), kReadBufferSize,
       DeleteStreamDelegate::Phase::ON_FAILED);
@@ -1709,8 +1691,7 @@
   request_info->priority = LOWEST;
   request_info->end_stream_on_headers = true;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto timer = std::make_unique<MockTimer>();
   auto delegate = std::make_unique<TestDelegateBase>(
       read_buffer.get(), kReadBufferSize, std::move(timer));
@@ -1766,8 +1747,7 @@
   request_info->extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
                                         base::NumberToString(kBodyDataSize));
   request_info->socket_tag = tag;
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->Start(std::move(request_info), http_session_.get());
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 30f86a9..b750c06 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -1544,7 +1544,7 @@
   TransitionToState(STATE_CACHE_READ_RESPONSE_COMPLETE);
 
   io_buf_len_ = entry_->GetEntry()->GetDataSize(kResponseInfoIndex);
-  read_buf_ = base::MakeRefCounted<IOBuffer>(io_buf_len_);
+  read_buf_ = base::MakeRefCounted<IOBufferWithSize>(io_buf_len_);
 
   net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_INFO);
   BeginDiskCacheAccessTimeCount();
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index f14a0adc..07abcf3 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -619,7 +619,7 @@
   // Set the last argument for this to be an incomplete request.
   EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(100);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(100);
   int len = static_cast<int>(base::strlcpy(buf->data(),
                                            "rg: 00-09 rg: 10-19 ", 100));
   TestCompletionCallback cb;
@@ -1385,7 +1385,7 @@
   ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
 
   const int kBufferSize = 10;
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(kBufferSize);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
   ReleaseBufferCompletionCallback cb(buffer.get());
 
   int rv = trans->Start(&request, cb.callback(), NetLogWithSource());
@@ -3204,8 +3204,7 @@
     // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
     // true.
     const int kBufferSize = 5;
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(kBufferSize);
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
     ReleaseBufferCompletionCallback cb(buffer.get());
     c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
     EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
@@ -3353,8 +3352,7 @@
     // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
     // true.
     const int kBufferSize = 5;
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(kBufferSize);
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
     ReleaseBufferCompletionCallback cb(buffer.get());
     c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
     EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
@@ -3448,8 +3446,7 @@
     base::RunLoop().RunUntilIdle();
 
     const int kBufferSize = 5;
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(kBufferSize);
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
     ReleaseBufferCompletionCallback cb(buffer.get());
     c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
     EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
@@ -3536,8 +3533,7 @@
     base::RunLoop().RunUntilIdle();
 
     const int kBufferSize = 5;
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(kBufferSize);
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
     ReleaseBufferCompletionCallback cb(buffer.get());
     c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
     EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
@@ -3612,8 +3608,7 @@
     // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
     // true.
     const int kBufferSize = 5;
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(kBufferSize);
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
     ReleaseBufferCompletionCallback cb(buffer.get());
     c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
     EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
@@ -3716,8 +3711,7 @@
     // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
     // true.
     const int kBufferSize = 10;
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(kBufferSize);
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
     ReleaseBufferCompletionCallback cb(buffer.get());
     c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
     EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
@@ -4458,7 +4452,7 @@
   result = callback.GetResult(result);
 
   // Read the first byte.
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(1);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(1);
   ReleaseBufferCompletionCallback buffer_callback(buffer.get());
   result = transaction->Read(buffer.get(), 1, buffer_callback.callback());
   EXPECT_EQ(1, buffer_callback.GetResult(result));
@@ -4469,7 +4463,7 @@
       mock_cache.disk_cache()->GetDiskEntryRef(cache_key);
   entry->SetDefer(MockDiskEntry::DEFER_WRITE);
 
-  buffer = base::MakeRefCounted<IOBuffer>(1);
+  buffer = base::MakeRefCounted<IOBufferWithSize>(1);
   ReleaseBufferCompletionCallback buffer_callback2(buffer.get());
   result = transaction->Read(buffer.get(), 1, buffer_callback2.callback());
   EXPECT_EQ(ERR_IO_PENDING, result);
@@ -4532,8 +4526,7 @@
   for (int i = 0; i < 2; i++) {
     auto& c = context_list[i];
     const int kBufferSize = 5;
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(kBufferSize);
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
     ReleaseBufferCompletionCallback cb(buffer.get());
     c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
     EXPECT_EQ(ERR_IO_PENDING, c->result);
@@ -4624,8 +4617,7 @@
   for (int i = 0; i < 2; i++) {
     auto& c = context_list[i];
     const int kBufferSize = 5;
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(kBufferSize);
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
     c->result =
         c->trans->Read(buffer.get(), kBufferSize, c->callback.callback());
     EXPECT_EQ(ERR_IO_PENDING, c->result);
@@ -4649,7 +4641,7 @@
   // Invoke Read on the 3rd transaction and it should get the error code back.
   auto& c = context_list[2];
   const int kBufferSize = 5;
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(kBufferSize);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
   c->result = c->trans->Read(buffer.get(), kBufferSize, c->callback.callback());
   EXPECT_EQ(ERR_INTERNET_DISCONNECTED, c->result);
 }
@@ -4702,7 +4694,7 @@
   en->Close();
   const int kBufferSize = 5;
   std::vector<scoped_refptr<IOBuffer>> buffer(
-      3, base::MakeRefCounted<IOBuffer>(kBufferSize));
+      3, base::MakeRefCounted<IOBufferWithSize>(kBufferSize));
   for (int i = 0; i < 2; i++) {
     auto& c = context_list[i];
     c->result =
@@ -4855,7 +4847,7 @@
   // Initiate Read from two writers.
   const int kBufferSize = 5;
   std::vector<scoped_refptr<IOBuffer>> buffer(
-      3, base::MakeRefCounted<IOBuffer>(kBufferSize));
+      3, base::MakeRefCounted<IOBufferWithSize>(kBufferSize));
   for (int i = 0; i < 2; i++) {
     auto& c = context_list[i];
     c->result =
@@ -4938,7 +4930,7 @@
   // Initiate Read from first transaction.
   const int kBufferSize = 5;
   std::vector<scoped_refptr<IOBuffer>> buffer(
-      kNumTransactions, base::MakeRefCounted<IOBuffer>(kBufferSize));
+      kNumTransactions, base::MakeRefCounted<IOBufferWithSize>(kBufferSize));
   auto& c = context_list[0];
   c->result =
       c->trans->Read(buffer[0].get(), kBufferSize, c->callback.callback());
@@ -5048,7 +5040,7 @@
 
   // Perform an extra Read.
   const int kBufferSize = 10;
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(kBufferSize);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
   c.result = c.trans->Read(buffer.get(), kBufferSize, c.callback.callback());
   EXPECT_EQ(0, c.result);
 }
@@ -5093,8 +5085,7 @@
   {
     auto& c = context_list[0];
     const int kBufferSize = 5;
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(kBufferSize);
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
     ReleaseBufferCompletionCallback cb(buffer.get());
     c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
     EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
@@ -5356,8 +5347,7 @@
     } else {
       // Read should lead to a failure being returned.
       const int kBufferSize = 5;
-      scoped_refptr<IOBuffer> buffer =
-          base::MakeRefCounted<IOBuffer>(kBufferSize);
+      auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
       ReleaseBufferCompletionCallback cb(buffer.get());
       c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
       EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, cb.GetResult(c->result));
@@ -5862,7 +5852,7 @@
     rv = callback.WaitForResult();
   ASSERT_THAT(rv, IsOk());
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
   rv = trans->Read(buf.get(), 256, callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
@@ -9461,7 +9451,7 @@
       HttpUtil::AssembleRawHeaders(raw_headers));
   EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
 
-  scoped_refptr<IOBuffer> buf(base::MakeRefCounted<IOBuffer>(500));
+  auto buf(base::MakeRefCounted<IOBufferWithSize>(500));
   int len = static_cast<int>(base::strlcpy(buf->data(),
                                            kRangeGET_TransactionOK.data, 500));
   TestCompletionCallback cb;
@@ -9507,7 +9497,7 @@
       HttpUtil::AssembleRawHeaders(raw_headers));
   EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(500);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(500);
   int len = static_cast<int>(base::strlcpy(buf->data(),
                                            kRangeGET_TransactionOK.data, 500));
   TestCompletionCallback cb;
@@ -9548,7 +9538,7 @@
       HttpUtil::AssembleRawHeaders(raw_headers));
   EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(500);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(500);
   int len = static_cast<int>(base::strlcpy(buf->data(),
                                            kRangeGET_TransactionOK.data, 500));
   TestCompletionCallback cb;
@@ -10489,7 +10479,7 @@
   rv = trans->Start(request.get(), cb.callback(), NetLogWithSource());
   EXPECT_EQ(0, cb.GetResult(rv));
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(10);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(10);
   rv = trans->Read(buf.get(), 10, cb.callback());
   EXPECT_EQ(10, cb.GetResult(rv));
 
@@ -10516,7 +10506,7 @@
   rv = trans->Start(request.get(), cb.callback(), NetLogWithSource());
   EXPECT_EQ(0, cb.GetResult(rv));
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(10);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(10);
   rv = trans->Read(buf.get(), 10, cb.callback());
   EXPECT_EQ(10, cb.GetResult(rv));
 
@@ -10879,7 +10869,7 @@
   EXPECT_THAT(c->callback.GetResult(rv), IsOk());
 
   // Read 20 bytes from the cache, and 10 from the net.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(100);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(100);
   rv = c->trans->Read(buf.get(), 20, c->callback.callback());
   EXPECT_EQ(20, c->callback.GetResult(rv));
   rv = c->trans->Read(buf.get(), 10, c->callback.callback());
@@ -11894,7 +11884,7 @@
     int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
     EXPECT_THAT(callback.GetResult(rv), IsOk());
 
-    scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
     rv = trans->Read(buf.get(), 256, callback.callback());
     EXPECT_GT(callback.GetResult(rv), 0);
 
@@ -11957,7 +11947,7 @@
     int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
     EXPECT_THAT(callback.GetResult(rv), IsOk());
 
-    scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
     rv = trans->Read(buf.get(), 10, callback.callback());
     EXPECT_EQ(10, callback.GetResult(rv));
 
@@ -11995,7 +11985,7 @@
     int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
     EXPECT_THAT(callback.GetResult(rv), IsOk());
 
-    scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
     rv = trans->Read(buf.get(), 10, callback.callback());
     EXPECT_EQ(10, callback.GetResult(rv));
 
@@ -12073,7 +12063,7 @@
     int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
     EXPECT_THAT(callback.GetResult(rv), IsOk());
 
-    scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
     rv = trans->Read(buf.get(), 10, callback.callback());
     EXPECT_EQ(callback.GetResult(rv), 10);
 
@@ -12116,7 +12106,7 @@
     int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
     EXPECT_THAT(callback.GetResult(rv), IsOk());
 
-    scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
     rv = trans->Read(buf.get(), 10, callback.callback());
     EXPECT_EQ(callback.GetResult(rv), 10);
 
@@ -12385,7 +12375,7 @@
     // to reduce the number of reads and speed up the test.
     const int kBufferSize = 1024 * 1024 * 10;
     scoped_refptr<net::IOBuffer> buf =
-        base::MakeRefCounted<net::IOBuffer>(kBufferSize);
+        base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
     rv = http_transaction->Read(buf.get(), kBufferSize, callback.callback());
     rv = callback.GetResult(rv);
 
diff --git a/net/http/http_cache_writers_unittest.cc b/net/http/http_cache_writers_unittest.cc
index ac93e6ef..46741443 100644
--- a/net/http/http_cache_writers_unittest.cc
+++ b/net/http/http_cache_writers_unittest.cc
@@ -183,8 +183,7 @@
     std::string content;
     int rv = 0;
     do {
-      scoped_refptr<IOBuffer> buf =
-          base::MakeRefCounted<IOBuffer>(kDefaultBufferSize);
+      auto buf = base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
       rv = writers_->Read(buf.get(), kDefaultBufferSize, callback.callback(),
                           transaction);
       if (rv == ERR_IO_PENDING) {
@@ -209,7 +208,7 @@
 
     std::string content;
     int rv = 0;
-    scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(5);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(5);
     rv = writers_->Read(buf.get(), 5, callback.callback(), transaction);
     if (rv == ERR_IO_PENDING) {
       rv = callback.WaitForResult();
@@ -240,7 +239,7 @@
 
     std::vector<scoped_refptr<IOBuffer>> bufs;
     for (auto buffer_length : buffer_lengths)
-      bufs.push_back(base::MakeRefCounted<IOBuffer>(buffer_length));
+      bufs.push_back(base::MakeRefCounted<IOBufferWithSize>(buffer_length));
 
     std::vector<TestCompletionCallback> callbacks(buffer_lengths.size());
 
@@ -299,7 +298,8 @@
       std::vector<TestCompletionCallback> callbacks(transactions_.size());
 
       for (size_t i = 0; i < transactions_.size(); i++) {
-        bufs.push_back(base::MakeRefCounted<IOBuffer>(kDefaultBufferSize));
+        bufs.push_back(
+            base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize));
 
         // If we have deleted a transaction in the first iteration, then do not
         // invoke Read on it, in subsequent iterations.
@@ -370,13 +370,13 @@
 
     // Read a few bytes so that truncation is possible.
     TestCompletionCallback callback;
-    scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(5);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(5);
     int rv = writers_->Read(buf.get(), 5, callback.callback(), transaction);
     EXPECT_EQ(ERR_IO_PENDING, rv);  // Since the default is asynchronous.
     EXPECT_EQ(5, callback.GetResult(rv));
 
     // Start reading a few more bytes and return.
-    buf = base::MakeRefCounted<IOBuffer>(5);
+    buf = base::MakeRefCounted<IOBufferWithSize>(5);
     rv = writers_->Read(buf.get(), 5, base::BindOnce([](int rv) {}),
                         transaction);
     EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -402,7 +402,7 @@
       en->Close();
 
       for (size_t i = 0; i < transactions_.size(); i++) {
-        bufs.push_back(base::MakeRefCounted<IOBuffer>(30));
+        bufs.push_back(base::MakeRefCounted<IOBufferWithSize>(30));
 
         if (!first_iter && i > 0)
           break;
@@ -435,7 +435,7 @@
     std::vector<TestCompletionCallback> callbacks(results->size());
 
     for (size_t i = 0; i < transactions_.size(); i++) {
-      bufs.push_back(base::MakeRefCounted<IOBuffer>(30));
+      bufs.push_back(base::MakeRefCounted<IOBufferWithSize>(30));
 
       rv = writers_->Read(bufs[i].get(), 30, callbacks[i].callback(),
                           transactions_[i].get());
@@ -476,8 +476,7 @@
     if (io_buf_len == 0)
       return false;
 
-    scoped_refptr<IOBuffer> read_buffer =
-        base::MakeRefCounted<IOBuffer>(io_buf_len);
+    auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(io_buf_len);
     int rv = disk_entry_->ReadData(kResponseInfoIndex, 0, read_buffer.get(),
                                    io_buf_len, callback.callback());
     rv = callback.GetResult(rv);
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index eb743d4..a522666a 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -385,7 +385,7 @@
     // it first.
     if (!stream_->IsResponseBodyComplete()) {
       next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
-      read_buf_ = base::MakeRefCounted<IOBuffer>(
+      read_buf_ = base::MakeRefCounted<IOBufferWithSize>(
           kDrainBodyBufferSize);  // A bit bucket.
       read_buf_len_ = kDrainBodyBufferSize;
       return;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 27a29143..6059328 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -7395,7 +7395,7 @@
   EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
 
   std::string response_data;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
   rv = trans.Read(buf.get(), 256, callback.callback());
   EXPECT_EQ(1, callback.GetResult(rv));
 
@@ -7523,7 +7523,7 @@
   EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
 
   std::string response_data;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
   EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
   trans.reset();
 
@@ -7628,7 +7628,7 @@
   EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
 
   std::string response_data;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
   rv = trans->Read(buf.get(), 256, callback.callback());
   EXPECT_EQ(1, callback.GetResult(rv));
   // Delete the first request, so the second one can reuse the socket.
@@ -10027,7 +10027,7 @@
         }
 
         case TestCase::kReadPartOfBodyRead: {
-          scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(5);
+          auto buf = base::MakeRefCounted<IOBufferWithSize>(5);
           rv = trans->Read(buf.get(), 5, callback.callback());
           ASSERT_EQ(5, callback.GetResult(rv));
           response_data.assign(buf->data(), 5);
@@ -11222,7 +11222,7 @@
   HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
 
   // Setup some state (which we expect ResetStateForRestart() will clear).
-  trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
+  trans.read_buf_ = base::MakeRefCounted<IOBufferWithSize>(15);
   trans.read_buf_len_ = 15;
   trans.request_headers_.SetHeader("Authorization", "NTLM");
 
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc
index f7b7df19..4ef02dad 100644
--- a/net/http/http_proxy_client_socket.cc
+++ b/net/http/http_proxy_client_socket.cc
@@ -226,7 +226,7 @@
   // If the auth request had a body, need to drain it before reusing the socket.
   if (!http_stream_parser_->IsResponseBodyComplete()) {
     next_state_ = STATE_DRAIN_BODY;
-    drain_buf_ = base::MakeRefCounted<IOBuffer>(kDrainBodyBufferSize);
+    drain_buf_ = base::MakeRefCounted<IOBufferWithSize>(kDrainBodyBufferSize);
     return OK;
   }
 
diff --git a/net/http/http_response_body_drainer.cc b/net/http/http_response_body_drainer.cc
index 76850120..e4c9ffe 100644
--- a/net/http/http_response_body_drainer.cc
+++ b/net/http/http_response_body_drainer.cc
@@ -26,7 +26,7 @@
 
 void HttpResponseBodyDrainer::Start(HttpNetworkSession* session) {
   session_ = session;
-  read_buf_ = base::MakeRefCounted<IOBuffer>(kDrainBodyBufferSize);
+  read_buf_ = base::MakeRefCounted<IOBufferWithSize>(kDrainBodyBufferSize);
   next_state_ = STATE_DRAIN_RESPONSE_BODY;
   int rv = DoLoop(OK);
 
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index c30c8783..b10949a5 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -2174,7 +2174,7 @@
                      nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
   delegate.WaitUntilDone();
 
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<net::IOBuffer>(1);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(1);
   EXPECT_THAT(stream_impl->ReadData(buffer.get(), 1), IsOk());
   EXPECT_EQ(kProtoQUIC, stream_impl->GetProtocol());
   EXPECT_EQ("200", delegate.response_headers().find(":status")->second);
@@ -2263,7 +2263,7 @@
   delegate.WaitUntilDone();
 
   // Make sure the BidirectionalStream negotiated goes through QUIC.
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<net::IOBuffer>(1);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(1);
   EXPECT_THAT(stream_impl->ReadData(buffer.get(), 1), IsOk());
   EXPECT_EQ(kProtoQUIC, stream_impl->GetProtocol());
   EXPECT_EQ("200", delegate.response_headers().find(":status")->second);
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc
index 3fd45a6..bbb365d 100644
--- a/net/http/http_stream_parser.cc
+++ b/net/http/http_stream_parser.cc
@@ -112,10 +112,10 @@
 // // size() == BytesRemaining() == BytesConsumed() == 0.
 // // data() points to the beginning of the buffer.
 //
-class HttpStreamParser::SeekableIOBuffer : public IOBuffer {
+class HttpStreamParser::SeekableIOBuffer : public IOBufferWithSize {
  public:
   explicit SeekableIOBuffer(int capacity)
-      : IOBuffer(capacity), real_data_(data_), capacity_(capacity) {}
+      : IOBufferWithSize(capacity), real_data_(data_), capacity_(capacity) {}
 
   // DidConsume() changes the |data_| pointer so that |data_| always points
   // to the first unconsumed byte.
@@ -245,8 +245,8 @@
   if (ShouldMergeRequestHeadersAndBody(request, request_->upload_data_stream)) {
     int merged_size = static_cast<int>(
         request_headers_length_ + request_->upload_data_stream->size());
-    scoped_refptr<IOBuffer> merged_request_headers_and_body =
-        base::MakeRefCounted<IOBuffer>(merged_size);
+    auto merged_request_headers_and_body =
+        base::MakeRefCounted<IOBufferWithSize>(merged_size);
     // We'll repurpose |request_headers_| to store the merged headers and
     // body.
     request_headers_ = base::MakeRefCounted<DrainableIOBuffer>(
diff --git a/net/http/http_stream_parser_unittest.cc b/net/http/http_stream_parser_unittest.cc
index f1fb696..2da347e 100644
--- a/net/http/http_stream_parser_unittest.cc
+++ b/net/http/http_stream_parser_unittest.cc
@@ -731,8 +731,7 @@
   ASSERT_THAT(callback.WaitForResult(), IsOk());
 
   // Finally, attempt to read the response body.
-  scoped_refptr<IOBuffer> body_buffer =
-      base::MakeRefCounted<IOBuffer>(kBodySize);
+  auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
   ASSERT_EQ(ERR_IO_PENDING,
             parser.ReadResponseBody(body_buffer.get(), kBodySize,
                                     callback.callback()));
@@ -808,8 +807,7 @@
   ASSERT_THAT(callback.WaitForResult(), IsOk());
 
   // Finally, attempt to read the response body.
-  scoped_refptr<IOBuffer> body_buffer =
-      base::MakeRefCounted<IOBuffer>(kBodySize);
+  auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
   ASSERT_EQ(ERR_IO_PENDING,
             parser.ReadResponseBody(body_buffer.get(), kBodySize,
                                     callback.callback()));
@@ -908,8 +906,7 @@
   ASSERT_THAT(callback.WaitForResult(), IsOk());
 
   // Finally, attempt to read the response body.
-  scoped_refptr<IOBuffer> body_buffer =
-      base::MakeRefCounted<IOBuffer>(kBodySize);
+  auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
   ASSERT_EQ(ERR_IO_PENDING,
             parser.ReadResponseBody(body_buffer.get(), kBodySize,
                                     callback.callback()));
@@ -985,8 +982,7 @@
   ASSERT_THAT(callback.WaitForResult(), IsOk());
 
   // Finally, attempt to read the response body.
-  scoped_refptr<IOBuffer> body_buffer =
-      base::MakeRefCounted<IOBuffer>(kBodySize);
+  auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
   ASSERT_EQ(ERR_IO_PENDING,
             parser.ReadResponseBody(body_buffer.get(), kBodySize,
                                     callback.callback()));
@@ -1061,8 +1057,7 @@
   ASSERT_THAT(callback.WaitForResult(), IsOk());
 
   // Finally, attempt to read the response body.
-  scoped_refptr<IOBuffer> body_buffer =
-      base::MakeRefCounted<IOBuffer>(kBodySize);
+  auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
   ASSERT_EQ(ERR_IO_PENDING,
             parser.ReadResponseBody(body_buffer.get(), kBodySize,
                                     callback.callback()));
@@ -1286,8 +1281,7 @@
 
   std::string ReadBody(int user_buf_len, int* read_lengths) {
     TestCompletionCallback callback;
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(user_buf_len);
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(user_buf_len);
     int rv;
     int i = 0;
     std::string body;
@@ -1747,8 +1741,8 @@
             first_response_start_time);
 
   // [seq=4] The parser reads the response body.
-  scoped_refptr<IOBuffer> body_buffer =
-      base::MakeRefCounted<IOBuffer>(response_body.size());
+  auto body_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(response_body.size());
   int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
                                        callback.callback());
   EXPECT_THAT(callback.GetResult(result), response_body.size());
@@ -1872,8 +1866,8 @@
             parser.non_informational_response_start_time());
 
   // [seq=8] The parser reads the non-informational response body.
-  scoped_refptr<IOBuffer> body_buffer =
-      base::MakeRefCounted<IOBuffer>(response_body.size());
+  auto body_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(response_body.size());
   int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
                                        callback.callback());
   EXPECT_THAT(callback.GetResult(result), response_body.size());
@@ -2013,8 +2007,8 @@
             parser.non_informational_response_start_time());
 
   // [seq=10] The parser reads the non-informational response body.
-  scoped_refptr<IOBuffer> body_buffer =
-      base::MakeRefCounted<IOBuffer>(response_body.size());
+  auto body_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(response_body.size());
   int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
                                        callback.callback());
   EXPECT_THAT(callback.GetResult(result), response_body.size());
@@ -2130,8 +2124,8 @@
             parser.non_informational_response_start_time());
 
   // [seq=6] The parser reads the non-informational response body.
-  scoped_refptr<IOBuffer> body_buffer =
-      base::MakeRefCounted<IOBuffer>(response_body.size());
+  auto body_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(response_body.size());
   int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
                                        callback.callback());
   EXPECT_THAT(callback.GetResult(result), response_body.size());
@@ -2186,8 +2180,7 @@
   request_headers.reset();
   response_info.reset();
 
-  scoped_refptr<IOBuffer> body_buffer =
-      base::MakeRefCounted<IOBuffer>(kBodySize);
+  auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
   ASSERT_EQ(kBodySize, parser.ReadResponseBody(
       body_buffer.get(), kBodySize, callback.callback()));
 
diff --git a/net/http/http_transaction_test_util.cc b/net/http/http_transaction_test_util.cc
index e8fbac2..4b1835da 100644
--- a/net/http/http_transaction_test_util.cc
+++ b/net/http/http_transaction_test_util.cc
@@ -273,7 +273,7 @@
 
 void TestTransactionConsumer::Read() {
   state_ = State::kReading;
-  read_buf_ = base::MakeRefCounted<IOBuffer>(1024);
+  read_buf_ = base::MakeRefCounted<IOBufferWithSize>(1024);
   int result =
       trans_->Read(read_buf_.get(), 1024,
                    base::BindOnce(&TestTransactionConsumer::OnIOComplete,
@@ -668,7 +668,7 @@
   std::string content;
   do {
     TestCompletionCallback callback;
-    scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
     rv = trans->Read(buf.get(), 256, callback.callback());
     if (rv == ERR_IO_PENDING) {
       rv = callback.WaitForResult();
diff --git a/net/http/mock_http_cache.cc b/net/http/mock_http_cache.cc
index 99d61819..d734af5 100644
--- a/net/http/mock_http_cache.cc
+++ b/net/http/mock_http_cache.cc
@@ -698,7 +698,7 @@
   int size = disk_entry->GetDataSize(0);
 
   TestCompletionCallback cb;
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(size);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(size);
   int rv = disk_entry->ReadData(0, 0, buffer.get(), size, cb.callback());
   rv = cb.GetResult(rv);
   EXPECT_EQ(size, rv);
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h
index 8038dfc..ec02c4b 100644
--- a/net/log/net_log_event_type_list.h
+++ b/net/log/net_log_event_type_list.h
@@ -3256,12 +3256,12 @@
 //   }
 EVENT_TYPE(CERT_VERIFIER_TASK_BOUND)
 
+// This event is created when a CertVerifyProc instance is created.
+EVENT_TYPE(CERT_VERIFY_PROC_CREATED)
+
 // This event is created when CertVerifyProc is verifying a certificate.
 // The BEGIN phase event parameters are:
 // {
-//   "additional_trust_anchors": <Optionally, a list of PEM encoded
-//                                certificates to be used as trust anchors
-//                                in addition to the trust store.>
 //   "certificates": <A list of PEM encoded certificates, the first one
 //                    being the certificate to verify and the remaining
 //                    being intermediate certificates to assist path
@@ -3334,10 +3334,16 @@
 //   }
 EVENT_TYPE(CERT_VERIFY_PROC_CHROME_ROOT_STORE_VERSION)
 
-// This event is created for each additional trust anchor passed into
+// This event is created for each additional certificate added to
 // CertVerifyProcBuiltin.
-// The parameters are the same as for CERT_VERIFY_PROC_TARGET_CERT.
-EVENT_TYPE(CERT_VERIFY_PROC_ADDITIONAL_TRUST_ANCHOR)
+// The event parameters are:
+//   {
+//      "certificate": <The PEM encoded certificate.>
+//      "trust": <The trust setting used for this certificate.>
+//      "errors": <Optionally, a string describing any errors or warnings
+//                 encountered while parsing the certificate.>
+//   }
+EVENT_TYPE(CERT_VERIFY_PROC_ADDITIONAL_CERT)
 
 // This event is created for each path building attempt performed by
 // CertVerifyProcBuiltin.
diff --git a/net/log/net_log_source_type_list.h b/net/log/net_log_source_type_list.h
index a92dbfd..df3c2b0 100644
--- a/net/log/net_log_source_type_list.h
+++ b/net/log/net_log_source_type_list.h
@@ -28,6 +28,7 @@
 SOURCE_TYPE(HTTP_STREAM_JOB)
 SOURCE_TYPE(EXPONENTIAL_BACKOFF_THROTTLING)
 SOURCE_TYPE(UDP_SOCKET)
+SOURCE_TYPE(CERT_VERIFY_PROC_CREATED)
 SOURCE_TYPE(CERT_VERIFIER_JOB)
 SOURCE_TYPE(CERT_VERIFIER_TASK)
 SOURCE_TYPE(PROXY_CLIENT_SOCKET)
diff --git a/net/proxy_resolution/pac_file_fetcher_impl.cc b/net/proxy_resolution/pac_file_fetcher_impl.cc
index 485dd7a..e13fb8d 100644
--- a/net/proxy_resolution/pac_file_fetcher_impl.cc
+++ b/net/proxy_resolution/pac_file_fetcher_impl.cc
@@ -316,7 +316,7 @@
 
 PacFileFetcherImpl::PacFileFetcherImpl(URLRequestContext* url_request_context)
     : url_request_context_(url_request_context),
-      buf_(base::MakeRefCounted<IOBuffer>(kBufSize)),
+      buf_(base::MakeRefCounted<IOBufferWithSize>(kBufSize)),
       max_response_bytes_(kDefaultMaxResponseBytes),
       max_duration_(kDefaultMaxDuration) {
   DCHECK(url_request_context);
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc
index c95b532..3c4fbb7 100644
--- a/net/quic/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -820,8 +820,7 @@
   request.end_stream_on_headers = true;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->set_trailers_expected(true);
@@ -921,16 +920,14 @@
   request.priority = DEFAULT_PRIORITY;
 
   // Start first request.
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->Start(&request, net_log_with_source(),
                   session()->CreateHandle(destination_));
 
   // Start second request.
-  scoped_refptr<IOBuffer> read_buffer2 =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer2 = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate2 =
       std::make_unique<TestDelegateBase>(read_buffer2.get(), kReadBufferSize);
   delegate2->Start(&request, net_log_with_source(),
@@ -1007,8 +1004,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->DoNotSendRequestHeadersAutomatically();
@@ -1121,8 +1117,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->DoNotSendRequestHeadersAutomatically();
@@ -1228,8 +1223,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->DoNotSendRequestHeadersAutomatically();
@@ -1325,8 +1319,7 @@
   request.priority = DEFAULT_PRIORITY;
   request.extra_headers.SetHeader("cookie", std::string(2048, 'A'));
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<DeleteStreamDelegate>(
       read_buffer.get(), kReadBufferSize, DeleteStreamDelegate::ON_FAILED);
   delegate->DoNotSendRequestHeadersAutomatically();
@@ -1361,8 +1354,7 @@
   request.priority = DEFAULT_PRIORITY;
   request.extra_headers.SetHeader("cookie", std::string(2048, 'A'));
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<DeleteStreamDelegate>(
       read_buffer.get(), kReadBufferSize, DeleteStreamDelegate::ON_FAILED);
   delegate->DoNotSendRequestHeadersAutomatically();
@@ -1406,8 +1398,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->Start(&request, net_log_with_source(),
@@ -1487,8 +1478,7 @@
   request.end_stream_on_headers = true;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->set_trailers_expected(true);
@@ -1590,8 +1580,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->Start(&request, net_log_with_source(),
@@ -1681,8 +1670,7 @@
   request.end_stream_on_headers = true;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->Start(&request, net_log_with_source(),
@@ -1733,8 +1721,7 @@
   request.end_stream_on_headers = true;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->Start(&request, net_log_with_source(),
@@ -1797,8 +1784,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->Start(&request, net_log_with_source(),
@@ -1856,8 +1842,7 @@
   session()->connection()->CloseConnection(
       quic::QUIC_NO_ERROR, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE);
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->Start(&request, net_log_with_source(),
@@ -1880,8 +1865,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->Start(&request, net_log_with_source(),
@@ -1905,8 +1889,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<DeleteStreamDelegate>(
       read_buffer.get(), kReadBufferSize, DeleteStreamDelegate::ON_FAILED);
   delegate->Start(&request, net_log_with_source(),
@@ -1937,8 +1920,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<DeleteStreamDelegate>(
       read_buffer.get(), kReadBufferSize,
       DeleteStreamDelegate::ON_STREAM_READY);
@@ -1970,8 +1952,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->Start(&request, net_log_with_source(),
@@ -2027,8 +2008,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<DeleteStreamDelegate>(
       read_buffer.get(), kReadBufferSize,
       DeleteStreamDelegate::ON_HEADERS_RECEIVED);
@@ -2077,8 +2057,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<DeleteStreamDelegate>(
       read_buffer.get(), kReadBufferSize, DeleteStreamDelegate::ON_DATA_READ);
   delegate->Start(&request, net_log_with_source(),
@@ -2138,8 +2117,7 @@
   request.end_stream_on_headers = false;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
 
@@ -2206,8 +2184,7 @@
   request.end_stream_on_headers = true;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<DeleteStreamDelegate>(
       read_buffer.get(), kReadBufferSize,
       DeleteStreamDelegate::ON_TRAILERS_RECEIVED);
@@ -2275,8 +2252,7 @@
   request.end_stream_on_headers = true;
   request.priority = DEFAULT_PRIORITY;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate =
       std::make_unique<TestDelegateBase>(read_buffer.get(), kReadBufferSize);
   delegate->set_trailers_expected(true);
diff --git a/net/quic/quic_chromium_client_stream_test.cc b/net/quic/quic_chromium_client_stream_test.cc
index 787eed15..db2b931 100644
--- a/net/quic/quic_chromium_client_stream_test.cc
+++ b/net/quic/quic_chromium_client_stream_test.cc
@@ -222,8 +222,8 @@
   }
 
   void ReadData(std::string_view expected_data) {
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(expected_data.length() + 1);
+    auto buffer =
+        base::MakeRefCounted<IOBufferWithSize>(expected_data.length() + 1);
     EXPECT_EQ(static_cast<int>(expected_data.length()),
               stream_->Read(buffer.get(), expected_data.length() + 1));
     EXPECT_EQ(expected_data,
@@ -351,7 +351,7 @@
                                      callback.callback()));
 
   std::vector<scoped_refptr<IOBuffer>> buffers = {
-      base::MakeRefCounted<IOBuffer>(10)};
+      base::MakeRefCounted<IOBufferWithSize>(10)};
   std::vector<int> lengths = {10};
   EXPECT_EQ(
       ERR_CONNECTION_CLOSED,
@@ -426,7 +426,7 @@
 
   // Read the body and verify that it arrives correctly.
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(2 * data_len);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
   EXPECT_EQ(data_len,
             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
   EXPECT_EQ(std::string_view(data), std::string_view(buffer->data(), data_len));
@@ -441,7 +441,7 @@
 
   // Start to read the body.
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(2 * data_len);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
   EXPECT_EQ(ERR_IO_PENDING,
             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
 
@@ -492,7 +492,7 @@
 
   // Start to read the body.
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(2 * data_len);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
   EXPECT_EQ(
       ERR_IO_PENDING,
       handle_->ReadBody(
@@ -553,7 +553,7 @@
 
   // Read the body and verify that it arrives correctly.
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(2 * data_len);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
   EXPECT_EQ(data_len,
             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
   EXPECT_EQ(std::string_view(data), std::string_view(buffer->data(), data_len));
@@ -600,7 +600,7 @@
 
   // Read the body and verify that it arrives correctly.
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(2 * data_len);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
   EXPECT_EQ(data_len,
             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
   EXPECT_EQ(std::string_view(data), std::string_view(buffer->data(), data_len));
@@ -654,7 +654,7 @@
 
   // Read the body and verify that it arrives correctly.
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(2 * data_len);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(2 * data_len);
   EXPECT_EQ(data_len,
             handle_->ReadBody(buffer.get(), 2 * data_len, callback.callback()));
   EXPECT_EQ(std::string_view(data), std::string_view(buffer->data(), data_len));
@@ -869,7 +869,7 @@
 
   // Now explicitly read the data.
   int data_len = std::size(data) - 1;
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(data_len + 1);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(data_len + 1);
   ASSERT_EQ(data_len, stream2->Read(buffer.get(), data_len + 1));
   EXPECT_EQ(std::string_view(data), std::string_view(buffer->data(), data_len));
 }
diff --git a/net/quic/quic_chromium_packet_writer.cc b/net/quic/quic_chromium_packet_writer.cc
index 47c4489..4964b544 100644
--- a/net/quic/quic_chromium_packet_writer.cc
+++ b/net/quic/quic_chromium_packet_writer.cc
@@ -70,7 +70,7 @@
 }  // namespace
 
 QuicChromiumPacketWriter::ReusableIOBuffer::ReusableIOBuffer(size_t capacity)
-    : IOBuffer(capacity), capacity_(capacity) {}
+    : IOBufferWithSize(capacity), capacity_(capacity) {}
 
 QuicChromiumPacketWriter::ReusableIOBuffer::~ReusableIOBuffer() = default;
 
diff --git a/net/quic/quic_chromium_packet_writer.h b/net/quic/quic_chromium_packet_writer.h
index 63e2bf6c..9694705 100644
--- a/net/quic/quic_chromium_packet_writer.h
+++ b/net/quic/quic_chromium_packet_writer.h
@@ -31,7 +31,7 @@
   // repeated memory allocations.  This packet writer only ever has a
   // single write in flight, a constraint inherited from the interface
   // of the underlying datagram Socket.
-  class NET_EXPORT_PRIVATE ReusableIOBuffer : public IOBuffer {
+  class NET_EXPORT_PRIVATE ReusableIOBuffer : public IOBufferWithSize {
    public:
     explicit ReusableIOBuffer(size_t capacity);
 
diff --git a/net/quic/quic_proxy_client_socket_unittest.cc b/net/quic/quic_proxy_client_socket_unittest.cc
index fb9168ab..6fcfb9a 100644
--- a/net/quic/quic_proxy_client_socket_unittest.cc
+++ b/net/quic/quic_proxy_client_socket_unittest.cc
@@ -514,8 +514,7 @@
   }
 
   void AssertWriteReturns(const char* data, int len, int rv) {
-    scoped_refptr<IOBufferWithSize> buf =
-        base::MakeRefCounted<IOBufferWithSize>(len);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(len);
     memcpy(buf->data(), data, len);
     EXPECT_EQ(rv,
               sock_->Write(buf.get(), buf->size(), write_callback_.callback(),
@@ -523,8 +522,7 @@
   }
 
   void AssertSyncWriteSucceeds(const char* data, int len) {
-    scoped_refptr<IOBufferWithSize> buf =
-        base::MakeRefCounted<IOBufferWithSize>(len);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(len);
     memcpy(buf->data(), data, len);
     EXPECT_EQ(len,
               sock_->Write(buf.get(), buf->size(), CompletionOnceCallback(),
@@ -532,14 +530,14 @@
   }
 
   void AssertSyncReadEquals(const char* data, int len) {
-    scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(len);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(len);
     ASSERT_EQ(len, sock_->Read(buf.get(), len, CompletionOnceCallback()));
     ASSERT_EQ(std::string(data, len), std::string(buf->data(), len));
     ASSERT_TRUE(sock_->IsConnected());
   }
 
   void AssertAsyncReadEquals(const char* data, int len) {
-    scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(len);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(len);
     ASSERT_EQ(ERR_IO_PENDING,
               sock_->Read(buf.get(), len, read_callback_.callback()));
     EXPECT_TRUE(sock_->IsConnected());
@@ -553,7 +551,7 @@
 
   void AssertReadStarts(const char* data, int len) {
     // Issue the read, which will be completed asynchronously.
-    read_buf_ = base::MakeRefCounted<IOBuffer>(len);
+    read_buf_ = base::MakeRefCounted<IOBufferWithSize>(len);
     ASSERT_EQ(ERR_IO_PENDING,
               sock_->Read(read_buf_.get(), len, read_callback_.callback()));
     EXPECT_TRUE(sock_->IsConnected());
@@ -1300,7 +1298,7 @@
   AssertSyncReadEquals(kMsg33, kLen33);
 
   // Now attempt to do a read of more data than remains buffered
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kLen33);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kLen33);
   ASSERT_EQ(kLen3, sock_->Read(buf.get(), kLen33, CompletionOnceCallback()));
   ASSERT_EQ(std::string(kMsg3, kLen3), std::string(buf->data(), kLen3));
   ASSERT_TRUE(sock_->IsConnected());
@@ -1894,7 +1892,7 @@
   EXPECT_TRUE(sock_->IsConnected());
 
   DeleteSockCallback read_callback(&sock_);
-  scoped_refptr<IOBuffer> read_buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   ASSERT_EQ(ERR_IO_PENDING,
             sock_->Read(read_buf.get(), kLen1, read_callback.callback()));
 
diff --git a/net/quic/quic_stream_factory_fuzzer.cc b/net/quic/quic_stream_factory_fuzzer.cc
index e181cdc..53b0557d 100644
--- a/net/quic/quic_stream_factory_fuzzer.cc
+++ b/net/quic/quic_stream_factory_fuzzer.cc
@@ -196,8 +196,7 @@
   }
   callback.WaitForResult();
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(kBufferSize);
+  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
   rv = stream->ReadResponseBody(buffer.get(), kBufferSize, callback.callback());
   if (rv == ERR_IO_PENDING)
     callback.WaitForResult();
diff --git a/net/socket/sequenced_socket_data_unittest.cc b/net/socket/sequenced_socket_data_unittest.cc
index bf1e4cd..7fefb26 100644
--- a/net/socket/sequenced_socket_data_unittest.cc
+++ b/net/socket/sequenced_socket_data_unittest.cc
@@ -56,7 +56,7 @@
   // |first_read_data_| with |first_read_data|.
   void SetExpectedRead(const char* first_read_data, int first_len) {
     verify_read_ = true;
-    first_read_buf_ = base::MakeRefCounted<IOBuffer>(first_len);
+    first_read_buf_ = base::MakeRefCounted<IOBufferWithSize>(first_len);
     first_read_data_ = first_read_data;
     first_len_ = first_len;
   }
@@ -117,8 +117,7 @@
       ASSERT_EQ(second_rv_, socket_->Read(second_read_buf_.get(), second_len_,
                                           std::move(second_callback_)));
     } else {
-      scoped_refptr<IOBuffer> write_buf =
-          base::MakeRefCounted<IOBuffer>(second_len_);
+      auto write_buf = base::MakeRefCounted<IOBufferWithSize>(second_len_);
       memcpy(write_buf->data(), second_write_data_, second_len_);
       ASSERT_EQ(second_rv_, socket_->Write(write_buf.get(), second_len_,
                                            std::move(second_callback_),
@@ -268,7 +267,7 @@
 }
 
 void SequencedSocketDataTest::AssertReadReturns(int len, int rv) {
-  read_buf_ = base::MakeRefCounted<IOBuffer>(len);
+  read_buf_ = base::MakeRefCounted<IOBufferWithSize>(len);
   if (rv == ERR_IO_PENDING) {
     ASSERT_EQ(rv, sock_->Read(read_buf_.get(), len, read_callback_.callback()));
     ASSERT_FALSE(read_callback_.have_result());
@@ -314,7 +313,7 @@
 void SequencedSocketDataTest::AssertWriteReturns(const char* data,
                                                  int len,
                                                  int rv) {
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(len);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(len);
   memcpy(buf->data(), data, len);
 
   if (rv == ERR_IO_PENDING) {
@@ -363,7 +362,7 @@
     int expected_rv,
     int rv) {
   EXPECT_EQ(expected_rv, rv);
-  scoped_refptr<IOBuffer> write_buf = base::MakeRefCounted<IOBuffer>(len);
+  auto write_buf = base::MakeRefCounted<IOBufferWithSize>(len);
   memcpy(write_buf->data(), data, len);
   EXPECT_THAT(sock_->Write(write_buf.get(), len, std::move(callback),
                            TRAFFIC_ANNOTATION_FOR_TESTS),
@@ -468,7 +467,7 @@
 
   Initialize(reads, base::span<MockWrite>());
 
-  read_buf_ = base::MakeRefCounted<IOBuffer>(kLen1);
+  read_buf_ = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   ASSERT_EQ(
       ERR_IO_PENDING,
       sock_->Read(
@@ -490,7 +489,7 @@
 
   Initialize(reads, base::span<MockWrite>());
 
-  read_buf_ = base::MakeRefCounted<IOBuffer>(kLen4);
+  read_buf_ = base::MakeRefCounted<IOBufferWithSize>(kLen4);
 
   ReentrantHelper helper3(sock_.get());
   helper3.SetExpectedRead(kMsg3, kLen3);
@@ -520,7 +519,7 @@
 
   Initialize(reads, base::span<MockWrite>());
 
-  read_buf_ = base::MakeRefCounted<IOBuffer>(kLen1);
+  read_buf_ = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   ASSERT_EQ(ERR_IO_PENDING,
             sock_->Read(
                 read_buf_.get(), kLen1,
@@ -568,7 +567,7 @@
   };
 
   Initialize(reads, base::span<MockWrite>());
-  scoped_refptr<IOBuffer> read_buf = base::MakeRefCounted<IOBuffer>(2 * kLen1);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(2 * kLen1);
   ASSERT_EQ(kLen1, sock_->Read(read_buf.get(), 2 * kLen1, failing_callback()));
   ASSERT_EQ(std::string(kMsg1, kLen1), std::string(read_buf->data(), kLen1));
 }
@@ -580,7 +579,7 @@
 
   Initialize(reads, base::span<MockWrite>());
 
-  scoped_refptr<IOBuffer> read_buf = base::MakeRefCounted<IOBuffer>(2 * kLen1);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(2 * kLen1);
   ASSERT_EQ(ERR_IO_PENDING,
             sock_->Read(read_buf.get(), 2 * kLen1, read_callback_.callback()));
   ASSERT_EQ(kLen1, read_callback_.WaitForResult());
@@ -594,7 +593,7 @@
 
   Initialize(reads, base::span<MockWrite>());
 
-  scoped_refptr<IOBuffer> read_buf = base::MakeRefCounted<IOBuffer>(1);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(1);
   ASSERT_EQ(ERR_IO_PENDING,
             sock_->Read(read_buf.get(), 1, read_callback_.callback()));
   ASSERT_FALSE(read_callback_.have_result());
@@ -772,7 +771,7 @@
 
   Initialize(base::span<MockRead>(), writes);
 
-  scoped_refptr<IOBuffer> write_buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto write_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   memcpy(write_buf->data(), kMsg1, kLen1);
   ASSERT_EQ(
       ERR_IO_PENDING,
@@ -792,7 +791,7 @@
 
   Initialize(base::span<MockRead>(), writes);
 
-  scoped_refptr<IOBuffer> write_buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto write_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   memcpy(write_buf->data(), kMsg1, kLen1);
   ASSERT_EQ(ERR_IO_PENDING,
             sock_->Write(
@@ -829,7 +828,7 @@
   helper.SetExpectedWrite(kLen1);
   helper.SetInvokeWrite(kMsg2, kLen2, ERR_IO_PENDING, helper2.callback());
 
-  scoped_refptr<IOBuffer> write_buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto write_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   memcpy(write_buf->data(), kMsg1, kLen1);
   sock_->Write(write_buf.get(), kLen1, helper.callback(),
                TRAFFIC_ANNOTATION_FOR_TESTS);
@@ -970,7 +969,7 @@
 
   Initialize(reads, writes);
 
-  scoped_refptr<IOBuffer> write_buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto write_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   memcpy(write_buf->data(), kMsg1, kLen1);
   ASSERT_EQ(
       ERR_IO_PENDING,
@@ -996,7 +995,7 @@
 
   Initialize(reads, writes);
 
-  scoped_refptr<IOBuffer> read_buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   ASSERT_EQ(
       ERR_IO_PENDING,
       sock_->Read(
@@ -1020,7 +1019,7 @@
 
   Initialize(reads, writes);
 
-  read_buf_ = base::MakeRefCounted<IOBuffer>(kLen4);
+  read_buf_ = base::MakeRefCounted<IOBufferWithSize>(kLen4);
 
   ReentrantHelper helper3(sock_.get());
   helper3.SetExpectedWrite(kLen3);
@@ -1036,7 +1035,7 @@
   helper.SetInvokeRead(helper2.read_buf(), kLen2, ERR_IO_PENDING,
                        helper2.callback());
 
-  scoped_refptr<IOBuffer> write_buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto write_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   memcpy(write_buf->data(), kMsg1, kLen1);
   sock_->Write(write_buf.get(), kLen1, helper.callback(),
                TRAFFIC_ANNOTATION_FOR_TESTS);
@@ -1055,7 +1054,7 @@
 
   Initialize(reads, writes);
 
-  read_buf_ = base::MakeRefCounted<IOBuffer>(kLen4);
+  read_buf_ = base::MakeRefCounted<IOBufferWithSize>(kLen4);
 
   ReentrantHelper helper3(sock_.get());
   helper3.SetExpectedWrite(kLen3);
@@ -1070,7 +1069,7 @@
   helper.SetInvokeRead(helper2.read_buf(), kLen2, ERR_IO_PENDING,
                        helper2.callback());
 
-  scoped_refptr<IOBuffer> write_buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto write_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   memcpy(write_buf->data(), kMsg1, kLen1);
   ASSERT_EQ(ERR_IO_PENDING,
             sock_->Write(write_buf.get(), kLen1, helper.callback(),
@@ -1092,7 +1091,7 @@
 
   Initialize(reads, writes);
 
-  read_buf_ = base::MakeRefCounted<IOBuffer>(kLen4);
+  read_buf_ = base::MakeRefCounted<IOBufferWithSize>(kLen4);
 
   ReentrantHelper helper3(sock_.get());
   helper3.SetExpectedRead(kMsg3, kLen3);
diff --git a/net/socket/socket_bio_adapter.cc b/net/socket/socket_bio_adapter.cc
index 4126ea3..34af2f11 100644
--- a/net/socket/socket_bio_adapter.cc
+++ b/net/socket/socket_bio_adapter.cc
@@ -123,7 +123,8 @@
     // reused after shutdown for non-SSL traffic, so overreading is fine.
     CHECK(!read_buffer_);
     CHECK_EQ(0, read_offset_);
-    read_buffer_ = base::MakeRefCounted<IOBuffer>(read_buffer_capacity_);
+    read_buffer_ =
+        base::MakeRefCounted<IOBufferWithSize>(read_buffer_capacity_);
     read_result_ = ERR_IO_PENDING;
     int result = socket_->ReadIfReady(
         read_buffer_.get(), read_buffer_capacity_,
diff --git a/net/socket/socks5_client_socket.cc b/net/socket/socks5_client_socket.cc
index 36a69f4..6b986a8b 100644
--- a/net/socket/socks5_client_socket.cc
+++ b/net/socket/socks5_client_socket.cc
@@ -276,7 +276,7 @@
 
   next_state_ = STATE_GREET_WRITE_COMPLETE;
   size_t handshake_buf_len = buffer_.size() - bytes_sent_;
-  handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
+  handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
   memcpy(handshake_buf_->data(), &buffer_.data()[bytes_sent_],
          handshake_buf_len);
   return transport_socket_->Write(handshake_buf_.get(), handshake_buf_len,
@@ -301,7 +301,7 @@
 int SOCKS5ClientSocket::DoGreetRead() {
   next_state_ = STATE_GREET_READ_COMPLETE;
   size_t handshake_buf_len = kGreetReadHeaderSize - bytes_received_;
-  handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
+  handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
   return transport_socket_->Read(handshake_buf_.get(), handshake_buf_len,
                                  io_callback_);
 }
@@ -374,7 +374,7 @@
 
   int handshake_buf_len = buffer_.size() - bytes_sent_;
   DCHECK_LT(0, handshake_buf_len);
-  handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
+  handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
   memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
          handshake_buf_len);
   return transport_socket_->Write(handshake_buf_.get(), handshake_buf_len,
@@ -410,7 +410,7 @@
   }
 
   int handshake_buf_len = read_header_size - bytes_received_;
-  handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
+  handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
   return transport_socket_->Read(handshake_buf_.get(), handshake_buf_len,
                                  io_callback_);
 }
diff --git a/net/socket/socks5_client_socket_unittest.cc b/net/socket/socks5_client_socket_unittest.cc
index 768a50f..bb4ab76 100644
--- a/net/socket/socks5_client_socket_unittest.cc
+++ b/net/socket/socks5_client_socket_unittest.cc
@@ -158,8 +158,7 @@
   EXPECT_TRUE(LogContainsEndEvent(net_log_entries, -1,
                                   NetLogEventType::SOCKS5_CONNECT));
 
-  scoped_refptr<IOBuffer> buffer =
-      base::MakeRefCounted<IOBuffer>(payload_write.size());
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(payload_write.size());
   memcpy(buffer->data(), payload_write.data(), payload_write.size());
   rv = user_sock_->Write(buffer.get(), payload_write.size(),
                          callback_.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
@@ -167,7 +166,7 @@
   rv = callback_.WaitForResult();
   EXPECT_EQ(static_cast<int>(payload_write.size()), rv);
 
-  buffer = base::MakeRefCounted<IOBuffer>(payload_read.size());
+  buffer = base::MakeRefCounted<IOBufferWithSize>(payload_read.size());
   rv =
       user_sock_->Read(buffer.get(), payload_read.size(), callback_.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
diff --git a/net/socket/socks_client_socket.cc b/net/socket/socks_client_socket.cc
index e280e63..89b3efcf 100644
--- a/net/socket/socks_client_socket.cc
+++ b/net/socket/socks_client_socket.cc
@@ -364,7 +364,7 @@
 
   int handshake_buf_len = buffer_.size() - bytes_sent_;
   DCHECK_GT(handshake_buf_len, 0);
-  handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
+  handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
   memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
          handshake_buf_len);
   return transport_socket_->Write(
@@ -401,7 +401,7 @@
   }
 
   int handshake_buf_len = kReadHeaderSize - bytes_received_;
-  handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
+  handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
   return transport_socket_->Read(
       handshake_buf_.get(), handshake_buf_len,
       base::BindOnce(&SOCKSClientSocket::OnIOComplete, base::Unretained(this)));
diff --git a/net/socket/socks_client_socket_unittest.cc b/net/socket/socks_client_socket_unittest.cc
index 5dca004..31fb90c 100644
--- a/net/socket/socks_client_socket_unittest.cc
+++ b/net/socket/socks_client_socket_unittest.cc
@@ -137,8 +137,7 @@
     EXPECT_TRUE(
         LogContainsEndEvent(entries, -1, NetLogEventType::SOCKS_CONNECT));
 
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<IOBuffer>(payload_write.size());
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(payload_write.size());
     memcpy(buffer->data(), payload_write.data(), payload_write.size());
     rv = user_sock_->Write(buffer.get(), payload_write.size(),
                            callback_.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
@@ -146,7 +145,7 @@
     rv = callback_.WaitForResult();
     EXPECT_EQ(static_cast<int>(payload_write.size()), rv);
 
-    buffer = base::MakeRefCounted<IOBuffer>(payload_read.size());
+    buffer = base::MakeRefCounted<IOBufferWithSize>(payload_read.size());
     if (use_read_if_ready) {
       rv = user_sock_->ReadIfReady(buffer.get(), payload_read.size(),
                                    callback_.callback());
@@ -192,7 +191,7 @@
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(user_sock_->IsConnected());
 
-  auto buffer = base::MakeRefCounted<IOBuffer>(payload_read.size());
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(payload_read.size());
   rv = user_sock_->ReadIfReady(buffer.get(), payload_read.size(),
                                callback_.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index beb82d41..09b0434 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -363,7 +363,7 @@
     read_if_ready_buf_.clear();
     return rv;
   }
-  scoped_refptr<IOBuffer> buf_copy = base::MakeRefCounted<IOBuffer>(len);
+  auto buf_copy = base::MakeRefCounted<IOBufferWithSize>(len);
   int rv = Read(buf_copy.get(), len,
                 base::BindOnce(&FakeBlockingStreamSocket::CompleteReadIfReady,
                                base::Unretained(this), buf_copy));
@@ -1132,8 +1132,8 @@
       const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
       static const int kRequestTextSize =
           static_cast<int>(std::size(request_text) - 1);
-      scoped_refptr<IOBuffer> request_buffer =
-          base::MakeRefCounted<IOBuffer>(kRequestTextSize);
+      auto request_buffer =
+          base::MakeRefCounted<IOBufferWithSize>(kRequestTextSize);
       memcpy(request_buffer->data(), request_text, kRequestTextSize);
 
       // Write the request.
@@ -1144,7 +1144,7 @@
 
       // The read will hang; it's waiting for the peer to complete the
       // handshake, and the handshake is still blocked.
-      scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+      auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
       rv = sock->Read(buf.get(), 4096, callback.callback());
 
       // After releasing reads, the connection proceeds.
@@ -1177,7 +1177,7 @@
     request = request.substr(rv);
   }
 
-  auto response_buffer = base::MakeRefCounted<IOBuffer>(1024);
+  auto response_buffer = base::MakeRefCounted<IOBufferWithSize>(1024);
   int rv = callback.GetResult(
       socket->Read(response_buffer.get(), 1024, callback.callback()));
   if (rv < 0) {
@@ -1283,8 +1283,8 @@
   }
 
   int WriteAndWait(base::StringPiece request) {
-    scoped_refptr<IOBuffer> request_buffer =
-        base::MakeRefCounted<IOBuffer>(request.size());
+    auto request_buffer =
+        base::MakeRefCounted<IOBufferWithSize>(request.size());
     memcpy(request_buffer->data(), request.data(), request.size());
     return callback_.GetResult(
         ssl_socket_->Write(request_buffer.get(), request.size(),
@@ -1629,8 +1629,8 @@
   EXPECT_GT(sock->GetTotalReceivedBytes(), 0);
 
   const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(std::size(request_text) - 1);
+  auto request_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(std::size(request_text) - 1);
   memcpy(request_buffer->data(), request_text, std::size(request_text) - 1);
 
   rv = callback.GetResult(
@@ -1638,7 +1638,7 @@
                   callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS));
   EXPECT_EQ(static_cast<int>(std::size(request_text) - 1), rv);
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int64_t unencrypted_bytes_read = 0;
   int64_t network_bytes_read_during_handshake = sock->GetTotalReceivedBytes();
   do {
@@ -1714,8 +1714,8 @@
   const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
   static const int kRequestTextSize =
       static_cast<int>(std::size(request_text) - 1);
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(kRequestTextSize);
+  auto request_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(kRequestTextSize);
   memcpy(request_buffer->data(), request_text, kRequestTextSize);
 
   rv = callback.GetResult(sock->Write(request_buffer.get(), kRequestTextSize,
@@ -1726,7 +1726,7 @@
   // Simulate an unclean/forcible shutdown.
   raw_transport->SetNextReadError(ERR_CONNECTION_RESET);
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
 
   // Note: This test will hang if this bug has regressed. Simply checking that
   // rv != ERR_IO_PENDING is insufficient, as ERR_IO_PENDING is a legitimate
@@ -1767,8 +1767,8 @@
   const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
   static const int kRequestTextSize =
       static_cast<int>(std::size(request_text) - 1);
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(kRequestTextSize);
+  auto request_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(kRequestTextSize);
   memcpy(request_buffer->data(), request_text, kRequestTextSize);
 
   // Simulate an unclean/forcible shutdown on the underlying socket.
@@ -1784,7 +1784,7 @@
                                       TRAFFIC_ANNOTATION_FOR_TESTS));
   EXPECT_EQ(kRequestTextSize, rv);
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
 
   rv = sock->Read(buf.get(), 4096, callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -1835,8 +1835,8 @@
   const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
   static const int kRequestTextSize =
       static_cast<int>(std::size(request_text) - 1);
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(kRequestTextSize);
+  auto request_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(kRequestTextSize);
   memcpy(request_buffer->data(), request_text, kRequestTextSize);
 
   // This write should complete synchronously, because the TLS ciphertext
@@ -1872,7 +1872,7 @@
 
   // Issue a "hanging" Read first.
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int read_rv = Read(sock_.get(), buf.get(), 4096, callback.callback());
   // We haven't written the request, so there should be no response yet.
   ASSERT_THAT(read_rv, IsError(ERR_IO_PENDING));
@@ -1885,8 +1885,7 @@
   for (int i = 0; i < 3770; ++i)
     request_text.push_back('*');
   request_text.append("\r\n\r\n");
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<StringIOBuffer>(request_text);
+  auto request_buffer = base::MakeRefCounted<StringIOBuffer>(request_text);
 
   TestCompletionCallback callback2;  // Used for Write only.
   rv = callback2.GetResult(
@@ -1954,7 +1953,7 @@
   // the ERR_IO_PENDING caused by SetReadShouldBlock() and thus return.
   SSLClientSocket* raw_sock = sock.get();
   DeleteSocketCallback read_callback(sock.release());
-  scoped_refptr<IOBuffer> read_buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   rv = Read(raw_sock, read_buf.get(), 4096, read_callback.callback());
 
   // Ensure things didn't complete synchronously, otherwise |sock| is invalid.
@@ -2020,8 +2019,8 @@
   const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
   static const int kRequestTextSize =
       static_cast<int>(std::size(request_text) - 1);
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(kRequestTextSize);
+  auto request_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(kRequestTextSize);
   memcpy(request_buffer->data(), request_text, kRequestTextSize);
 
   rv = callback.GetResult(sock->Write(request_buffer.get(), kRequestTextSize,
@@ -2032,7 +2031,7 @@
   // Start a hanging read.
   TestCompletionCallback read_callback;
   raw_transport->BlockReadResult();
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   rv = Read(sock.get(), buf.get(), 4096, read_callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
@@ -2128,7 +2127,7 @@
   EXPECT_TRUE(sock->IsConnected());
 
   raw_transport->SetNextReadError(0);
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   rv = ReadAndWaitForCompletion(sock.get(), buf.get(), 4096);
   EXPECT_EQ(0, rv);
 }
@@ -2163,7 +2162,7 @@
 
   raw_error_socket->SetNextReadError(0);
   raw_transport->BlockReadResult();
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   TestCompletionCallback read_callback;
   rv = Read(sock.get(), buf.get(), 4096, read_callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -2187,7 +2186,7 @@
 
   // Receive the fatal alert.
   TestCompletionCallback callback;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR,
             ReadAndWaitForCompletion(sock_.get(), buf.get(), 4096));
 }
@@ -2201,8 +2200,8 @@
   EXPECT_THAT(rv, IsOk());
 
   const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(std::size(request_text) - 1);
+  auto request_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(std::size(request_text) - 1);
   memcpy(request_buffer->data(), request_text, std::size(request_text) - 1);
 
   TestCompletionCallback callback;
@@ -2211,7 +2210,7 @@
                    callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS));
   EXPECT_EQ(static_cast<int>(std::size(request_text) - 1), rv);
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(1);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(1);
   do {
     rv = ReadAndWaitForCompletion(sock_.get(), buf.get(), 1);
     EXPECT_GE(rv, 0);
@@ -2242,8 +2241,8 @@
   ASSERT_TRUE(sock->IsConnected());
 
   const char request_text[] = "GET /ssl-many-small-records HTTP/1.0\r\n\r\n";
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(std::size(request_text) - 1);
+  auto request_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(std::size(request_text) - 1);
   memcpy(request_buffer->data(), request_text, std::size(request_text) - 1);
 
   rv = callback.GetResult(
@@ -2263,7 +2262,7 @@
   // of ciphertext necessary to contain the 8K of plaintext requested below.
   raw_transport->BufferNextRead(15000);
 
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(8192);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(8192);
   rv = ReadAndWaitForCompletion(sock.get(), buffer.get(), 8192);
   ASSERT_EQ(rv, 8192);
 }
@@ -2277,8 +2276,8 @@
   EXPECT_THAT(rv, IsOk());
 
   const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(std::size(request_text) - 1);
+  auto request_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(std::size(request_text) - 1);
   memcpy(request_buffer->data(), request_text, std::size(request_text) - 1);
 
   TestCompletionCallback callback;
@@ -2288,7 +2287,7 @@
   EXPECT_EQ(static_cast<int>(std::size(request_text) - 1), rv);
 
   // Do a partial read and then exit.  This test should not crash!
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(512);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(512);
   rv = ReadAndWaitForCompletion(sock_.get(), buf.get(), 512);
   EXPECT_GT(rv, 0);
 }
@@ -2312,8 +2311,8 @@
   EXPECT_TRUE(sock->IsConnected());
 
   const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(std::size(request_text) - 1);
+  auto request_buffer =
+      base::MakeRefCounted<IOBufferWithSize>(std::size(request_text) - 1);
   memcpy(request_buffer->data(), request_text, std::size(request_text) - 1);
 
   rv = callback.GetResult(
@@ -2326,7 +2325,7 @@
       entries, 5, NetLogEventType::SSL_SOCKET_BYTES_SENT,
       NetLogEventPhase::NONE);
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   for (;;) {
     rv = ReadAndWaitForCompletion(sock.get(), buf.get(), 4096);
     EXPECT_GE(rv, 0);
@@ -2866,8 +2865,7 @@
 
   const char kRequestText[] = "GET / HTTP/1.0\r\n\r\n";
   const size_t kRequestLen = std::size(kRequestText) - 1;
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(kRequestLen);
+  auto request_buffer = base::MakeRefCounted<IOBufferWithSize>(kRequestLen);
   memcpy(request_buffer->data(), kRequestText, kRequestLen);
 
   TestCompletionCallback callback;
@@ -2939,8 +2937,7 @@
   // Write a partial HTTP request.
   const char kRequestText[] = "GET / HTTP/1.0";
   const size_t kRequestLen = std::size(kRequestText) - 1;
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(kRequestLen);
+  auto request_buffer = base::MakeRefCounted<IOBufferWithSize>(kRequestLen);
   memcpy(request_buffer->data(), kRequestText, kRequestLen);
 
   // Although transport writes are blocked, SSLClientSocketImpl completes the
@@ -3489,7 +3486,7 @@
   // processed; however, pump the underlying transport so that it is read from
   // the socket. NOTE: This may flakily pass if the server's final flight
   // doesn't come in one Read.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int rv = sock1->Read(buf.get(), 4096, callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   raw_transport1->WaitForReadResult();
@@ -3541,7 +3538,7 @@
   // The actual read on |sock1| will not complete until the Finished message is
   // processed; however, pump the underlying transport so that it is read from
   // the socket.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int rv = sock1->Read(buf.get(), 4096, callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   raw_transport1->WaitForReadResult();
@@ -4791,7 +4788,7 @@
 
   // Release the ServerHello. Now reads complete.
   socket->UnblockReadResult();
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int size = ReadAndWait(buf.get(), 4096);
   EXPECT_GT(size, 0);
   EXPECT_EQ('1', buf->data()[size - 1]);
@@ -4826,7 +4823,7 @@
   // explicitly called ReaD() or ConfirmHandshake(), SSLClientSocketImpl
   // internally consumed the ServerHello and switch keys. The server then
   // responds with '0'.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int size = ReadAndWait(buf.get(), 4096);
   EXPECT_GT(size, 0);
   EXPECT_EQ('0', buf->data()[size - 1]);
@@ -4850,7 +4847,7 @@
   EXPECT_EQ(static_cast<int>(kRequest.size()), WriteAndWait(kRequest));
 
   socket->UnblockReadResult();
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int size = ReadAndWait(buf.get(), 4096);
   EXPECT_GT(size, 0);
   EXPECT_EQ('1', buf->data()[size - 1]);
@@ -4902,7 +4899,7 @@
 
   // Queue a read. It should be blocked on the ServerHello.
   TestCompletionCallback read_callback;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int read_rv =
       ssl_socket()->Read(read_buf.get(), 4096, read_callback.callback());
   ASSERT_THAT(read_rv, IsError(ERR_IO_PENDING));
@@ -4969,7 +4966,7 @@
 
   // Attempt a ReadIfReady(). It should be blocked on the ServerHello.
   TestCompletionCallback read_callback;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int read_rv =
       ssl_socket()->ReadIfReady(read_buf.get(), 4096, read_callback.callback());
   ASSERT_THAT(read_rv, IsError(ERR_IO_PENDING));
@@ -5020,7 +5017,7 @@
   socket->UnblockReadResult();
 
   // Expect early data to be rejected.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int rv = ReadAndWait(buf.get(), 4096);
   EXPECT_EQ(ERR_EARLY_DATA_REJECTED, rv);
   rv = WriteAndWait(kRequest);
@@ -5056,7 +5053,7 @@
   socket->UnblockReadResult();
 
   // Expect early data to be rejected because the TLS version was incorrect.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int rv = ReadAndWait(buf.get(), 4096);
   EXPECT_EQ(ERR_WRONG_VERSION_ON_EARLY_DATA, rv);
   rv = WriteAndWait(kRequest);
@@ -5100,7 +5097,7 @@
   constexpr base::StringPiece kRequest = "GET /zerortt HTTP/1.0\r\n\r\n";
   EXPECT_EQ(static_cast<int>(kRequest.size()), WriteAndWait(kRequest));
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int size = ReadAndWait(buf.get(), 4096);
   EXPECT_GT(size, 0);
   EXPECT_EQ('0', buf->data()[size - 1]);
@@ -5122,7 +5119,7 @@
   ASSERT_THAT(Connect(), IsOk());
 
   // Read() does not make progress.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   TestCompletionCallback read_callback;
   ASSERT_EQ(ERR_IO_PENDING,
             ssl_socket()->Read(buf.get(), 4096, read_callback.callback()));
@@ -5159,7 +5156,7 @@
   constexpr base::StringPiece kRequest = "GET /zerortt HTTP/1.0\r\n\r\n";
   EXPECT_EQ(static_cast<int>(kRequest.size()), WriteAndWait(kRequest));
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int size = ReadAndWait(buf.get(), 4096);
   EXPECT_GT(size, 0);
   EXPECT_EQ('0', buf->data()[size - 1]);
@@ -5188,7 +5185,7 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(callback.have_result());
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   TestCompletionCallback read_callback;
   ASSERT_EQ(ERR_IO_PENDING,
             ssl_socket()->Read(buf.get(), 4096, read_callback.callback()));
@@ -5259,13 +5256,13 @@
   EXPECT_THAT(client_callback.GetResult(client_rv), IsOk());
 
   // Write a single record on the server.
-  scoped_refptr<IOBuffer> write_buf = base::MakeRefCounted<StringIOBuffer>("a");
+  auto write_buf = base::MakeRefCounted<StringIOBuffer>("a");
   server_rv = server->Write(write_buf.get(), 1, server_callback.callback(),
                             TRAFFIC_ANNOTATION_FOR_TESTS);
 
   // Read that record on the server, but with a much larger buffer than
   // necessary.
-  scoped_refptr<IOBuffer> read_buf = base::MakeRefCounted<IOBuffer>(1024);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(1024);
   client_rv =
       Read(client.get(), read_buf.get(), 1024, client_callback.callback());
 
@@ -5817,7 +5814,7 @@
   socket->UnblockReadResult();
 
   // Expect early data to be rejected.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int rv = ReadAndWait(buf.get(), 4096);
   EXPECT_EQ(ERR_EARLY_DATA_REJECTED, rv);
 
@@ -5862,7 +5859,7 @@
   constexpr base::StringPiece kRequest = "GET /zerortt HTTP/1.0\r\n\r\n";
   EXPECT_EQ(static_cast<int>(kRequest.size()), WriteAndWait(kRequest));
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   int size = ReadAndWait(buf.get(), 4096);
   EXPECT_GT(size, 0);
   EXPECT_EQ('1', buf->data()[size - 1]);
@@ -5960,7 +5957,7 @@
 
   // ReadIfReady() should not read anything because the socket is blocked.
   bool callback_called = false;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(100);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(100);
   int rv = sock->ReadIfReady(
       read_buf.get(), 100,
       base::BindLambdaForTesting([&](int rv) { callback_called = true; }));
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
index 2cfb6563..33a2c94 100644
--- a/net/socket/ssl_server_socket_unittest.cc
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -327,10 +327,8 @@
   const char kTestData[] = "testing123";
   const int kTestDataSize = strlen(kTestData);
   const int kReadBufSize = 1024;
-  scoped_refptr<IOBuffer> write_buf =
-      base::MakeRefCounted<StringIOBuffer>(kTestData);
-  scoped_refptr<IOBuffer> read_buf =
-      base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto write_buf = base::MakeRefCounted<StringIOBuffer>(kTestData);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
 
   // Write then read.
   int written =
@@ -501,7 +499,7 @@
         base::MakeRefCounted<StringIOBuffer>("testing123");
     scoped_refptr<DrainableIOBuffer> read_buf =
         base::MakeRefCounted<DrainableIOBuffer>(
-            base::MakeRefCounted<IOBuffer>(kReadBufSize), kReadBufSize);
+            base::MakeRefCounted<IOBufferWithSize>(kReadBufSize), kReadBufSize);
     TestCompletionCallback write_callback;
     TestCompletionCallback read_callback;
     int server_ret = server_socket_->Write(write_buf.get(), write_buf->size(),
@@ -924,7 +922,7 @@
   const int kReadBufSize = 1024;
   scoped_refptr<DrainableIOBuffer> read_buf =
       base::MakeRefCounted<DrainableIOBuffer>(
-          base::MakeRefCounted<IOBuffer>(kReadBufSize), kReadBufSize);
+          base::MakeRefCounted<IOBufferWithSize>(kReadBufSize), kReadBufSize);
   TestCompletionCallback read_callback;
   client_ret = client_socket_->Read(read_buf.get(), read_buf->BytesRemaining(),
                                     read_callback.callback());
@@ -982,7 +980,7 @@
   const int kReadBufSize = 1024;
   scoped_refptr<DrainableIOBuffer> read_buf =
       base::MakeRefCounted<DrainableIOBuffer>(
-          base::MakeRefCounted<IOBuffer>(kReadBufSize), kReadBufSize);
+          base::MakeRefCounted<IOBufferWithSize>(kReadBufSize), kReadBufSize);
   TestCompletionCallback read_callback;
   client_ret = client_socket_->Read(read_buf.get(), read_buf->BytesRemaining(),
                                     read_callback.callback());
@@ -1036,7 +1034,7 @@
       base::MakeRefCounted<StringIOBuffer>("testing123");
   scoped_refptr<DrainableIOBuffer> read_buf =
       base::MakeRefCounted<DrainableIOBuffer>(
-          base::MakeRefCounted<IOBuffer>(kReadBufSize), kReadBufSize);
+          base::MakeRefCounted<IOBufferWithSize>(kReadBufSize), kReadBufSize);
 
   // Write then read.
   TestCompletionCallback write_callback;
@@ -1438,7 +1436,7 @@
   // Attempt to read from the server socket. There will not be anything to read.
   // Cancel the read immediately afterwards.
   TestCompletionCallback read_callback;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(1);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(1);
   int read_ret =
       server_socket_->ReadIfReady(read_buf.get(), 1, read_callback.callback());
   ASSERT_THAT(read_ret, IsError(ERR_IO_PENDING));
diff --git a/net/socket/tcp_client_socket_unittest.cc b/net/socket/tcp_client_socket_unittest.cc
index 851e2fa..9ee8727 100644
--- a/net/socket/tcp_client_socket_unittest.cc
+++ b/net/socket/tcp_client_socket_unittest.cc
@@ -393,8 +393,7 @@
   SocketTag tag2(getuid(), tag_val2);
   s.ApplySocketTag(tag2);
   const char kRequest1[] = "GET / HTTP/1.0";
-  scoped_refptr<IOBuffer> write_buffer1 =
-      base::MakeRefCounted<StringIOBuffer>(kRequest1);
+  auto write_buffer1 = base::MakeRefCounted<StringIOBuffer>(kRequest1);
   TestCompletionCallback write_callback1;
   EXPECT_EQ(s.Write(write_buffer1.get(), strlen(kRequest1),
                     write_callback1.callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
@@ -445,8 +444,7 @@
   SocketTag tag2(getuid(), tag_val2);
   s.ApplySocketTag(tag2);
   const char kRequest1[] = "GET / HTTP/1.0";
-  scoped_refptr<IOBuffer> write_buffer1 =
-      base::MakeRefCounted<StringIOBuffer>(kRequest1);
+  auto write_buffer1 = base::MakeRefCounted<StringIOBuffer>(kRequest1);
   TestCompletionCallback write_callback1;
   EXPECT_EQ(s.Write(write_buffer1.get(), strlen(kRequest1),
                     write_callback1.callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
@@ -460,8 +458,7 @@
   SocketTag tag1(SocketTag::UNSET_UID, tag_val1);
   s.ApplySocketTag(tag1);
   const char kRequest2[] = "\n\n";
-  scoped_refptr<IOBuffer> write_buffer2 =
-      base::MakeRefCounted<StringIOBuffer>(kRequest2);
+  auto write_buffer2 = base::MakeRefCounted<StringIOBuffer>(kRequest2);
   TestCompletionCallback write_callback2;
   EXPECT_EQ(s.Write(write_buffer2.get(), strlen(kRequest2),
                     write_callback2.callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
@@ -613,7 +610,7 @@
   // Power notifications happen asynchronously.
   base::RunLoop().RunUntilIdle();
 
-  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(1);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(1);
   buffer->data()[0] = '1';
   TestCompletionCallback callback;
   // Check that the client socket is disconnected, and actions fail with
@@ -652,7 +649,7 @@
 
   // Start a read. This shouldn't complete, since the other end of the pipe
   // writes no data.
-  scoped_refptr<IOBuffer> read_buffer = base::MakeRefCounted<IOBuffer>(1);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(1);
   read_buffer->data()[0] = '1';
   TestCompletionCallback callback;
   ASSERT_THAT(client_socket->Read(read_buffer.get(), 1, callback.callback()),
@@ -679,8 +676,7 @@
 
   // Write to the socket until a write doesn't complete synchronously.
   const int kBufferSize = 4096;
-  scoped_refptr<IOBuffer> write_buffer =
-      base::MakeRefCounted<IOBuffer>(kBufferSize);
+  auto write_buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
   memset(write_buffer->data(), '1', kBufferSize);
   TestCompletionCallback callback;
   while (true) {
@@ -727,7 +723,7 @@
 
     // Start a read. This shouldn't complete, since the other end of the pipe
     // writes no data.
-    scoped_refptr<IOBuffer> read_buffer = base::MakeRefCounted<IOBuffer>(1);
+    auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(1);
     read_buffer->data()[0] = '1';
     TestCompletionCallback read_callback;
 
@@ -763,8 +759,7 @@
 
     // Write to the socket until a write doesn't complete synchronously.
     const int kBufferSize = 4096;
-    scoped_refptr<IOBuffer> write_buffer =
-        base::MakeRefCounted<IOBuffer>(kBufferSize);
+    auto write_buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
     memset(write_buffer->data(), '1', kBufferSize);
     TestCompletionCallback write_callback;
     while (true) {
diff --git a/net/socket/transport_client_socket_test_util.cc b/net/socket/transport_client_socket_test_util.cc
index a93b97ac..47dec6b9 100644
--- a/net/socket/transport_client_socket_test_util.cc
+++ b/net/socket/transport_client_socket_test_util.cc
@@ -23,7 +23,7 @@
   int request_len = strlen(request_text);
   scoped_refptr<DrainableIOBuffer> request_buffer =
       base::MakeRefCounted<DrainableIOBuffer>(
-          base::MakeRefCounted<IOBuffer>(request_len), request_len);
+          base::MakeRefCounted<IOBufferWithSize>(request_len), request_len);
   memcpy(request_buffer->data(), request_text, request_len);
 
   int bytes_written = 0;
@@ -75,7 +75,7 @@
   int reply_len = strlen(kServerReply);
   scoped_refptr<DrainableIOBuffer> write_buffer =
       base::MakeRefCounted<DrainableIOBuffer>(
-          base::MakeRefCounted<IOBuffer>(reply_len), reply_len);
+          base::MakeRefCounted<IOBufferWithSize>(reply_len), reply_len);
   memcpy(write_buffer->data(), kServerReply, reply_len);
   int bytes_written = 0;
   while (write_buffer->BytesRemaining() > 0) {
diff --git a/net/socket/transport_client_socket_unittest.cc b/net/socket/transport_client_socket_unittest.cc
index 4b24198..9feb0dd 100644
--- a/net/socket/transport_client_socket_unittest.cc
+++ b/net/socket/transport_client_socket_unittest.cc
@@ -137,7 +137,7 @@
 }
 
 TEST_F(TransportClientSocketTest, IsConnected) {
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   TestCompletionCallback callback;
   uint32_t bytes_read;
 
@@ -203,7 +203,7 @@
 
   SendRequestAndResponse(sock_.get(), connected_sock_.get());
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(4096);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(4096);
   uint32_t bytes_read = DrainStreamSocket(sock_.get(), buf.get(), 4096,
                                           strlen(kServerReply), &callback);
   ASSERT_EQ(bytes_read, strlen(kServerReply));
@@ -224,7 +224,7 @@
 
   SendRequestAndResponse(sock_.get(), connected_sock_.get());
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(1);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(1);
   uint32_t bytes_read = 0;
   while (bytes_read < strlen(kServerReply)) {
     int rv = sock_->Read(buf.get(), 1, callback.callback());
@@ -252,7 +252,7 @@
   SendRequestAndResponse(sock_.get(), connected_sock_.get());
 
   // Do a partial read and then exit.  This test should not crash!
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(16);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(16);
   int rv = sock_->Read(buf.get(), 16, callback.callback());
   EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
 
@@ -267,13 +267,12 @@
 
   // Read first.  There's no data, so it should return ERR_IO_PENDING.
   const int kBufLen = 4096;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kBufLen);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kBufLen);
   int rv = sock_->Read(buf.get(), kBufLen, callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   const int kWriteBufLen = 64 * 1024;
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(kWriteBufLen);
+  auto request_buffer = base::MakeRefCounted<IOBufferWithSize>(kWriteBufLen);
   char* request_data = request_buffer->data();
   memset(request_data, 'A', kWriteBufLen);
   TestCompletionCallback write_callback;
@@ -305,8 +304,7 @@
   EstablishConnection(&callback);
 
   const int kWriteBufLen = 64 * 1024;
-  scoped_refptr<IOBuffer> request_buffer =
-      base::MakeRefCounted<IOBuffer>(kWriteBufLen);
+  auto request_buffer = base::MakeRefCounted<IOBufferWithSize>(kWriteBufLen);
   char* request_data = request_buffer->data();
   memset(request_data, 'A', kWriteBufLen);
   TestCompletionCallback write_callback;
@@ -327,7 +325,7 @@
   // Read() to block on ERR_IO_PENDING too.
 
   const int kBufLen = 4096;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kBufLen);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kBufLen);
   while (true) {
     int rv = sock_->Read(buf.get(), kBufLen, callback.callback());
     ASSERT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
diff --git a/net/socket/udp_socket_unittest.cc b/net/socket/udp_socket_unittest.cc
index c0d4fd2..a0df4fa 100644
--- a/net/socket/udp_socket_unittest.cc
+++ b/net/socket/udp_socket_unittest.cc
@@ -326,8 +326,7 @@
   // Read just 2 bytes. Read() is expected to return the first 2 bytes from the
   // packet and discard the rest.
   const int kPartialReadSize = 2;
-  scoped_refptr<IOBuffer> buffer =
-      base::MakeRefCounted<IOBuffer>(kPartialReadSize);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(kPartialReadSize);
   int rv =
       server_socket.RecvFrom(buffer.get(), kPartialReadSize,
                              &recv_from_address_, recv_callback.callback());
diff --git a/net/socket/unix_domain_client_socket_posix_unittest.cc b/net/socket/unix_domain_client_socket_posix_unittest.cc
index 29dd7e6..4a93bb75 100644
--- a/net/socket/unix_domain_client_socket_posix_unittest.cc
+++ b/net/socket/unix_domain_client_socket_posix_unittest.cc
@@ -201,8 +201,7 @@
 
   // Try to read data.
   const int kReadDataSize = 10;
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadDataSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadDataSize);
   TestCompletionCallback read_callback;
   EXPECT_EQ(ERR_IO_PENDING,
             rewrapped_socket.Read(
@@ -284,8 +283,7 @@
 
   // Try to read data.
   const int kReadDataSize = 10;
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadDataSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadDataSize);
   TestCompletionCallback read_callback;
   EXPECT_EQ(ERR_IO_PENDING,
             accepted_socket->Read(
@@ -318,8 +316,7 @@
 
   // Try to read data.
   const int kReadDataSize = 10;
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadDataSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadDataSize);
   TestCompletionCallback read_callback;
   EXPECT_EQ(ERR_IO_PENDING,
             client_socket.Read(
@@ -352,7 +349,7 @@
 
   // Send data from client to server.
   const int kWriteDataSize = 10;
-  scoped_refptr<IOBuffer> write_buffer =
+  auto write_buffer =
       base::MakeRefCounted<StringIOBuffer>(std::string(kWriteDataSize, 'd'));
   EXPECT_EQ(
       kWriteDataSize,
@@ -360,8 +357,7 @@
 
   // The buffer is bigger than write data size.
   const int kReadBufferSize = kWriteDataSize * 2;
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   EXPECT_EQ(kWriteDataSize,
             ReadSynchronously(accepted_socket.get(),
                               read_buffer.get(),
@@ -425,15 +421,14 @@
   const int kReadBufferSize = kWriteDataSize * 2;
   const int kSmallReadBufferSize = kWriteDataSize / 3;
   // Read smaller than write data size first.
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   TestCompletionCallback read_callback;
   EXPECT_EQ(
       ERR_IO_PENDING,
       accepted_socket->Read(
           read_buffer.get(), kSmallReadBufferSize, read_callback.callback()));
 
-  scoped_refptr<IOBuffer> write_buffer =
+  auto write_buffer =
       base::MakeRefCounted<StringIOBuffer>(std::string(kWriteDataSize, 'd'));
   EXPECT_EQ(
       kWriteDataSize,
diff --git a/net/socket/unix_domain_server_socket_posix_unittest.cc b/net/socket/unix_domain_server_socket_posix_unittest.cc
index ad43fbd..4e27407 100644
--- a/net/socket/unix_domain_server_socket_posix_unittest.cc
+++ b/net/socket/unix_domain_server_socket_posix_unittest.cc
@@ -114,8 +114,7 @@
 
   // Try to read from the socket.
   const int read_buffer_size = 10;
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(read_buffer_size);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(read_buffer_size);
   TestCompletionCallback read_callback;
   rv = read_callback.GetResult(client_socket.Read(
       read_buffer.get(), read_buffer_size, read_callback.callback()));
diff --git a/net/spdy/bidirectional_stream_spdy_impl.cc b/net/spdy/bidirectional_stream_spdy_impl.cc
index acf84099..e2f58b8 100644
--- a/net/spdy/bidirectional_stream_spdy_impl.cc
+++ b/net/spdy/bidirectional_stream_spdy_impl.cc
@@ -129,7 +129,8 @@
   if (buffers.size() == 1) {
     pending_combined_buffer_ = buffers[0];
   } else {
-    pending_combined_buffer_ = base::MakeRefCounted<net::IOBuffer>(total_len);
+    pending_combined_buffer_ =
+        base::MakeRefCounted<net::IOBufferWithSize>(total_len);
     int len = 0;
     // TODO(xunjieli): Get rid of extra copy. Coalesce headers and data frames.
     for (size_t i = 0; i < buffers.size(); ++i) {
diff --git a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
index 22b8738..f4dd384 100644
--- a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
+++ b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
@@ -317,8 +317,7 @@
   request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
                                        base::NumberToString(kBodyDataSize));
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<TestDelegateBase>(
       session_, read_buffer.get(), kReadBufferSize);
   delegate->SetRunUntilCompletion(true);
@@ -369,10 +368,8 @@
   request_info.url = default_url_;
   request_info.end_stream_on_headers = true;
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
-  scoped_refptr<IOBuffer> read_buffer2 =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
+  auto read_buffer2 = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<TestDelegateBase>(
       session_, read_buffer.get(), kReadBufferSize);
   auto delegate2 = std::make_unique<TestDelegateBase>(
@@ -419,8 +416,7 @@
   request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
                                        base::NumberToString(kBodyDataSize * 3));
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<TestDelegateBase>(
       session_, read_buffer.get(), kReadBufferSize);
   delegate->SetRunUntilCompletion(true);
@@ -473,8 +469,7 @@
   request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
                                        base::NumberToString(kBodyDataSize * 3));
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<TestDelegateBase>(
       session_, read_buffer.get(), kReadBufferSize);
   delegate->SetRunUntilCompletion(true);
@@ -565,8 +560,7 @@
   request_info.detect_broken_connection = true;
   request_info.heartbeat_interval = base::Seconds(1);
 
-  scoped_refptr<IOBuffer> read_buffer =
-      base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  auto read_buffer = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   auto delegate = std::make_unique<TestDelegateBase>(
       session_, read_buffer.get(), kReadBufferSize);
   delegate->SetRunUntilCompletion(true);
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index d16f6a5c..d3160ec 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -444,7 +444,7 @@
   CHECK(!HasUploadData());
   CHECK(spdy_session_->EndStreamWithDataFrame());
 
-  auto buffer = base::MakeRefCounted<IOBuffer>(/* buffer_size = */ 0);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(/* buffer_size = */ 0);
   stream_->SendData(buffer.get(), /* length = */ 0, NO_MORE_DATA_TO_SEND);
 }
 
diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc
index ad754c9..b45dc2f 100644
--- a/net/spdy/spdy_http_stream_unittest.cc
+++ b/net/spdy/spdy_http_stream_unittest.cc
@@ -303,7 +303,7 @@
   request.reset();
 
   // Read stream to completion.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(1);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(1);
   ASSERT_EQ(0,
             http_stream->ReadResponseBody(buf.get(), 1, callback.callback()));
 
@@ -403,7 +403,7 @@
 
   // Read stream 1 to completion, before making sure we can still read load
   // timing from both streams.
-  scoped_refptr<IOBuffer> buf1 = base::MakeRefCounted<IOBuffer>(1);
+  auto buf1 = base::MakeRefCounted<IOBufferWithSize>(1);
   ASSERT_EQ(
       0, http_stream1->ReadResponseBody(buf1.get(), 1, callback1.callback()));
 
@@ -694,24 +694,21 @@
   ASSERT_THAT(http_stream->ReadResponseHeaders(callback.callback()), IsOk());
 
   // Check |chunk1| response.
-  scoped_refptr<IOBuffer> buf1 =
-      base::MakeRefCounted<IOBuffer>(kUploadDataSize);
+  auto buf1 = base::MakeRefCounted<IOBufferWithSize>(kUploadDataSize);
   ASSERT_EQ(kUploadDataSize,
             http_stream->ReadResponseBody(
                 buf1.get(), kUploadDataSize, callback.callback()));
   EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize));
 
   // Check |chunk2| response.
-  scoped_refptr<IOBuffer> buf2 =
-      base::MakeRefCounted<IOBuffer>(kUploadData1Size);
+  auto buf2 = base::MakeRefCounted<IOBufferWithSize>(kUploadData1Size);
   ASSERT_EQ(kUploadData1Size,
             http_stream->ReadResponseBody(
                 buf2.get(), kUploadData1Size, callback.callback()));
   EXPECT_EQ(kUploadData1, std::string(buf2->data(), kUploadData1Size));
 
   // Check |chunk3| response.
-  scoped_refptr<IOBuffer> buf3 =
-      base::MakeRefCounted<IOBuffer>(kUploadDataSize);
+  auto buf3 = base::MakeRefCounted<IOBufferWithSize>(kUploadDataSize);
   ASSERT_EQ(kUploadDataSize,
             http_stream->ReadResponseBody(
                 buf3.get(), kUploadDataSize, callback.callback()));
@@ -799,8 +796,7 @@
             http_stream->GetTotalReceivedBytes());
 
   // Check |chunk1| response.
-  scoped_refptr<IOBuffer> buf1 =
-      base::MakeRefCounted<IOBuffer>(kUploadDataSize);
+  auto buf1 = base::MakeRefCounted<IOBufferWithSize>(kUploadDataSize);
   ASSERT_EQ(kUploadDataSize,
             http_stream->ReadResponseBody(
                 buf1.get(), kUploadDataSize, callback.callback()));
@@ -879,7 +875,7 @@
   ASSERT_THAT(http_stream->ReadResponseHeaders(callback.callback()), IsOk());
 
   // Check |chunk| response.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(1);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(1);
   ASSERT_EQ(0,
             http_stream->ReadResponseBody(
                 buf.get(), 1, callback.callback()));
@@ -1032,8 +1028,7 @@
   ASSERT_THAT(http_stream->ReadResponseHeaders(callback.callback()), IsOk());
 
   // Check |chunk1| response.
-  scoped_refptr<IOBuffer> buf1 =
-      base::MakeRefCounted<IOBuffer>(kUploadDataSize);
+  auto buf1 = base::MakeRefCounted<IOBufferWithSize>(kUploadDataSize);
   ASSERT_EQ(kUploadDataSize,
             http_stream->ReadResponseBody(
                 buf1.get(), kUploadDataSize, callback.callback()));
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index e5c23430..f8df7b27 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -2256,7 +2256,7 @@
   rv = callback.WaitForResult();
 
   const int kSize = 3000;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kSize);
   rv = trans->Read(
       buf.get(), kSize,
       base::BindOnce(&SpdyNetworkTransactionTest::StartTransactionCallback,
@@ -2305,7 +2305,7 @@
   // Setup a user callback which will delete the session, and clear out the
   // memory holding the stream object. Note that the callback deletes trans.
   const int kSize = 3000;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kSize);
   rv = trans->Read(
       buf.get(), kSize,
       base::BindOnce(&SpdyNetworkTransactionTest::DeleteSessionCallback,
@@ -3643,8 +3643,7 @@
   do {
     // Read small chunks at a time.
     const int kSmallReadSize = 3;
-    scoped_refptr<IOBuffer> buf =
-        base::MakeRefCounted<IOBuffer>(kSmallReadSize);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(kSmallReadSize);
     rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
     if (rv == ERR_IO_PENDING) {
       data.Resume();
@@ -3724,8 +3723,7 @@
   do {
     // Read small chunks at a time.
     const int kSmallReadSize = 14;
-    scoped_refptr<IOBuffer> buf =
-        base::MakeRefCounted<IOBuffer>(kSmallReadSize);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(kSmallReadSize);
     rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
     if (rv == ERR_IO_PENDING) {
       data.Resume();
@@ -3805,8 +3803,7 @@
   do {
     // Read small chunks at a time.
     const int kSmallReadSize = 14;
-    scoped_refptr<IOBuffer> buf =
-        base::MakeRefCounted<IOBuffer>(kSmallReadSize);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(kSmallReadSize);
     rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
     if (rv > 0) {
       EXPECT_EQ(kSmallReadSize, rv);
@@ -3882,8 +3879,7 @@
     // Allocate a large buffer to allow buffering. If a single read fills the
     // buffer, no buffering happens.
     const int kLargeReadSize = 1000;
-    scoped_refptr<IOBuffer> buf =
-        base::MakeRefCounted<IOBuffer>(kLargeReadSize);
+    auto buf = base::MakeRefCounted<IOBufferWithSize>(kLargeReadSize);
     rv = trans->Read(buf.get(), kLargeReadSize, read_callback.callback());
     if (rv == ERR_IO_PENDING) {
       data.Resume();
@@ -3953,7 +3949,7 @@
   TestCompletionCallback read_callback;
 
   const int kReadSize = 256;
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kReadSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kReadSize);
   rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
   ASSERT_EQ(ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
 
@@ -5446,7 +5442,7 @@
 
   // Issue a read which will cause a WINDOW_UPDATE to be sent and window
   // size increased to default.
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kTargetSize);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kTargetSize);
   EXPECT_EQ(static_cast<int>(kTargetSize),
             trans->Read(buf.get(), kTargetSize, CompletionOnceCallback()));
   EXPECT_EQ(static_cast<int>(stream_max_recv_window_size),
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
index 4cb468d0..107ab27 100644
--- a/net/spdy/spdy_proxy_client_socket.cc
+++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -584,7 +584,7 @@
   if (write_callback_)
     return;
 
-  auto buffer = base::MakeRefCounted<IOBuffer>(/*buffer_size=*/0);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(/*buffer_size=*/0);
   spdy_stream_->SendData(buffer.get(), /*length=*/0, NO_MORE_DATA_TO_SEND);
   end_stream_state_ = EndStreamState::kEndStreamSent;
 }
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc
index b385dee2..8a5b5732 100644
--- a/net/spdy/spdy_proxy_client_socket_unittest.cc
+++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -327,7 +327,7 @@
 
 void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data,
                                                      int len) {
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(len);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(len);
   if (use_read_if_ready()) {
     ASSERT_EQ(len,
               sock_->ReadIfReady(buf.get(), len, CompletionOnceCallback()));
@@ -350,7 +350,7 @@
                                                       int len,
                                                       bool fin) {
   // Issue the read, which will be completed asynchronously
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(len);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(len);
   if (use_read_if_ready()) {
     ASSERT_EQ(ERR_IO_PENDING,
               sock_->ReadIfReady(buf.get(), len, read_callback_.callback()));
@@ -381,7 +381,7 @@
 
 void SpdyProxyClientSocketTest::AssertReadStarts(const char* data, int len) {
   // Issue the read, which will be completed asynchronously.
-  read_buf_ = base::MakeRefCounted<IOBuffer>(len);
+  read_buf_ = base::MakeRefCounted<IOBufferWithSize>(len);
   if (use_read_if_ready()) {
     ASSERT_EQ(ERR_IO_PENDING, sock_->ReadIfReady(read_buf_.get(), len,
                                                  read_callback_.callback()));
@@ -1215,7 +1215,7 @@
   ResumeAndRun();
 
   ASSERT_FALSE(sock_->IsConnected());
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   ASSERT_EQ(kLen1, sock_->Read(buf.get(), kLen1, CompletionOnceCallback()));
   ASSERT_EQ(std::string(kMsg1, kLen1), std::string(buf->data(), kLen1));
 
@@ -1370,7 +1370,7 @@
 
   EXPECT_TRUE(sock_->IsConnected());
 
-  scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   ASSERT_EQ(ERR_IO_PENDING,
             sock_->Read(buf.get(), kLen1, read_callback_.callback()));
 
@@ -1405,7 +1405,7 @@
 
   EXPECT_TRUE(sock_->IsConnected());
 
-  scoped_refptr<IOBuffer> read_buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   ASSERT_EQ(ERR_IO_PENDING,
             sock_->Read(read_buf.get(), kLen1, read_callback_.callback()));
 
@@ -1535,7 +1535,7 @@
 
   DeleteSockCallback read_callback(&sock_);
 
-  scoped_refptr<IOBuffer> read_buf = base::MakeRefCounted<IOBuffer>(kLen1);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kLen1);
   ASSERT_EQ(ERR_IO_PENDING,
             sock_->Read(read_buf.get(), kLen1, read_callback.callback()));
 
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index fa57f9d924..92876e4 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -1883,7 +1883,7 @@
 
   CHECK(socket_);
   read_state_ = READ_STATE_DO_READ_COMPLETE;
-  read_buffer_ = base::MakeRefCounted<IOBuffer>(kReadBufferSize);
+  read_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize);
   int rv = socket_->ReadIfReady(
       read_buffer_.get(), kReadBufferSize,
       base::BindOnce(&SpdySession::PumpReadLoop, weak_factory_.GetWeakPtr(),
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index 75fb406..110f1de 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -2758,8 +2758,7 @@
   ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
   const int kPayloadSize = kYieldAfterBytesRead / 4 - spdy::kFrameHeaderSize;
   TestDataStream test_stream;
-  scoped_refptr<IOBuffer> payload =
-      base::MakeRefCounted<IOBuffer>(kPayloadSize);
+  auto payload = base::MakeRefCounted<IOBufferWithSize>(kPayloadSize);
   char* payload_data = payload->data();
   test_stream.GetBytes(payload_data, kPayloadSize);
 
@@ -2973,8 +2972,7 @@
   ASSERT_EQ(32 * 1024, kYieldAfterBytesRead);
   const int kPayloadSize = kYieldAfterBytesRead / 4 - spdy::kFrameHeaderSize;
   TestDataStream test_stream;
-  scoped_refptr<IOBuffer> payload =
-      base::MakeRefCounted<IOBuffer>(kPayloadSize);
+  auto payload = base::MakeRefCounted<IOBufferWithSize>(kPayloadSize);
   char* payload_data = payload->data();
   test_stream.GetBytes(payload_data, kPayloadSize);
 
@@ -3068,16 +3066,15 @@
   TestDataStream test_stream;
   const int kEightKPayloadSize =
       kYieldAfterBytesRead / 4 - spdy::kFrameHeaderSize;
-  scoped_refptr<IOBuffer> eightk_payload =
-      base::MakeRefCounted<IOBuffer>(kEightKPayloadSize);
+  auto eightk_payload =
+      base::MakeRefCounted<IOBufferWithSize>(kEightKPayloadSize);
   char* eightk_payload_data = eightk_payload->data();
   test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
 
   // Build buffer of 2k size.
   TestDataStream test_stream2;
   const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
-  scoped_refptr<IOBuffer> twok_payload =
-      base::MakeRefCounted<IOBuffer>(kTwoKPayloadSize);
+  auto twok_payload = base::MakeRefCounted<IOBufferWithSize>(kTwoKPayloadSize);
   char* twok_payload_data = twok_payload->data();
   test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
 
diff --git a/net/test/spawned_test_server/remote_test_server_spawner_request.cc b/net/test/spawned_test_server/remote_test_server_spawner_request.cc
index 808fa2d2..66443ec 100644
--- a/net/test/spawned_test_server/remote_test_server_spawner_request.cc
+++ b/net/test/spawned_test_server/remote_test_server_spawner_request.cc
@@ -71,7 +71,7 @@
 RemoteTestServerSpawnerRequest::Core::Core()
     : event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
              base::WaitableEvent::InitialState::NOT_SIGNALED),
-      read_buffer_(base::MakeRefCounted<IOBuffer>(kBufferSize)) {
+      read_buffer_(base::MakeRefCounted<IOBufferWithSize>(kBufferSize)) {
   DETACH_FROM_THREAD(thread_checker_);
 }
 
diff --git a/net/tools/cert_verify_tool/cert_verify_comparision_tool.cc b/net/tools/cert_verify_tool/cert_verify_comparision_tool.cc
index 8814a47..360f402 100644
--- a/net/tools/cert_verify_tool/cert_verify_comparision_tool.cc
+++ b/net/tools/cert_verify_tool/cert_verify_comparision_tool.cc
@@ -103,14 +103,11 @@
 
     // TODO(mattm): add command line flags to configure VerifyFlags.
     int flags = 0;
-    // Don't add any additional trust anchors.
-    net::CertificateList x509_additional_trust_anchors;
 
     // TODO(crbug.com/634484): use a real netlog and print the results?
     *error = proc_->Verify(&x509_target_and_intermediates, hostname,
                            /*ocsp_response=*/std::string(),
-                           /*sct_list=*/std::string(), flags,
-                           x509_additional_trust_anchors, result,
+                           /*sct_list=*/std::string(), flags, result,
                            net::NetLogWithSource());
 
     return *error == net::OK;
@@ -142,7 +139,8 @@
         net::CreateCertVerifyProcBuiltin(
             std::move(cert_net_fetcher), net::CRLSet::BuiltinCRLSet(),
             net::CreateSslSystemTrustStoreChromeRoot(
-                std::make_unique<net::TrustStoreChrome>())));
+                std::make_unique<net::TrustStoreChrome>()),
+            {}));
 #endif
   }
 
diff --git a/net/tools/cert_verify_tool/cert_verify_tool.cc b/net/tools/cert_verify_tool/cert_verify_tool.cc
index 474f108..4d92629 100644
--- a/net/tools/cert_verify_tool/cert_verify_tool.cc
+++ b/net/tools/cert_verify_tool/cert_verify_tool.cc
@@ -247,7 +247,7 @@
         "CertVerifyProcBuiltin",
         net::CreateCertVerifyProcBuiltin(
             std::move(cert_net_fetcher), std::move(crl_set),
-            CreateSystemTrustStore(impl_name, root_store_type)));
+            CreateSystemTrustStore(impl_name, root_store_type), {}));
   }
 
   if (impl_name == "pathbuilder") {
diff --git a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
index 4c02aadb..38d6c5c00 100644
--- a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
+++ b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
@@ -129,7 +129,7 @@
   int rv = cert_verify_proc->Verify(
       x509_target_and_intermediates.get(), hostname,
       /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
-      /*additional_trust_anchors=*/{}, &result, net::NetLogWithSource());
+      &result, net::NetLogWithSource());
 
   std::cout << "CertVerifyProc result: " << net::ErrorToShortString(rv) << "\n";
   PrintCertVerifyResult(result);
diff --git a/net/tools/stress_cache/stress_cache.cc b/net/tools/stress_cache/stress_cache.cc
index c6d278e..767463ba 100644
--- a/net/tools/stress_cache/stress_cache.cc
+++ b/net/tools/stress_cache/stress_cache.cc
@@ -124,7 +124,7 @@
 class EntryWrapper {
  public:
   EntryWrapper() {
-    buffer_ = base::MakeRefCounted<net::IOBuffer>(kBufferSize);
+    buffer_ = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
     memset(buffer_->data(), 'k', kBufferSize);
   }
 
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc
index e8f9d5e..83468bf 100644
--- a/net/url_request/url_request_test_util.cc
+++ b/net/url_request/url_request_test_util.cc
@@ -131,7 +131,7 @@
 const int TestDelegate::kBufferSize;
 
 TestDelegate::TestDelegate()
-    : buf_(base::MakeRefCounted<IOBuffer>(kBufferSize)) {}
+    : buf_(base::MakeRefCounted<IOBufferWithSize>(kBufferSize)) {}
 
 TestDelegate::~TestDelegate() = default;
 
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 9737490..972aefa 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -10547,9 +10547,10 @@
   }
 
   void UpdateCertVerifier(scoped_refptr<CRLSet> crl_set) {
-    net::CertVerifyProcFactory::ImplParams params;
+    net::CertVerifyProc::ImplParams params;
     params.crl_set = std::move(crl_set);
-    updatable_cert_verifier_->UpdateVerifyProcData(cert_net_fetcher_, params);
+    updatable_cert_verifier_->UpdateVerifyProcData(cert_net_fetcher_, params,
+                                                   {});
   }
 
   scoped_refptr<CertNetFetcherURLRequest> cert_net_fetcher_;
@@ -11697,7 +11698,7 @@
   // Configure a CRL that will mark |root_ca_cert| as a blocked interception
   // root.
   std::string crl_set_bytes;
-  net::CertVerifyProcFactory::ImplParams params;
+  net::CertVerifyProc::ImplParams params;
   ASSERT_TRUE(
       base::ReadFileToString(GetTestCertsDirectory().AppendASCII(
                                  "crlset_blocked_interception_by_root.raw"),
@@ -11705,7 +11706,7 @@
   ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &params.crl_set));
 
   updatable_cert_verifier_->UpdateVerifyProcData(
-      /*cert_net_fetcher=*/nullptr, params);
+      /*cert_net_fetcher=*/nullptr, params, {});
 
   // Verify the connection fails as being a known interception root.
   {
diff --git a/net/websockets/websocket_basic_stream_adapters_test.cc b/net/websockets/websocket_basic_stream_adapters_test.cc
index 53857612..d4366ba4e 100644
--- a/net/websockets/websocket_basic_stream_adapters_test.cc
+++ b/net/websockets/websocket_basic_stream_adapters_test.cc
@@ -215,7 +215,7 @@
 
   // Buffer larger than each MockRead.
   const int kReadBufSize = 1024;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
   int rv = adapter.Read(read_buf.get(), kReadBufSize, CompletionOnceCallback());
   ASSERT_EQ(3, rv);
   EXPECT_EQ("foo", base::StringPiece(read_buf->data(), rv));
@@ -246,7 +246,7 @@
 
   // Buffer smaller than each MockRead.
   const int kReadBufSize = 2;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
   int rv = adapter.Read(read_buf.get(), kReadBufSize, CompletionOnceCallback());
   ASSERT_EQ(2, rv);
   EXPECT_EQ("fo", base::StringPiece(read_buf->data(), rv));
@@ -318,7 +318,7 @@
   EXPECT_TRUE(adapter.is_initialized());
 
   const int kReadBufSize = 1024;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
   TestCompletionCallback read_callback;
   int rv = adapter.Read(read_buf.get(), kReadBufSize, read_callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -683,7 +683,7 @@
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   constexpr int kReadBufSize = 1024;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
   TestCompletionCallback read_callback;
   rv = adapter.Read(read_buf.get(), kReadBufSize, read_callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -772,7 +772,7 @@
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   const int kReadBufSize = 3;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
   TestCompletionCallback callback;
   rv = adapter.Read(read_buf.get(), kReadBufSize, callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -842,7 +842,7 @@
 
   // Buffer larger than each MockRead.
   const int kReadBufSize = 1024;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
   TestCompletionCallback callback;
   rv = adapter.Read(read_buf.get(), kReadBufSize, callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -944,7 +944,7 @@
   base::RunLoop().RunUntilIdle();
 
   const int kReadBufSize = 1024;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
   TestCompletionCallback read_callback;
   rv = adapter.Read(read_buf.get(), kReadBufSize, read_callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -1022,7 +1022,7 @@
   KillerCallback callback(std::move(adapter));
 
   const int kReadBufSize = 1024;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
   rv = adapter_raw->Read(read_buf.get(), kReadBufSize, callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
@@ -1120,7 +1120,7 @@
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   const int kReadBufSize = 1024;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
   TestCompletionCallback callback;
   rv = adapter.Read(read_buf.get(), kReadBufSize, callback.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -1596,7 +1596,7 @@
 
   // Buffer larger than each MockRead.
   const int kReadBufSize = 1024;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
   TestCompletionCallback read_callback;
 
   int rv =
@@ -1678,7 +1678,7 @@
   run_loop.Run();
 
   const int kReadBufSize = 3;
-  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  auto read_buf = base::MakeRefCounted<IOBufferWithSize>(kReadBufSize);
   TestCompletionCallback read_callback;
 
   int rv =
diff --git a/net/websockets/websocket_basic_stream_test.cc b/net/websockets/websocket_basic_stream_test.cc
index db3e068..7a7cc7a 100644
--- a/net/websockets/websocket_basic_stream_test.cc
+++ b/net/websockets/websocket_basic_stream_test.cc
@@ -265,7 +265,7 @@
     const size_t payload_size =
         kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize +
                            WebSocketFrameHeader::kMaskingKeyLength);
-    auto buffer = base::MakeRefCounted<IOBuffer>(payload_size);
+    auto buffer = base::MakeRefCounted<IOBufferWithSize>(payload_size);
     frame_buffers_.push_back(buffer);
     memcpy(buffer->data(), kWriteFrame + kWriteFrameSize - payload_size,
            payload_size);
@@ -970,7 +970,7 @@
       std::make_unique<WebSocketFrame>(WebSocketFrameHeader::kOpCodeText);
   const std::string unmasked_payload = "graphics";
   const size_t payload_size = unmasked_payload.size();
-  auto buffer = base::MakeRefCounted<IOBuffer>(payload_size);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(payload_size);
   memcpy(buffer->data(), unmasked_payload.data(), payload_size);
   frame->payload = buffer->data();
   WebSocketFrameHeader& header = frame->header;
diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc
index df3e3c2a..f9004d5 100644
--- a/net/websockets/websocket_channel.cc
+++ b/net/websockets/websocket_channel.cc
@@ -719,7 +719,7 @@
     case WebSocketFrameHeader::kOpCodePing:
       DVLOG(1) << "Got Ping of size " << payload.size();
       if (state_ == CONNECTED) {
-        auto buffer = base::MakeRefCounted<IOBuffer>(payload.size());
+        auto buffer = base::MakeRefCounted<IOBufferWithSize>(payload.size());
         base::ranges::copy(payload, buffer->data());
         return SendFrameInternal(true, WebSocketFrameHeader::kOpCodePong,
                                  std::move(buffer), payload.size());
@@ -939,10 +939,10 @@
     // Special case: translate kWebSocketErrorNoStatusReceived into a Close
     // frame with no payload.
     DCHECK(reason.empty());
-    body = base::MakeRefCounted<IOBuffer>();
+    body = base::MakeRefCounted<IOBufferWithSize>();
   } else {
     const size_t payload_length = kWebSocketCloseCodeLength + reason.length();
-    body = base::MakeRefCounted<IOBuffer>(payload_length);
+    body = base::MakeRefCounted<IOBufferWithSize>(payload_length);
     size = payload_length;
     base::WriteBigEndian(body->data(), code);
     static_assert(sizeof(code) == kWebSocketCloseCodeLength,
diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc
index b7967bd..8454d532 100644
--- a/net/websockets/websocket_channel_test.cc
+++ b/net/websockets/websocket_channel_test.cc
@@ -368,7 +368,7 @@
     result_header.masked = (source_frame.masked == MASKED);
     result_header.payload_length = frame_length;
     if (source_frame.data) {
-      auto buffer = base::MakeRefCounted<IOBuffer>(frame_length);
+      auto buffer = base::MakeRefCounted<IOBufferWithSize>(frame_length);
       result_frame_data->push_back(buffer);
       std::copy(source_frame.data, source_frame.data + frame_length,
                 buffer->data());
@@ -605,7 +605,7 @@
   int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
                   CompletionOnceCallback callback) override {
     for (const auto& frame : *frames) {
-      auto buffer = base::MakeRefCounted<IOBuffer>(
+      auto buffer = base::MakeRefCounted<IOBufferWithSize>(
           static_cast<size_t>(frame->header.payload_length));
       std::copy(frame->payload, frame->payload + frame->header.payload_length,
                 buffer->data());
@@ -788,7 +788,7 @@
 // convenient to be able to specify data as a string, but the
 // WebSocketEventInterface requires the IOBuffer type.
 scoped_refptr<IOBuffer> AsIOBuffer(base::StringPiece s) {
-  auto buffer = base::MakeRefCounted<IOBuffer>(s.size());
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(s.size());
   base::ranges::copy(s, buffer->data());
   return buffer;
 }
@@ -2250,7 +2250,7 @@
   WebSocketFrameHeader& frame_header = frame->header;
   frame_header.final = true;
   frame_header.payload_length = kBinaryBlobSize;
-  auto buffer = base::MakeRefCounted<IOBuffer>(kBinaryBlobSize);
+  auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBinaryBlobSize);
   memcpy(buffer->data(), kBinaryBlob, kBinaryBlobSize);
   frame->payload = buffer->data();
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
diff --git a/printing/backend/win_helper.cc b/printing/backend/win_helper.cc
index b6254fef..fcd4532 100644
--- a/printing/backend/win_helper.cc
+++ b/printing/backend/win_helper.cc
@@ -9,6 +9,7 @@
 
 #include <algorithm>
 #include <memory>
+#include <string_view>
 
 #include "base/check_op.h"
 #include "base/containers/fixed_flat_set.h"
@@ -19,7 +20,6 @@
 #include "base/notreached.h"
 #include "base/numerics/checked_math.h"
 #include "base/numerics/safe_conversions.h"
-#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -472,7 +472,7 @@
 }
 
 bool DoesDriverDisplayFileDialogForPrinting(const std::string& printer_name) {
-  static constexpr auto kPortNames = base::MakeFixedFlatSet<base::WStringPiece>(
+  static constexpr auto kPortNames = base::MakeFixedFlatSet<std::wstring_view>(
       {kPrinterDriverPortFile, kPrinterDriverPortPrompt,
        kPrinterDriverPortFax});
   return kPortNames.contains(GetPrinterDriverPort(printer_name));
diff --git a/remoting/host/chromeos/remote_support_host_ash.cc b/remoting/host/chromeos/remote_support_host_ash.cc
index ceffbf96..ecaacb8 100644
--- a/remoting/host/chromeos/remote_support_host_ash.cc
+++ b/remoting/host/chromeos/remote_support_host_ash.cc
@@ -151,6 +151,7 @@
 }
 
 void RemoteSupportHostAsh::ReconnectToSession(SessionId session_id,
+                                              const std::string& access_token,
                                               StartSessionCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -167,7 +168,6 @@
 
   LOG(INFO) << "CRD: Retrieving details for reconnectable session id:"
             << session_id;
-  std::string access_token = "TODO(joedow): Provide real access token";
   session_storage_->RetrieveSession(base::BindOnce(
       &RemoteSupportHostAsh::OnSessionRetrieved, weak_ptr_factory_.GetWeakPtr(),
       session_id, access_token, std::move(callback)));
diff --git a/remoting/host/chromeos/remote_support_host_ash.h b/remoting/host/chromeos/remote_support_host_ash.h
index 36d93a5f..e56c507c 100644
--- a/remoting/host/chromeos/remote_support_host_ash.h
+++ b/remoting/host/chromeos/remote_support_host_ash.h
@@ -61,7 +61,9 @@
 
   // Allows the caller to resume the given remote support session.
   // `callback` is called with the result.
-  void ReconnectToSession(SessionId session_id, StartSessionCallback callback);
+  void ReconnectToSession(SessionId session_id,
+                          const std::string& access_token,
+                          StartSessionCallback callback);
 
  private:
   void StartSession(
diff --git a/remoting/host/chromeos/remote_support_host_ash_unittest.cc b/remoting/host/chromeos/remote_support_host_ash_unittest.cc
index 1b7ae3be..4286058 100644
--- a/remoting/host/chromeos/remote_support_host_ash_unittest.cc
+++ b/remoting/host/chromeos/remote_support_host_ash_unittest.cc
@@ -250,7 +250,8 @@
   mojom::StartSupportSessionResponsePtr ReconnectToSession(
       SessionId id = kEnterpriseSessionId) {
     TestFuture<mojom::StartSupportSessionResponsePtr> connect_result;
-    support_host().ReconnectToSession(id, connect_result.GetCallback());
+    support_host().ReconnectToSession(id, "faux access token",
+                                      connect_result.GetCallback());
     return connect_result.Take();
   }
 
diff --git a/remoting/host/it2me/it2me_confirmation_dialog_win.cc b/remoting/host/it2me/it2me_confirmation_dialog_win.cc
index 94b3526..f4016ff 100644
--- a/remoting/host/it2me/it2me_confirmation_dialog_win.cc
+++ b/remoting/host/it2me/it2me_confirmation_dialog_win.cc
@@ -2,12 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "remoting/host/it2me/it2me_confirmation_dialog.h"
+
 #include <windows.h>
 #include <commctrl.h>
 
 #include <cstdint>
 #include <memory>
 #include <string>
+#include <string_view>
 
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
@@ -17,7 +20,6 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
-#include "remoting/host/it2me/it2me_confirmation_dialog.h"
 #include "remoting/host/win/core_resource.h"
 #include "remoting/host/win/simple_task_dialog.h"
 
@@ -90,7 +92,7 @@
   std::wstring message_text =
       base::AsWString(base::i18n::MessageFormatter::FormatWithNumberedArgs(
           base::AsStringPiece16(
-              base::WStringPiece(message_stringw, string_length)),
+              std::wstring_view(message_stringw, string_length)),
           base::UTF8ToUTF16(remote_user_email)));
 
   task_dialog.set_message_text(message_text);
diff --git a/remoting/host/keyboard_layout_monitor_win.cc b/remoting/host/keyboard_layout_monitor_win.cc
index 636c1cee..70f7f6d 100644
--- a/remoting/host/keyboard_layout_monitor_win.cc
+++ b/remoting/host/keyboard_layout_monitor_win.cc
@@ -8,6 +8,7 @@
 #include <ime.h>
 
 #include <memory>
+#include <string_view>
 #include <utility>
 #include <vector>
 
@@ -286,7 +287,7 @@
         }
         // The key generated at least one character.
         key_actions[shift_level].set_character(
-            base::WideToUTF8(base::WStringPiece(char_buffer, size)));
+            base::WideToUTF8(std::wstring_view(char_buffer, size)));
         if (shift_level > 2) {
           has_altgr = true;
         }
diff --git a/sandbox/win/src/target_process.cc b/sandbox/win/src/target_process.cc
index 544d4925..d3c1324 100644
--- a/sandbox/win/src/target_process.cc
+++ b/sandbox/win/src/target_process.cc
@@ -12,6 +12,7 @@
 
 #include <limits>
 #include <memory>
+#include <string_view>
 #include <utility>
 #include <vector>
 
@@ -163,7 +164,7 @@
     //    operation and tests.
     //  * "LOCALAPPDATA": Needed for App Container processes.
     //  * "CHROME_CRASHPAD_PIPE_NAME": Needed for crashpad.
-    static constexpr base::WStringPiece to_keep[] = {
+    static constexpr std::wstring_view to_keep[] = {
         L"Path",
         L"SystemDrive",
         L"SystemRoot",
@@ -424,7 +425,7 @@
 // static
 std::wstring TargetProcess::FilterEnvironment(
     const wchar_t* env,
-    const base::span<const base::WStringPiece> to_keep) {
+    const base::span<const std::wstring_view> to_keep) {
   std::wstring result;
 
   // Iterate all of the environment strings.
diff --git a/sandbox/win/src/target_process.h b/sandbox/win/src/target_process.h
index b203e07..aea55b2 100644
--- a/sandbox/win/src/target_process.h
+++ b/sandbox/win/src/target_process.h
@@ -9,6 +9,7 @@
 #include <stdint.h>
 
 #include <memory>
+#include <string_view>
 
 #include "base/containers/span.h"
 #include "base/gtest_prod_util.h"
@@ -100,7 +101,7 @@
   // `to_keep`.
   static std::wstring FilterEnvironment(
       const wchar_t* env,
-      const base::span<const base::WStringPiece> to_keep);
+      const base::span<const std::wstring_view> to_keep);
 
   // Details of the target process.
   base::win::ScopedProcessInformation sandbox_process_info_;
diff --git a/sandbox/win/src/target_process_unittest.cc b/sandbox/win/src/target_process_unittest.cc
index 7c7c3eb..21bb672 100644
--- a/sandbox/win/src/target_process_unittest.cc
+++ b/sandbox/win/src/target_process_unittest.cc
@@ -5,6 +5,7 @@
 #include "sandbox/win/src/target_process.h"
 
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/strings/string_util.h"
@@ -35,7 +36,7 @@
                             '\0', 'C', '=', '4',  '\0', '\0'};
 
   // Empty filter should filter everything.
-  std::vector<base::WStringPiece> to_keep;
+  std::vector<std::wstring_view> to_keep;
   auto res = TargetProcess::FilterEnvironment(empty, to_keep);
   ExpectEnvironmentBlock({}, res);
 
diff --git a/services/cert_verifier/cert_verifier_creation.cc b/services/cert_verifier/cert_verifier_creation.cc
index 3cbbdd3..210c9a4d 100644
--- a/services/cert_verifier/cert_verifier_creation.cc
+++ b/services/cert_verifier/cert_verifier_creation.cc
@@ -73,20 +73,22 @@
 
   scoped_refptr<net::CertVerifyProc> CreateCertVerifyProc(
       scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
-      const CertVerifyProcFactory::ImplParams& impl_params) override {
+      const net::CertVerifyProc::ImplParams& impl_params,
+      const net::CertVerifyProc::InstanceParams& instance_params) override {
 #if BUILDFLAG(CHROME_ROOT_STORE_ONLY)
     return CreateNewCertVerifyProc(
         cert_net_fetcher, impl_params.crl_set,
-        base::OptionalToPtr(impl_params.root_store_data));
+        base::OptionalToPtr(impl_params.root_store_data), instance_params);
 #else
 #if BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL)
     if (impl_params.use_chrome_root_store) {
       return CreateNewCertVerifyProc(
           cert_net_fetcher, impl_params.crl_set,
-          base::OptionalToPtr(impl_params.root_store_data));
+          base::OptionalToPtr(impl_params.root_store_data), instance_params);
     }
 #endif
-    return CreateOldCertVerifyProc(cert_net_fetcher, impl_params.crl_set);
+    return CreateOldCertVerifyProc(cert_net_fetcher, impl_params.crl_set,
+                                   instance_params);
 #endif
   }
 
@@ -100,11 +102,12 @@
   // return a CertVerifyProc that supports that configuration.
   scoped_refptr<net::CertVerifyProc> CreateOldCertVerifyProc(
       scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
-      scoped_refptr<net::CRLSet> crl_set) {
+      scoped_refptr<net::CRLSet> crl_set,
+      const net::CertVerifyProc::InstanceParams& instance_params) {
 #if BUILDFLAG(IS_FUCHSIA)
-    return net::CreateCertVerifyProcBuiltin(std::move(cert_net_fetcher),
-                                            std::move(crl_set),
-                                            net::CreateSslSystemTrustStore());
+    return net::CreateCertVerifyProcBuiltin(
+        std::move(cert_net_fetcher), std::move(crl_set),
+        net::CreateSslSystemTrustStore(), instance_params);
 #else
     return net::CertVerifyProc::CreateSystemVerifyProc(
         std::move(cert_net_fetcher), std::move(crl_set));
@@ -118,7 +121,8 @@
   scoped_refptr<net::CertVerifyProc> CreateNewCertVerifyProc(
       scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
       scoped_refptr<net::CRLSet> crl_set,
-      const net::ChromeRootStoreData* root_store_data) {
+      const net::ChromeRootStoreData* root_store_data,
+      const net::CertVerifyProc::InstanceParams& instance_params) {
     std::unique_ptr<net::TrustStoreChrome> chrome_root =
         root_store_data
             ? std::make_unique<net::TrustStoreChrome>(*root_store_data)
@@ -151,9 +155,9 @@
     // tests that don't use threads otherwise.
     net::InitializeTrustStoreAndroid();
 #endif
-    return net::CreateCertVerifyProcBuiltin(std::move(cert_net_fetcher),
-                                            std::move(crl_set),
-                                            std::move(trust_store));
+    return net::CreateCertVerifyProcBuiltin(
+        std::move(cert_net_fetcher), std::move(crl_set), std::move(trust_store),
+        instance_params);
   }
 #endif  // BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
 
@@ -176,13 +180,15 @@
 std::unique_ptr<net::CertVerifierWithUpdatableProc> CreateCertVerifier(
     mojom::CertVerifierCreationParams* creation_params,
     scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
-    const net::CertVerifyProcFactory::ImplParams& impl_params) {
+    const net::CertVerifyProc::ImplParams& impl_params,
+    const net::CertVerifyProc::InstanceParams& instance_params) {
   DCHECK(cert_net_fetcher || !IsUsingCertNetFetcher());
 
   scoped_refptr<net::CertVerifyProcFactory> proc_factory =
       base::MakeRefCounted<CertVerifyProcFactoryImpl>(creation_params);
   return std::make_unique<net::MultiThreadedCertVerifier>(
-      proc_factory->CreateCertVerifyProc(cert_net_fetcher, impl_params),
+      proc_factory->CreateCertVerifyProc(cert_net_fetcher, impl_params,
+                                         instance_params),
       proc_factory);
 }
 
diff --git a/services/cert_verifier/cert_verifier_creation.h b/services/cert_verifier/cert_verifier_creation.h
index 1f2fe062..357b88d 100644
--- a/services/cert_verifier/cert_verifier_creation.h
+++ b/services/cert_verifier/cert_verifier_creation.h
@@ -29,7 +29,8 @@
 std::unique_ptr<net::CertVerifierWithUpdatableProc> CreateCertVerifier(
     mojom::CertVerifierCreationParams* creation_params,
     scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
-    const net::CertVerifyProcFactory::ImplParams& impl_params);
+    const net::CertVerifyProc::ImplParams& impl_params,
+    const net::CertVerifyProc::InstanceParams& instance_params);
 
 }  // namespace cert_verifier
 
diff --git a/services/cert_verifier/cert_verifier_service.cc b/services/cert_verifier/cert_verifier_service.cc
index e1f2c912..03657128 100644
--- a/services/cert_verifier/cert_verifier_service.cc
+++ b/services/cert_verifier/cert_verifier_service.cc
@@ -82,16 +82,20 @@
 
 CertVerifierServiceImpl::CertVerifierServiceImpl(
     std::unique_ptr<net::CertVerifierWithUpdatableProc> verifier,
-    mojo::PendingReceiver<mojom::CertVerifierService> receiver,
+    mojo::PendingReceiver<mojom::CertVerifierService> service_receiver,
+    mojo::PendingReceiver<mojom::CertVerifierServiceUpdater> updater_receiver,
     mojo::PendingRemote<mojom::CertVerifierServiceClient> client,
-    scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher)
-    : verifier_(std::move(verifier)),
-      receiver_(this, std::move(receiver)),
+    scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher,
+    net::CertVerifyProc::InstanceParams instance_params)
+    : instance_params_(std::move(instance_params)),
+      verifier_(std::move(verifier)),
+      service_receiver_(this, std::move(service_receiver)),
+      updater_receiver_(this, std::move(updater_receiver)),
       client_(std::move(client)),
       cert_net_fetcher_(std::move(cert_net_fetcher)) {
   // base::Unretained is safe because |this| owns |receiver_|, so deleting
   // |this| will prevent |receiver_| from calling this callback.
-  receiver_.set_disconnect_handler(
+  service_receiver_.set_disconnect_handler(
       base::BindRepeating(&CertVerifierServiceImpl::OnDisconnectFromService,
                           base::Unretained(this)));
   verifier_->AddObserver(this);
@@ -126,6 +130,18 @@
   }
 }
 
+void CertVerifierServiceImpl::UpdateAdditionalCertificates(
+    mojom::AdditionalCertificatesPtr additional_certificates) {
+  instance_params_.additional_trust_anchors =
+      additional_certificates->trust_anchors;
+  instance_params_.additional_untrusted_authorities =
+      additional_certificates->all_certificates;
+
+  verifier_->UpdateVerifyProcData(cert_net_fetcher_,
+                                  service_factory_impl_->get_impl_params(),
+                                  instance_params_);
+}
+
 void CertVerifierServiceImpl::SetCertVerifierServiceFactory(
     base::WeakPtr<cert_verifier::CertVerifierServiceFactoryImpl>
         service_factory_impl) {
@@ -133,8 +149,9 @@
 }
 
 void CertVerifierServiceImpl::UpdateVerifierData(
-    const net::CertVerifyProcFactory::ImplParams& impl_params) {
-  verifier_->UpdateVerifyProcData(cert_net_fetcher_, impl_params);
+    const net::CertVerifyProc::ImplParams& impl_params) {
+  verifier_->UpdateVerifyProcData(cert_net_fetcher_, impl_params,
+                                  instance_params_);
 }
 
 void CertVerifierServiceImpl::Verify(
diff --git a/services/cert_verifier/cert_verifier_service.h b/services/cert_verifier/cert_verifier_service.h
index 918678e..1f9abb8 100644
--- a/services/cert_verifier/cert_verifier_service.h
+++ b/services/cert_verifier/cert_verifier_service.h
@@ -18,6 +18,7 @@
 #include "net/cert/cert_verify_proc.h"
 #include "net/log/net_log_with_source.h"
 #include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"
+#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
 #include "services/network/public/mojom/cert_verifier_service.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 
@@ -35,13 +36,16 @@
 
 // This class will delete itself upon disconnection of its Mojo receiver.
 class CertVerifierServiceImpl : public mojom::CertVerifierService,
+                                public mojom::CertVerifierServiceUpdater,
                                 public net::CertVerifier::Observer {
  public:
   explicit CertVerifierServiceImpl(
       std::unique_ptr<net::CertVerifierWithUpdatableProc> verifier,
-      mojo::PendingReceiver<mojom::CertVerifierService> receiver,
+      mojo::PendingReceiver<mojom::CertVerifierService> service_receiver,
+      mojo::PendingReceiver<mojom::CertVerifierServiceUpdater> updater_receiver,
       mojo::PendingRemote<mojom::CertVerifierServiceClient> client,
-      scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher);
+      scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher,
+      net::CertVerifyProc::InstanceParams instance_params);
 
   // mojom::CertVerifierService implementation:
   void Verify(const net::CertVerifier::RequestParams& params,
@@ -54,6 +58,10 @@
       mojo::PendingRemote<mojom::URLLoaderFactoryConnector> reconnector)
       override;
 
+  // mojom::CertVerifierServiceUpdater implementation:
+  void UpdateAdditionalCertificates(
+      mojom::AdditionalCertificatesPtr additional_certificates) override;
+
   // Set a pointer to the CertVerifierServiceFactory so that it may be notified
   // when we are deleted.
   void SetCertVerifierServiceFactory(
@@ -61,8 +69,7 @@
           service_factory_impl);
 
   // Update the wrapped verifier with CRLSet and ChromeRootStoreData.
-  void UpdateVerifierData(
-      const net::CertVerifyProcFactory::ImplParams& impl_params);
+  void UpdateVerifierData(const net::CertVerifyProc::ImplParams& impl_params);
 
  private:
   ~CertVerifierServiceImpl() override;
@@ -72,8 +79,10 @@
 
   void OnDisconnectFromService();
 
+  net::CertVerifyProc::InstanceParams instance_params_;
   std::unique_ptr<net::CertVerifierWithUpdatableProc> verifier_;
-  mojo::Receiver<mojom::CertVerifierService> receiver_;
+  mojo::Receiver<mojom::CertVerifierService> service_receiver_;
+  mojo::Receiver<mojom::CertVerifierServiceUpdater> updater_receiver_;
   mojo::Remote<mojom::CertVerifierServiceClient> client_;
   scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher_;
   base::WeakPtr<cert_verifier::CertVerifierServiceFactoryImpl>
diff --git a/services/cert_verifier/cert_verifier_service_factory.cc b/services/cert_verifier/cert_verifier_service_factory.cc
index 28e978e..c37093da 100644
--- a/services/cert_verifier/cert_verifier_service_factory.cc
+++ b/services/cert_verifier/cert_verifier_service_factory.cc
@@ -44,10 +44,11 @@
 namespace {
 
 internal::CertVerifierServiceImpl* GetNewCertVerifierImpl(
-    mojo::PendingReceiver<mojom::CertVerifierService> receiver,
+    mojo::PendingReceiver<mojom::CertVerifierService> service_receiver,
+    mojo::PendingReceiver<mojom::CertVerifierServiceUpdater> updater_receiver,
     mojo::PendingRemote<mojom::CertVerifierServiceClient> client,
     mojom::CertVerifierCreationParamsPtr creation_params,
-    const net::CertVerifyProcFactory::ImplParams& impl_params,
+    const net::CertVerifyProc::ImplParams& impl_params,
     scoped_refptr<CertNetFetcherURLLoader>* out_cert_net_fetcher) {
   scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher;
 
@@ -58,8 +59,18 @@
     cert_net_fetcher = base::MakeRefCounted<CertNetFetcherURLLoader>();
   }
 
+  // Populate initial instance params from creation params.
+  net::CertVerifyProc::InstanceParams instance_params;
+  if (creation_params->initial_additional_certificates) {
+    instance_params.additional_trust_anchors =
+        creation_params->initial_additional_certificates->trust_anchors;
+    instance_params.additional_untrusted_authorities =
+        creation_params->initial_additional_certificates->all_certificates;
+  }
+
   std::unique_ptr<net::CertVerifierWithUpdatableProc> cert_verifier =
-      CreateCertVerifier(creation_params.get(), cert_net_fetcher, impl_params);
+      CreateCertVerifier(creation_params.get(), cert_net_fetcher, impl_params,
+                         instance_params);
 
   // As an optimization, if the CertNetFetcher isn't used by the CertVerifier,
   // shut it down immediately.
@@ -74,8 +85,9 @@
 
   // The service will delete itself upon disconnection.
   return new internal::CertVerifierServiceImpl(
-      std::move(cert_verifier), std::move(receiver), std::move(client),
-      std::move(cert_net_fetcher));
+      std::move(cert_verifier), std::move(service_receiver),
+      std::move(updater_receiver), std::move(client),
+      std::move(cert_net_fetcher), std::move(instance_params));
 }
 
 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
@@ -122,24 +134,27 @@
 CertVerifierServiceFactoryImpl::~CertVerifierServiceFactoryImpl() = default;
 
 void CertVerifierServiceFactoryImpl::GetNewCertVerifier(
-    mojo::PendingReceiver<mojom::CertVerifierService> receiver,
+    mojo::PendingReceiver<mojom::CertVerifierService> service_receiver,
+    mojo::PendingReceiver<mojom::CertVerifierServiceUpdater> updater_receiver,
     mojo::PendingRemote<mojom::CertVerifierServiceClient> client,
     mojom::CertVerifierCreationParamsPtr creation_params) {
-  internal::CertVerifierServiceImpl* service_impl =
-      GetNewCertVerifierImpl(std::move(receiver), std::move(client),
-                             std::move(creation_params), proc_params_,
-                             /*out_cert_net_fetcher=*/nullptr);
+  internal::CertVerifierServiceImpl* service_impl = GetNewCertVerifierImpl(
+      std::move(service_receiver), std::move(updater_receiver),
+      std::move(client), std::move(creation_params), proc_params_,
+      /*out_cert_net_fetcher=*/nullptr);
 
   verifier_services_.insert(service_impl);
   service_impl->SetCertVerifierServiceFactory(weak_factory_.GetWeakPtr());
 }
 
 void CertVerifierServiceFactoryImpl::GetNewCertVerifierForTesting(
-    mojo::PendingReceiver<mojom::CertVerifierService> receiver,
+    mojo::PendingReceiver<mojom::CertVerifierService> service_receiver,
+    mojo::PendingReceiver<mojom::CertVerifierServiceUpdater> updater_receiver,
     mojo::PendingRemote<mojom::CertVerifierServiceClient> client,
     mojom::CertVerifierCreationParamsPtr creation_params,
     scoped_refptr<CertNetFetcherURLLoader>* cert_net_fetcher_ptr) {
-  GetNewCertVerifierImpl(std::move(receiver), std::move(client),
+  GetNewCertVerifierImpl(std::move(service_receiver),
+                         std::move(updater_receiver), std::move(client),
                          std::move(creation_params), proc_params_,
                          cert_net_fetcher_ptr);
 }
diff --git a/services/cert_verifier/cert_verifier_service_factory.h b/services/cert_verifier/cert_verifier_service_factory.h
index 96cfe5a..8657426 100644
--- a/services/cert_verifier/cert_verifier_service_factory.h
+++ b/services/cert_verifier/cert_verifier_service_factory.h
@@ -40,7 +40,8 @@
 
   // mojom::CertVerifierServiceFactory implementation:
   void GetNewCertVerifier(
-      mojo::PendingReceiver<mojom::CertVerifierService> receiver,
+      mojo::PendingReceiver<mojom::CertVerifierService> service_receiver,
+      mojo::PendingReceiver<mojom::CertVerifierServiceUpdater> updater_receiver,
       mojo::PendingRemote<mojom::CertVerifierServiceClient> client,
       mojom::CertVerifierCreationParamsPtr creation_params) override;
 
@@ -49,6 +50,7 @@
   // CertNetFetcherURLLoader is in use.
   void GetNewCertVerifierForTesting(
       mojo::PendingReceiver<mojom::CertVerifierService> receiver,
+      mojo::PendingReceiver<mojom::CertVerifierServiceUpdater> updater_receiver,
       mojo::PendingRemote<mojom::CertVerifierServiceClient> client,
       mojom::CertVerifierCreationParamsPtr creation_params,
       scoped_refptr<CertNetFetcherURLLoader>* cert_net_fetcher_ptr);
@@ -70,13 +72,17 @@
   // Remove a CertVerifyService from needing updates to the Chrome Root Store.
   void RemoveService(internal::CertVerifierServiceImpl* service_impl);
 
+  const net::CertVerifyProc::ImplParams& get_impl_params() const {
+    return proc_params_;
+  }
+
  private:
   // Update all the `verifier_services_` with the current data.
   void UpdateVerifierServices();
 
   void OnCRLSetParsed(scoped_refptr<net::CRLSet> parsed_crl_set);
 
-  net::CertVerifyProcFactory::ImplParams proc_params_;
+  net::CertVerifyProc::ImplParams proc_params_;
 
   mojo::Receiver<mojom::CertVerifierServiceFactory> receiver_;
 
diff --git a/services/cert_verifier/cert_verifier_service_factory_unittest.cc b/services/cert_verifier/cert_verifier_service_factory_unittest.cc
index 8a83c557..2f16ee0e 100644
--- a/services/cert_verifier/cert_verifier_service_factory_unittest.cc
+++ b/services/cert_verifier/cert_verifier_service_factory_unittest.cc
@@ -163,6 +163,7 @@
 
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote.BindNewPipeAndPassReceiver(),
+      /*updater=*/mojo::NullReceiver(),
       cv_service_client.InitWithNewPipeAndPassRemote(),
       std::move(cv_creation_params));
 
@@ -215,6 +216,7 @@
 
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote.BindNewPipeAndPassReceiver(),
+      /*updater=*/mojo::NullReceiver(),
       cv_service_client.client_.BindNewPipeAndPassRemote(),
       std::move(cv_creation_params));
 
@@ -249,6 +251,7 @@
 
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote.BindNewPipeAndPassReceiver(),
+      /*updater=*/mojo::NullReceiver(),
       cv_service_client.client_.BindNewPipeAndPassRemote(),
       std::move(cv_creation_params));
 
@@ -333,6 +336,7 @@
 
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote.BindNewPipeAndPassReceiver(),
+      /*updater=*/mojo::NullReceiver(),
       cv_service_client.client_.BindNewPipeAndPassRemote(),
       std::move(cv_creation_params));
 
@@ -385,6 +389,7 @@
 
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote.BindNewPipeAndPassReceiver(),
+      /*updater=*/mojo::NullReceiver(),
       cv_service_client.client_.BindNewPipeAndPassRemote(),
       std::move(cv_creation_params));
 
@@ -529,18 +534,19 @@
 
 #endif  // BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
 
-class CertVerifierServiceFactoryCRLSetTest : public ::testing::Test {
+class CertVerifierServiceFactoryBuiltinVerifierTest : public ::testing::Test {
  public:
   void SetUp() override {
-    if (!SystemSupportsCRLSets()) {
-      GTEST_SKIP() << "Skipping test because system doesn't support CRLSets";
+    if (!SystemUsesBuiltinVerifier()) {
+      GTEST_SKIP()
+          << "Skipping test because system doesn't use builtin verifier";
     }
 
     ::testing::Test::SetUp();
   }
 
  private:
-  bool SystemSupportsCRLSets() {
+  bool SystemUsesBuiltinVerifier() {
 #if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(CHROME_ROOT_STORE_ONLY)
     return true;
 #elif BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL)
@@ -561,7 +567,7 @@
 
 // Test that a new Cert verifier will use an updated CRLSet if
 // one was already passed into CertVerifierServiceFactory.
-TEST_F(CertVerifierServiceFactoryCRLSetTest,
+TEST_F(CertVerifierServiceFactoryBuiltinVerifierTest,
        GetNewCertVerifierWithUpdatedCRLSet) {
   scoped_refptr<net::X509Certificate> test_root(net::ImportCertFromFile(
       net::GetTestCertsDirectory(), "root_ca_cert.pem"));
@@ -589,6 +595,7 @@
   // CRLSet already active.
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote.BindNewPipeAndPassReceiver(),
+      /*updater=*/mojo::NullReceiver(),
       cv_service_client.client_.BindNewPipeAndPassRemote(),
       std::move(cv_creation_params));
 
@@ -603,7 +610,7 @@
 
 // Test that an existing CertVerifierService will use an updated CRLSet if one
 // is provided to the CertVerifierServiceFactory
-TEST_F(CertVerifierServiceFactoryCRLSetTest,
+TEST_F(CertVerifierServiceFactoryBuiltinVerifierTest,
        UpdateExistingCertVerifierWithCRLSet) {
   scoped_refptr<net::X509Certificate> test_root(net::ImportCertFromFile(
       net::GetTestCertsDirectory(), "root_ca_cert.pem"));
@@ -626,6 +633,7 @@
 
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote.BindNewPipeAndPassReceiver(),
+      /*updater=*/mojo::NullReceiver(),
       cv_service_client.client_.BindNewPipeAndPassRemote(),
       std::move(cv_creation_params));
 
@@ -652,7 +660,7 @@
 }
 
 // Verifies newer CRLSets (by sequence number) are applied.
-TEST_F(CertVerifierServiceFactoryCRLSetTest, CRLSetIsUpdatedIfNewer) {
+TEST_F(CertVerifierServiceFactoryBuiltinVerifierTest, CRLSetIsUpdatedIfNewer) {
   scoped_refptr<net::X509Certificate> test_root(net::ImportCertFromFile(
       net::GetTestCertsDirectory(), "root_ca_cert.pem"));
   ASSERT_TRUE(test_root);
@@ -674,6 +682,7 @@
 
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote.BindNewPipeAndPassReceiver(),
+      /*updater=*/mojo::NullReceiver(),
       cv_service_client.client_.BindNewPipeAndPassRemote(),
       std::move(cv_creation_params));
 
@@ -716,7 +725,7 @@
 
 // Verifies that attempting to send an older CRLSet (by sequence number)
 // does not apply to existing or new contexts.
-TEST_F(CertVerifierServiceFactoryCRLSetTest, CRLSetDoesNotDowngrade) {
+TEST_F(CertVerifierServiceFactoryBuiltinVerifierTest, CRLSetDoesNotDowngrade) {
   scoped_refptr<net::X509Certificate> test_root(net::ImportCertFromFile(
       net::GetTestCertsDirectory(), "root_ca_cert.pem"));
   ASSERT_TRUE(test_root);
@@ -738,6 +747,7 @@
 
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote.BindNewPipeAndPassReceiver(),
+      /*updater=*/mojo::NullReceiver(),
       cv_service_client.client_.BindNewPipeAndPassRemote(),
       std::move(cv_creation_params));
 
@@ -778,12 +788,14 @@
   // Create a new CertVerifierService and ensure the latest CRLSet is still
   // applied.
   mojo::Remote<mojom::CertVerifierService> cv_service_remote2;
+  mojo::Remote<mojom::CertVerifierServiceUpdater> cv_service_updater_remote2;
   DummyCVServiceClient cv_service_client2;
   mojom::CertVerifierCreationParamsPtr cv_creation_params2 =
       mojom::CertVerifierCreationParams::New();
 
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote2.BindNewPipeAndPassReceiver(),
+      cv_service_updater_remote2.BindNewPipeAndPassReceiver(),
       cv_service_client2.client_.BindNewPipeAndPassRemote(),
       std::move(cv_creation_params2));
 
@@ -798,7 +810,7 @@
 
 // Verifies that attempting to send an invalid CRLSet does not affect existing
 // or new contexts.
-TEST_F(CertVerifierServiceFactoryCRLSetTest, BadCRLSetIgnored) {
+TEST_F(CertVerifierServiceFactoryBuiltinVerifierTest, BadCRLSetIgnored) {
   scoped_refptr<net::X509Certificate> test_root(net::ImportCertFromFile(
       net::GetTestCertsDirectory(), "root_ca_cert.pem"));
   ASSERT_TRUE(test_root);
@@ -820,6 +832,7 @@
 
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote.BindNewPipeAndPassReceiver(),
+      /*updater=*/mojo::NullReceiver(),
       cv_service_client.client_.BindNewPipeAndPassRemote(),
       std::move(cv_creation_params));
 
@@ -867,12 +880,14 @@
   // Create a new CertVerifierService and ensure the latest valid CRLSet is
   // still applied.
   mojo::Remote<mojom::CertVerifierService> cv_service_remote2;
+  mojo::Remote<mojom::CertVerifierServiceUpdater> cv_service_updater_remote2;
   DummyCVServiceClient cv_service_client2;
   mojom::CertVerifierCreationParamsPtr cv_creation_params2 =
       mojom::CertVerifierCreationParams::New();
 
   cv_service_factory_remote->GetNewCertVerifier(
       cv_service_remote2.BindNewPipeAndPassReceiver(),
+      cv_service_updater_remote2.BindNewPipeAndPassReceiver(),
       cv_service_client2.client_.BindNewPipeAndPassRemote(),
       std::move(cv_creation_params2));
 
@@ -885,4 +900,76 @@
   }
 }
 
+TEST_F(CertVerifierServiceFactoryBuiltinVerifierTest,
+       GetNewCertVerifierWithAdditionalCerts) {
+  auto [leaf1, intermediate1, root1] = net::CertBuilder::CreateSimpleChain3();
+  auto [leaf2, intermediate2, root2] = net::CertBuilder::CreateSimpleChain3();
+
+  mojo::Remote<mojom::CertVerifierServiceFactory> cv_service_factory_remote;
+  CertVerifierServiceFactoryImpl cv_service_factory_impl(
+      cv_service_factory_remote.BindNewPipeAndPassReceiver());
+
+  EnableChromeRootStoreIfOptional(&cv_service_factory_impl);
+
+  mojo::Remote<mojom::CertVerifierService> cv_service_remote;
+  mojo::Remote<mojom::CertVerifierServiceUpdater> cv_service_updater_remote;
+  DummyCVServiceClient cv_service_client;
+  mojom::CertVerifierCreationParamsPtr cv_creation_params =
+      mojom::CertVerifierCreationParams::New();
+  // Initial creation params supply `root1` as an additional trust anchor and
+  // `intermediate1` as an untrusted cert.
+  cv_creation_params->initial_additional_certificates =
+      mojom::AdditionalCertificates::New();
+  cv_creation_params->initial_additional_certificates->trust_anchors.push_back(
+      root1->GetX509Certificate());
+  cv_creation_params->initial_additional_certificates->all_certificates
+      .push_back(intermediate1->GetX509Certificate());
+
+  // Create the cert verifier. It should start with the additional trust
+  // anchors from the creation params already trusted.
+  cv_service_factory_remote->GetNewCertVerifier(
+      cv_service_remote.BindNewPipeAndPassReceiver(),
+      cv_service_updater_remote.BindNewPipeAndPassReceiver(),
+      cv_service_client.client_.BindNewPipeAndPassRemote(),
+      std::move(cv_creation_params));
+
+  // `leaf1` should be trusted and `leaf2` should not be trusted.
+  {
+    auto [net_error, result] = Verify(
+        cv_service_remote, leaf1->GetX509Certificate(), "www.example.com");
+    EXPECT_THAT(net_error, IsError(net::OK));
+  }
+  {
+    auto [net_error, result] = Verify(
+        cv_service_remote, leaf2->GetX509Certificate(), "www.example.com");
+    EXPECT_THAT(net_error, IsError(net::ERR_CERT_AUTHORITY_INVALID));
+  }
+
+  EXPECT_EQ(cv_service_client.changed_count_, 0u);
+
+  // Supply a new set of additional certificates with `root2` trusted this time.
+  auto new_additional_certificates = mojom::AdditionalCertificates::New();
+  new_additional_certificates->trust_anchors.push_back(
+      root2->GetX509Certificate());
+  new_additional_certificates->all_certificates.push_back(
+      intermediate2->GetX509Certificate());
+  cv_service_updater_remote->UpdateAdditionalCertificates(
+      std::move(new_additional_certificates));
+
+  // Client should have received notification of the update.
+  EXPECT_NO_FATAL_FAILURE(cv_service_client.WaitForCertVerifierChange(1u));
+
+  // Now `leaf1` should not be trusted and `leaf2` should be trusted.
+  {
+    auto [net_error, result] = Verify(
+        cv_service_remote, leaf1->GetX509Certificate(), "www.example.com");
+    EXPECT_THAT(net_error, IsError(net::ERR_CERT_AUTHORITY_INVALID));
+  }
+  {
+    auto [net_error, result] = Verify(
+        cv_service_remote, leaf2->GetX509Certificate(), "www.example.com");
+    EXPECT_THAT(net_error, IsError(net::OK));
+  }
+}
+
 }  // namespace cert_verifier
diff --git a/services/cert_verifier/cert_verifier_service_unittest.cc b/services/cert_verifier/cert_verifier_service_unittest.cc
index beb52bcaa..68be6ed 100644
--- a/services/cert_verifier/cert_verifier_service_unittest.cc
+++ b/services/cert_verifier/cert_verifier_service_unittest.cc
@@ -111,7 +111,8 @@
   void RemoveObserver(Observer* observer) override { observer_ = nullptr; }
   void UpdateVerifyProcData(
       scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
-      const net::CertVerifyProcFactory::ImplParams& impl_params) override {
+      const net::CertVerifyProc::ImplParams& impl_params,
+      const net::CertVerifyProc::InstanceParams& instance_params) override {
     ADD_FAILURE() << "not handled";
   }
 
@@ -200,8 +201,10 @@
     (void)new internal::CertVerifierServiceImpl(
         base::WrapUnique(dummy_cv_.get()),
         cv_service_remote_.BindNewPipeAndPassReceiver(),
+        cv_service_updater_remote_.BindNewPipeAndPassReceiver(),
         cv_service_client_.BindNewPipeAndPassRemote(),
-        /*cert_net_fetcher=*/nullptr);
+        /*cert_net_fetcher=*/nullptr,
+        /*instance_params=*/{});
   }
 
   void SetUp() override { ASSERT_TRUE(GetTestCert()); }
@@ -283,6 +286,7 @@
   base::test::TaskEnvironment task_environment_;
 
   mojo::Remote<mojom::CertVerifierService> cv_service_remote_;
+  mojo::Remote<mojom::CertVerifierServiceUpdater> cv_service_updater_remote_;
   mojo::Receiver<mojom::CertVerifierServiceClient> cv_service_client_;
   unsigned cv_service_client_changed_count_ = 0;
   raw_ptr<DummyCertVerifier> dummy_cv_;
diff --git a/services/cert_verifier/integration_tests/network_context_unittest.cc b/services/cert_verifier/integration_tests/network_context_unittest.cc
index a30610a..5727515 100644
--- a/services/cert_verifier/integration_tests/network_context_unittest.cc
+++ b/services/cert_verifier/integration_tests/network_context_unittest.cc
@@ -37,6 +37,7 @@
   mojo::PendingReceiver<mojom::CertVerifierServiceClient> cert_verifier_client;
   cert_verifier_service_factory->GetNewCertVerifier(
       cert_verifier_remote.InitWithNewPipeAndPassReceiver(),
+      /*updater=*/mojo::NullReceiver(),
       cert_verifier_client.InitWithNewPipeAndPassRemote(),
       std::move(creation_params));
   return network::mojom::CertVerifierServiceRemoteParams::New(
diff --git a/services/cert_verifier/integration_tests/network_service_unittest.cc b/services/cert_verifier/integration_tests/network_service_unittest.cc
index e12dda4..137e1680 100644
--- a/services/cert_verifier/integration_tests/network_service_unittest.cc
+++ b/services/cert_verifier/integration_tests/network_service_unittest.cc
@@ -66,6 +66,7 @@
     // Create a cert verifier service.
     cert_verifier_service_impl_.GetNewCertVerifierForTesting(
         cv_service_remote.InitWithNewPipeAndPassReceiver(),
+        /*updater_receiver=*/mojo::NullReceiver(),
         cv_service_client.InitWithNewPipeAndPassRemote(),
         mojom::CertVerifierCreationParams::New(),
         &cert_net_fetcher_url_loader_);
diff --git a/services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom b/services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom
index 6cd79e3d..6a4c0a6 100644
--- a/services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom
+++ b/services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom
@@ -8,6 +8,7 @@
 import "mojo/public/mojom/base/file_path.mojom";
 import "mojo/public/mojom/base/read_only_buffer.mojom";
 import "services/network/public/mojom/cert_verifier_service.mojom";
+import "services/network/public/mojom/network_param.mojom";
 
 // Parameters to specify how the net::CertVerifier and net::CertVerifyProc
 // objects should be instantiated.
@@ -26,6 +27,10 @@
   // isn't opened multiple times for NetworkContexts in the same profie.
   [EnableIf=is_chromeos_ash]
   string username_hash;
+
+  // Initial additional certificates that will be used for certificate
+  // validation.
+  AdditionalCertificates? initial_additional_certificates;
 };
 
 // Serialized copy of the Chrome Root store.
@@ -54,6 +59,7 @@
   // Gets a new CertVerifierService, which //net code can interface with using
   // cert_verifier::MojoCertVerifier.
   GetNewCertVerifier(pending_receiver<CertVerifierService> receiver,
+                     pending_receiver<CertVerifierServiceUpdater>? updater,
                      pending_remote<CertVerifierServiceClient> client,
                      CertVerifierCreationParams? creation_params);
 
diff --git a/services/device/hid/hid_service_win.cc b/services/device/hid/hid_service_win.cc
index aefc6d1..0a3437d0 100644
--- a/services/device/hid/hid_service_win.cc
+++ b/services/device/hid/hid_service_win.cc
@@ -4,6 +4,8 @@
 
 #include "services/device/hid/hid_service_win.h"
 
+#include <string_view>
+
 #define INITGUID
 
 #include <dbt.h>
@@ -241,7 +243,7 @@
   instance_id = base::ToLowerASCII(*instance_id);
   // Remove trailing NUL bytes.
   return std::wstring(base::TrimString(
-      *instance_id, base::WStringPiece(L"\0", 1), base::TRIM_TRAILING));
+      *instance_id, std::wstring_view(L"\0", 1), base::TRIM_TRAILING));
 }
 
 mojom::HidReportItemPtr CreateHidReportItem(
@@ -380,7 +382,7 @@
   // HidD_GetProductString is guaranteed to write a NUL-terminated string into
   // |buffer|. The characters following the string were value-initialized by
   // base::WriteInto and are also NUL. Trim the trailing NUL characters.
-  buffer = std::wstring(base::TrimString(buffer, base::WStringPiece(L"\0", 1),
+  buffer = std::wstring(base::TrimString(buffer, std::wstring_view(L"\0", 1),
                                          base::TRIM_TRAILING));
   return base::SysWideToUTF8(buffer);
 }
@@ -398,7 +400,7 @@
   // HidD_GetSerialNumberString is guaranteed to write a NUL-terminated string
   // into |buffer|. The characters following the string were value-initialized
   // by base::WriteInto and are also NUL. Trim the trailing NUL characters.
-  buffer = std::wstring(base::TrimString(buffer, base::WStringPiece(L"\0", 1),
+  buffer = std::wstring(base::TrimString(buffer, std::wstring_view(L"\0", 1),
                                          base::TRIM_TRAILING));
   return base::SysWideToUTF8(buffer);
 }
diff --git a/services/device/usb/usb_device_handle_win.cc b/services/device/usb/usb_device_handle_win.cc
index a33e6ef..b87eaa29 100644
--- a/services/device/usb/usb_device_handle_win.cc
+++ b/services/device/usb/usb_device_handle_win.cc
@@ -14,6 +14,7 @@
 #include <memory>
 #include <numeric>
 #include <string>
+#include <string_view>
 #include <utility>
 #include <vector>
 
@@ -44,7 +45,7 @@
 
 namespace {
 
-const base::WStringPiece kWinUsbDriverName = L"winusb";
+const std::wstring_view kWinUsbDriverName = L"winusb";
 
 uint8_t BuildRequestFlags(UsbTransferDirection direction,
                           UsbControlTransferType request_type,
diff --git a/services/device/usb/usb_service_win.cc b/services/device/usb/usb_service_win.cc
index 3dee7e03..52298df 100644
--- a/services/device/usb/usb_service_win.cc
+++ b/services/device/usb/usb_service_win.cc
@@ -7,6 +7,8 @@
 // windows.h must be included first.
 #include <windows.h>
 
+#include <string_view>
+
 #define INITGUID
 
 #include <devpkey.h>
@@ -22,7 +24,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/scoped_generic.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
@@ -168,7 +169,7 @@
   }
 
   // Windows string list properties use a NUL character as the delimiter.
-  return base::SplitString(buffer, base::WStringPiece(L"\0", 1),
+  return base::SplitString(buffer, std::wstring_view(L"\0", 1),
                            base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
 }
 
@@ -180,7 +181,7 @@
 
   // Windows pads this string with a variable number of NUL bytes for no
   // discernible reason.
-  return std::wstring(base::TrimString(*property, base::WStringPiece(L"\0", 1),
+  return std::wstring(base::TrimString(*property, std::wstring_view(L"\0", 1),
                                        base::TRIM_TRAILING));
 }
 
diff --git a/services/network/cert_verifier_with_trust_anchors.cc b/services/network/cert_verifier_with_trust_anchors.cc
index 40028af..8c11f13 100644
--- a/services/network/cert_verifier_with_trust_anchors.cc
+++ b/services/network/cert_verifier_with_trust_anchors.cc
@@ -9,11 +9,8 @@
 #include "base/check_op.h"
 #include "base/functional/bind.h"
 #include "net/base/net_errors.h"
-#include "net/cert/caching_cert_verifier.h"
 #include "net/cert/cert_verifier.h"
-#include "net/cert/cert_verify_proc.h"
-#include "net/cert/coalescing_cert_verifier.h"
-#include "net/cert/multi_threaded_cert_verifier.h"
+#include "net/cert/cert_verify_result.h"
 
 namespace network {
 
@@ -38,20 +35,6 @@
   std::move(completion_callback).Run(error);
 }
 
-net::CertVerifier::Config ExtendTrustAnchorsAndTempCerts(
-    const net::CertVerifier::Config& config,
-    const net::CertificateList& trust_anchors,
-    const net::CertificateList& untrusted_authorities) {
-  net::CertVerifier::Config new_config = config;
-  new_config.additional_trust_anchors.insert(
-      new_config.additional_trust_anchors.begin(), trust_anchors.begin(),
-      trust_anchors.end());
-  new_config.additional_untrusted_authorities.insert(
-      new_config.additional_untrusted_authorities.begin(),
-      untrusted_authorities.begin(), untrusted_authorities.end());
-  return new_config;
-}
-
 }  // namespace
 
 CertVerifierWithTrustAnchors::CertVerifierWithTrustAnchors(
@@ -68,23 +51,6 @@
     std::unique_ptr<net::CertVerifier> delegate) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   delegate_ = std::move(delegate);
-  delegate_->SetConfig(ExtendTrustAnchorsAndTempCerts(
-      orig_config_, trust_anchors_, untrusted_authorities_));
-}
-
-void CertVerifierWithTrustAnchors::SetAdditionalCerts(
-    const net::CertificateList& trust_anchors,
-    const net::CertificateList& untrusted_authorities) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  if (std::tie(trust_anchors, untrusted_authorities) ==
-      std::tie(trust_anchors_, untrusted_authorities_))
-    return;
-  trust_anchors_ = trust_anchors;
-  untrusted_authorities_ = untrusted_authorities;
-  if (!delegate_)
-    return;
-  delegate_->SetConfig(ExtendTrustAnchorsAndTempCerts(
-      orig_config_, trust_anchors_, untrusted_authorities_));
 }
 
 int CertVerifierWithTrustAnchors::Verify(
@@ -108,9 +74,7 @@
 
 void CertVerifierWithTrustAnchors::SetConfig(const Config& config) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  orig_config_ = config;
-  delegate_->SetConfig(ExtendTrustAnchorsAndTempCerts(
-      orig_config_, trust_anchors_, untrusted_authorities_));
+  delegate_->SetConfig(config);
 }
 
 void CertVerifierWithTrustAnchors::AddObserver(Observer* observer) {
diff --git a/services/network/cert_verifier_with_trust_anchors.h b/services/network/cert_verifier_with_trust_anchors.h
index e49fd5d..925f3b84 100644
--- a/services/network/cert_verifier_with_trust_anchors.h
+++ b/services/network/cert_verifier_with_trust_anchors.h
@@ -24,8 +24,8 @@
 
 namespace network {
 
-// Wraps a net::CertVerifier to make it use the additional trust anchors
-// configured by the ONC user policy.
+// Wraps a net::CertVerifier to run a callback if the additional trust anchors
+// configured by the ONC user policy are used.
 class COMPONENT_EXPORT(NETWORK_SERVICE) CertVerifierWithTrustAnchors
     : public net::CertVerifier {
  public:
@@ -46,11 +46,6 @@
   // this method.
   void InitializeOnIOThread(std::unique_ptr<net::CertVerifier> delegate);
 
-  // Sets the additional trust anchors and untrusted authorities to be
-  // considered as intermediates.
-  void SetAdditionalCerts(const net::CertificateList& trust_anchors,
-                          const net::CertificateList& untrusted_authorities);
-
   // CertVerifier:
   int Verify(const RequestParams& params,
              net::CertVerifyResult* verify_result,
@@ -62,9 +57,6 @@
   void RemoveObserver(Observer* observer) override;
 
  private:
-  net::CertVerifier::Config orig_config_;
-  net::CertificateList trust_anchors_;
-  net::CertificateList untrusted_authorities_;
   base::RepeatingClosure anchor_used_callback_;
   std::unique_ptr<CertVerifier> delegate_;
   THREAD_CHECKER(thread_checker_);
diff --git a/services/network/cert_verifier_with_trust_anchors_unittest.cc b/services/network/cert_verifier_with_trust_anchors_unittest.cc
index 16accf2..e6727a9 100644
--- a/services/network/cert_verifier_with_trust_anchors_unittest.cc
+++ b/services/network/cert_verifier_with_trust_anchors_unittest.cc
@@ -16,14 +16,10 @@
 #include "base/test/task_environment.h"
 #include "crypto/nss_util_internal.h"
 #include "net/base/test_completion_callback.h"
-#include "net/cert/caching_cert_verifier.h"
 #include "net/cert/cert_net_fetcher.h"
 #include "net/cert/cert_verify_proc.h"
-#include "net/cert/cert_verify_proc_builtin.h"
 #include "net/cert/cert_verify_result.h"
-#include "net/cert/coalescing_cert_verifier.h"
 #include "net/cert/mock_cert_verifier.h"
-#include "net/cert/multi_threaded_cert_verifier.h"
 #include "net/cert/x509_certificate.h"
 #include "net/log/net_log_with_source.h"
 #include "net/test/cert_test_util.h"
@@ -32,58 +28,6 @@
 
 namespace network {
 
-// Wraps a net::MockCertVerifier. When SetConfig() is called with trust anchors,
-// this sets |server_cert_| to pass cert verification using an additional trust
-// anchor. Otherwise |server_cert_| wil fail cert verification with
-// net::ERR_CERT_AUTHORITY_INVALID.
-class WrappedMockCertVerifier : public net::CertVerifier {
- public:
-  explicit WrappedMockCertVerifier(
-      scoped_refptr<net::X509Certificate> server_cert)
-      : server_cert_(std::move(server_cert)) {
-    mock_cert_verifier_.set_async(true);
-  }
-
-  // net::CertVerifier implementation:
-  int Verify(const RequestParams& params,
-             net::CertVerifyResult* verify_result,
-             net::CompletionOnceCallback callback,
-             std::unique_ptr<Request>* out_req,
-             const net::NetLogWithSource& net_log) override {
-    return mock_cert_verifier_.Verify(params, verify_result,
-                                      std::move(callback), out_req, net_log);
-  }
-  void SetConfig(const Config& config) override {
-    mock_cert_verifier_.ClearRules();
-
-    int net_err;
-    net::CertVerifyResult verify_result;
-    if (config.additional_trust_anchors.empty()) {
-      net_err = net::ERR_CERT_AUTHORITY_INVALID;
-    } else {
-      net_err = net::OK;
-      verify_result.is_issued_by_additional_trust_anchor = true;
-    }
-
-    verify_result.verified_cert = server_cert_;
-    verify_result.cert_status = net::MapNetErrorToCertStatus(net_err);
-
-    mock_cert_verifier_.AddResultForCert(server_cert_, verify_result, net_err);
-
-    mock_cert_verifier_.SetConfig(config);
-  }
-  void AddObserver(Observer* observer) override {
-    mock_cert_verifier_.AddObserver(observer);
-  }
-  void RemoveObserver(Observer* observer) override {
-    mock_cert_verifier_.RemoveObserver(observer);
-  }
-
- private:
-  scoped_refptr<net::X509Certificate> server_cert_;
-  net::MockCertVerifier mock_cert_verifier_;
-};
-
 class CertVerifierWithTrustAnchorsTest : public testing::Test {
  public:
   CertVerifierWithTrustAnchorsTest()
@@ -105,13 +49,15 @@
             &CertVerifierWithTrustAnchorsTest::OnTrustAnchorUsed,
             base::Unretained(this)));
 
-    cert_verifier_->InitializeOnIOThread(
-        std::make_unique<net::CachingCertVerifier>(
-            std::make_unique<net::CoalescingCertVerifier>(
-                std::make_unique<WrappedMockCertVerifier>(test_server_cert_))));
+    auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+    mock_cert_verifier_ = mock_cert_verifier.get();
+    mock_cert_verifier_->set_async(true);
+    mock_cert_verifier_->set_default_result(net::ERR_CERT_AUTHORITY_INVALID);
+    cert_verifier_->InitializeOnIOThread(std::move(mock_cert_verifier));
   }
 
   void TearDown() override {
+    mock_cert_verifier_ = nullptr;
     // Destroy |cert_verifier_| before destroying the TaskEnvironment, otherwise
     // BrowserThread::CurrentlyOn checks fail.
     cert_verifier_.reset();
@@ -145,7 +91,7 @@
   scoped_refptr<net::X509Certificate> test_server_cert_;
   net::CertificateList test_ca_cert_list_;
   std::unique_ptr<network::CertVerifierWithTrustAnchors> cert_verifier_;
-  scoped_refptr<net::CertVerifyProc> cert_verify_proc_;
+  raw_ptr<net::MockCertVerifier> mock_cert_verifier_;
 
  private:
   void OnTrustAnchorUsed() { trust_anchor_used_ = true; }
@@ -173,10 +119,14 @@
   }
   EXPECT_FALSE(WasTrustAnchorUsedAndReset());
 
-  // Verify() again with the additional trust anchors.
-  cert_verifier_->SetAdditionalCerts(test_ca_cert_list_,
-                                     net::CertificateList());
+  // Verify() again with the cert configured as non-policy provided trust
+  // anchor.
   {
+    net::CertVerifyResult mock_verify_result;
+    mock_verify_result.is_issued_by_additional_trust_anchor = false;
+    mock_verify_result.verified_cert = test_server_cert_;
+    mock_cert_verifier_->AddResultForCert(test_server_cert_, mock_verify_result,
+                                          net::OK);
     net::CertVerifyResult verify_result;
     net::TestCompletionCallback callback;
     std::unique_ptr<net::CertVerifier::Request> request;
@@ -187,79 +137,16 @@
     error = callback.WaitForResult();
     EXPECT_EQ(net::OK, error);
   }
-  EXPECT_TRUE(WasTrustAnchorUsedAndReset());
-
-  // Verify() again with the additional trust anchors will hit the cache.
-  cert_verifier_->SetAdditionalCerts(test_ca_cert_list_,
-                                     net::CertificateList());
-  {
-    net::CertVerifyResult verify_result;
-    net::TestCompletionCallback callback;
-    std::unique_ptr<net::CertVerifier::Request> request;
-    int error =
-        VerifyTestServerCert(callback.callback(), &verify_result, &request);
-    EXPECT_EQ(net::OK, error);
-  }
-  EXPECT_TRUE(WasTrustAnchorUsedAndReset());
-
-  // Verifying after removing the trust anchors should now fail.
-  cert_verifier_->SetAdditionalCerts(net::CertificateList(),
-                                     net::CertificateList());
-  {
-    net::CertVerifyResult verify_result;
-    net::TestCompletionCallback callback;
-    std::unique_ptr<net::CertVerifier::Request> request;
-    int error =
-        VerifyTestServerCert(callback.callback(), &verify_result, &request);
-    // Note: Changing the trust anchors should flush the cache.
-    ASSERT_EQ(net::ERR_IO_PENDING, error);
-    EXPECT_TRUE(request);
-    error = callback.WaitForResult();
-    EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
-  }
-  // The additional trust anchors were reset, thus |cert_verifier_| should not
-  // signal it's usage anymore.
-  EXPECT_FALSE(WasTrustAnchorUsedAndReset());
-}
-
-TEST_F(CertVerifierWithTrustAnchorsTest,
-       VerifyUsesAdditionalTrustAnchorsAfterConfigChange) {
-  // |test_server_cert_| is untrusted, so Verify() fails.
-  {
-    net::CertVerifyResult verify_result;
-    net::TestCompletionCallback callback;
-    std::unique_ptr<net::CertVerifier::Request> request;
-    int error =
-        VerifyTestServerCert(callback.callback(), &verify_result, &request);
-    ASSERT_EQ(net::ERR_IO_PENDING, error);
-    EXPECT_TRUE(request);
-    error = callback.WaitForResult();
-    EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
-  }
   EXPECT_FALSE(WasTrustAnchorUsedAndReset());
 
-  // Verify() again with the additional trust anchors.
-  cert_verifier_->SetAdditionalCerts(test_ca_cert_list_,
-                                     net::CertificateList());
+  // Verify() again with the cert configured as an additional trust anchor.
   {
-    net::CertVerifyResult verify_result;
-    net::TestCompletionCallback callback;
-    std::unique_ptr<net::CertVerifier::Request> request;
-    int error =
-        VerifyTestServerCert(callback.callback(), &verify_result, &request);
-    ASSERT_EQ(net::ERR_IO_PENDING, error);
-    EXPECT_TRUE(request);
-    error = callback.WaitForResult();
-    EXPECT_EQ(net::OK, error);
-  }
-  EXPECT_TRUE(WasTrustAnchorUsedAndReset());
-
-  // Change the configuration to enable SHA-1, which should still use the
-  // additional trust anchors.
-  net::CertVerifier::Config config;
-  config.enable_sha1_local_anchors = true;
-  cert_verifier_->SetConfig(config);
-  {
+    net::CertVerifyResult mock_verify_result;
+    mock_verify_result.is_issued_by_additional_trust_anchor = true;
+    mock_verify_result.verified_cert = test_server_cert_;
+    mock_cert_verifier_->ClearRules();
+    mock_cert_verifier_->AddResultForCert(test_server_cert_, mock_verify_result,
+                                          net::OK);
     net::CertVerifyResult verify_result;
     net::TestCompletionCallback callback;
     std::unique_ptr<net::CertVerifier::Request> request;
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 372ba83..6edd2b51 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -1471,25 +1471,6 @@
   network_delegate_->set_enable_referrers(enable_referrers);
 }
 
-#if BUILDFLAG(IS_CHROMEOS)
-void NetworkContext::UpdateAdditionalCertificates(
-    mojom::AdditionalCertificatesPtr additional_certificates) {
-  if (!cert_verifier_with_trust_anchors_) {
-    CHECK(g_cert_verifier_for_testing);
-    return;
-  }
-  if (!additional_certificates) {
-    cert_verifier_with_trust_anchors_->SetAdditionalCerts(
-        net::CertificateList(), net::CertificateList());
-    return;
-  }
-
-  cert_verifier_with_trust_anchors_->SetAdditionalCerts(
-      additional_certificates->trust_anchors,
-      additional_certificates->all_certificates);
-}
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
 #if BUILDFLAG(IS_CT_SUPPORTED)
 void NetworkContext::SetCTPolicy(mojom::CTPolicyPtr ct_policy) {
   if (!require_ct_delegate_)
@@ -2458,11 +2439,12 @@
             std::move(cert_verifier)));
 
 #if BUILDFLAG(IS_CHROMEOS)
+    // TODO(https://crbug.com/1477317): The TrustAnchorUsed callback should
+    // work on all platforms. (Also consider whether this wrapper is the best
+    // way to handle this or if it should be refactored.)
     cert_verifier_with_trust_anchors_ =
         new CertVerifierWithTrustAnchors(base::BindRepeating(
             &NetworkContext::TrustAnchorUsed, base::Unretained(this)));
-    UpdateAdditionalCertificates(
-        std::move(params_->initial_additional_certificates));
     cert_verifier_with_trust_anchors_->InitializeOnIOThread(
         std::move(cert_verifier));
     cert_verifier = base::WrapUnique(cert_verifier_with_trust_anchors_.get());
diff --git a/services/network/network_context.h b/services/network/network_context.h
index 7e6ae6f9..dca9e11a 100644
--- a/services/network/network_context.h
+++ b/services/network/network_context.h
@@ -316,10 +316,6 @@
                             mojom::NetworkConditionsPtr conditions) override;
   void SetAcceptLanguage(const std::string& new_accept_language) override;
   void SetEnableReferrers(bool enable_referrers) override;
-#if BUILDFLAG(IS_CHROMEOS)
-  void UpdateAdditionalCertificates(
-      mojom::AdditionalCertificatesPtr additional_certificates) override;
-#endif
 #if BUILDFLAG(IS_CT_SUPPORTED)
   void SetCTPolicy(mojom::CTPolicyPtr ct_policy) override;
   void MaybeEnqueueSCTReport(
diff --git a/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.cc b/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.cc
index e39edd7b..38a2ec3 100644
--- a/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.cc
+++ b/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.cc
@@ -32,23 +32,11 @@
                   net::CertVerifier::Config>::
     Read(cert_verifier::mojom::CertVerifierConfigDataView data,
          net::CertVerifier::Config* config) {
-  std::vector<scoped_refptr<net::X509Certificate>> additional_trust_anchors;
-  std::vector<scoped_refptr<net::X509Certificate>>
-      additional_untrusted_authorities;
-  if (!data.ReadAdditionalTrustAnchors(&additional_trust_anchors) ||
-      !data.ReadAdditionalUntrustedAuthorities(
-          &additional_untrusted_authorities)) {
-    return false;
-  }
-
   config->enable_rev_checking = data.enable_rev_checking();
   config->require_rev_checking_local_anchors =
       data.require_rev_checking_local_anchors();
   config->enable_sha1_local_anchors = data.enable_sha1_local_anchors();
   config->disable_symantec_enforcement = data.disable_symantec_enforcement();
-  config->additional_trust_anchors = std::move(additional_trust_anchors);
-  config->additional_untrusted_authorities =
-      std::move(additional_untrusted_authorities);
   return true;
 }
 
diff --git a/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.h b/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.h
index f2fc57712..c0f6077 100644
--- a/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.h
+++ b/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.h
@@ -57,14 +57,6 @@
       const net::CertVerifier::Config& config) {
     return config.disable_symantec_enforcement;
   }
-  static const std::vector<scoped_refptr<net::X509Certificate>>&
-  additional_trust_anchors(const net::CertVerifier::Config& config) {
-    return config.additional_trust_anchors;
-  }
-  static const std::vector<scoped_refptr<net::X509Certificate>>&
-  additional_untrusted_authorities(const net::CertVerifier::Config& config) {
-    return config.additional_untrusted_authorities;
-  }
 
   static bool Read(cert_verifier::mojom::CertVerifierConfigDataView data,
                    net::CertVerifier::Config* config);
diff --git a/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc b/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
index 8e28502b2..f4a99b3 100644
--- a/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
+++ b/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
@@ -39,19 +39,6 @@
 }
 
 namespace {
-bool CertificateListsEqual(const net::CertificateList& cert_list1,
-                           const net::CertificateList& cert_list2) {
-  if (cert_list1.size() != cert_list2.size())
-    return false;
-
-  std::set<net::SHA256HashValue> fingerprints1, fingerprints2;
-  for (size_t i = 0; i < cert_list1.size(); i++) {
-    fingerprints1.insert(cert_list1[i]->CalculateChainFingerprint256());
-    fingerprints2.insert(cert_list2[i]->CalculateChainFingerprint256());
-  }
-
-  return fingerprints1 == fingerprints2;
-}
 
 bool ConfigsEqual(const net::CertVerifier::Config& config1,
                   const net::CertVerifier::Config& config2) {
@@ -65,14 +52,6 @@
                config2.disable_symantec_enforcement))
     return false;
 
-  if (!CertificateListsEqual(config1.additional_trust_anchors,
-                             config2.additional_trust_anchors))
-    return false;
-
-  if (!CertificateListsEqual(config1.additional_untrusted_authorities,
-                             config2.additional_untrusted_authorities))
-    return false;
-
   return true;
 }
 }  // namespace
@@ -100,23 +79,4 @@
   ASSERT_TRUE(ConfigsEqual(config, out_config));
 }
 
-TEST(CertVerifierMojomTraitsTest, ConfigCRLAndAdditionalCerts) {
-  const base::FilePath certs_dir = net::GetTestCertsDirectory();
-
-  net::CertVerifier::Config config;
-  config.additional_trust_anchors.push_back(
-      net::ImportCertFromFile(certs_dir, "root_ca_cert.pem"));
-  config.additional_trust_anchors.push_back(
-      net::ImportCertFromFile(certs_dir, "2029_globalsign_com_cert.pem"));
-
-  config.additional_untrusted_authorities.push_back(
-      net::ImportCertFromFile(certs_dir, "intermediate_ca_cert.pem"));
-
-  net::CertVerifier::Config out_config;
-
-  ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CertVerifierConfig>(
-      config, out_config));
-  ASSERT_TRUE(ConfigsEqual(config, out_config));
-}
-
 }  // namespace cert_verifier
diff --git a/services/network/public/mojom/cert_verifier_service.mojom b/services/network/public/mojom/cert_verifier_service.mojom
index bb9029a..3eb4444 100644
--- a/services/network/public/mojom/cert_verifier_service.mojom
+++ b/services/network/public/mojom/cert_verifier_service.mojom
@@ -26,8 +26,16 @@
   bool require_rev_checking_local_anchors;
   bool enable_sha1_local_anchors;
   bool disable_symantec_enforcement;
-  array<network.mojom.X509Certificate> additional_trust_anchors;
-  array<network.mojom.X509Certificate> additional_untrusted_authorities;
+};
+
+struct AdditionalCertificates {
+  // TODO(crbug.com/1477317): store these as bytestrings
+
+  // List of untrusted certificates, which will be used during path building.
+  array<network.mojom.X509Certificate> all_certificates;
+
+  // List of additional trust anchors.
+  array<network.mojom.X509Certificate> trust_anchors;
 };
 
 // Allows the CertVerifierService to connect a new URLLoaderFactory if its
@@ -60,6 +68,15 @@
   SetConfig(CertVerifierConfig config);
 };
 
+// Updates a Cert Verifier with new parameters.
+interface CertVerifierServiceUpdater {
+  // Called when trust parameters change for Cert Verification.  All parameters
+  // will override any previously provided parameters that were provide (either
+  // via previous calls to UpdateCertVerifier or that were specified in
+  // cert_verifier.mojom.CertVerifierCreationParams.
+  UpdateAdditionalCertificates(AdditionalCertificates certificates);
+};
+
 // Receives events from the CertVerifierService.
 interface CertVerifierServiceClient {
   // Called when the certificate verifier changes internal configuration.
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index e696f81..536e3728 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -159,15 +159,6 @@
   ClearBadProxiesCache();
 };
 
-[EnableIf=is_chromeos]
-struct AdditionalCertificates {
-  // List of all additional certificates.
-  array<X509Certificate> all_certificates;
-
-  // List of additional trust anchors.
-  array<X509Certificate> trust_anchors;
-};
-
 // Sent by TrustedURLLoaderHeaderClient to perform modifications for a request.
 interface TrustedHeaderClient {
   // Allows modifying request headers before the request is sent.
@@ -480,11 +471,6 @@
   // Contains a pipe to a CertVerifierService.
   CertVerifierServiceRemoteParams cert_verifier_params;
 
-  // Initial additional certificates that will be used for certificate
-  // validation.
-  [EnableIf=is_chromeos]
-  AdditionalCertificates? initial_additional_certificates;
-
   // Parameters for constructing the cookie manager.
   CookieManagerParams? cookie_manager_params;
 
@@ -1237,10 +1223,6 @@
   // If false, the referrer of requests is never populated.
   SetEnableReferrers(bool enable_referrers);
 
-  // Updates the additional trust anchors for certificate verification.
-  [EnableIf=is_chromeos]
-  UpdateAdditionalCertificates(AdditionalCertificates? additional_certificates);
-
   // Updates the CT policy to be used for requests. Only applies if the
   // NetworkContextParams set enforce_chrome_ct_policy to true.
   // TODO(rsleevi): Remove this once Chrome-specific policies are moved out
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h
index a133f8b8..97ae929f 100644
--- a/services/network/test/test_network_context.h
+++ b/services/network/test/test_network_context.h
@@ -147,10 +147,6 @@
                             mojom::NetworkConditionsPtr conditions) override {}
   void SetAcceptLanguage(const std::string& new_accept_language) override {}
   void SetEnableReferrers(bool enable_referrers) override {}
-#if BUILDFLAG(IS_CHROMEOS)
-  void UpdateAdditionalCertificates(
-      mojom::AdditionalCertificatesPtr additional_certificates) override {}
-#endif
 #if BUILDFLAG(IS_CT_SUPPORTED)
   void SetCTPolicy(mojom::CTPolicyPtr ct_policy) override {}
   void SetCTLogListAlwaysTimelyForTesting() override {}
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index cc16ed8..8190333f 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -2107,6 +2107,7 @@
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "jacuzzi",
         "cros_img": "jacuzzi-release/R118-15604.42.0",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -2124,6 +2125,7 @@
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "jacuzzi",
         "cros_img": "jacuzzi-release/R119-15633.10.0",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -2158,6 +2160,7 @@
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "jacuzzi",
         "cros_img": "jacuzzi-release/R117-15572.63.0",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_STABLE",
         "resultdb": {
           "enable": true,
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 3801900..6cfb6ca 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -6097,9 +6097,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6115.0",
+        "description": "Run with ash-chrome version 121.0.6116.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6109,8 +6109,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6115.0",
-              "revision": "version:121.0.6115.0"
+              "location": "lacros_version_skew_tests_v121.0.6116.0",
+              "revision": "version:121.0.6116.0"
             }
           ],
           "dimensions": {
@@ -6247,9 +6247,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6115.0",
+        "description": "Run with ash-chrome version 121.0.6116.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6259,8 +6259,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6115.0",
-              "revision": "version:121.0.6115.0"
+              "location": "lacros_version_skew_tests_v121.0.6116.0",
+              "revision": "version:121.0.6116.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index 6343035..c4365a56 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -20451,9 +20451,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6115.0",
+        "description": "Run with ash-chrome version 121.0.6116.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20463,8 +20463,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6115.0",
-              "revision": "version:121.0.6115.0"
+              "location": "lacros_version_skew_tests_v121.0.6116.0",
+              "revision": "version:121.0.6116.0"
             }
           ],
           "dimensions": {
@@ -20601,9 +20601,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6115.0",
+        "description": "Run with ash-chrome version 121.0.6116.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20613,8 +20613,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6115.0",
-              "revision": "version:121.0.6115.0"
+              "location": "lacros_version_skew_tests_v121.0.6116.0",
+              "revision": "version:121.0.6116.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 8bcdd611..a7404a21 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -43451,9 +43451,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6115.0",
+        "description": "Run with ash-chrome version 121.0.6116.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43462,8 +43462,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6115.0",
-              "revision": "version:121.0.6115.0"
+              "location": "lacros_version_skew_tests_v121.0.6116.0",
+              "revision": "version:121.0.6116.0"
             }
           ],
           "dimensions": {
@@ -43601,9 +43601,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6115.0",
+        "description": "Run with ash-chrome version 121.0.6116.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43612,8 +43612,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6115.0",
-              "revision": "version:121.0.6115.0"
+              "location": "lacros_version_skew_tests_v121.0.6116.0",
+              "revision": "version:121.0.6116.0"
             }
           ],
           "dimensions": {
@@ -44910,9 +44910,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6115.0",
+        "description": "Run with ash-chrome version 121.0.6116.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -44921,8 +44921,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6115.0",
-              "revision": "version:121.0.6115.0"
+              "location": "lacros_version_skew_tests_v121.0.6116.0",
+              "revision": "version:121.0.6116.0"
             }
           ],
           "dimensions": {
@@ -45060,9 +45060,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6115.0",
+        "description": "Run with ash-chrome version 121.0.6116.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45071,8 +45071,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6115.0",
-              "revision": "version:121.0.6115.0"
+              "location": "lacros_version_skew_tests_v121.0.6116.0",
+              "revision": "version:121.0.6116.0"
             }
           ],
           "dimensions": {
@@ -45755,9 +45755,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6115.0",
+        "description": "Run with ash-chrome version 121.0.6116.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45766,8 +45766,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6115.0",
-              "revision": "version:121.0.6115.0"
+              "location": "lacros_version_skew_tests_v121.0.6116.0",
+              "revision": "version:121.0.6116.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index a2c73fc6..e962dc1 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -15643,7 +15643,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 20
+          "shards": 30
         },
         "test": "browser_tests",
         "test_id_prefix": "ninja://chrome/test:browser_tests/"
@@ -16249,12 +16249,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 121.0.6115.0",
+        "description": "Run with ash-chrome version 121.0.6116.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16264,8 +16264,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6115.0",
-              "revision": "version:121.0.6115.0"
+              "location": "lacros_version_skew_tests_v121.0.6116.0",
+              "revision": "version:121.0.6116.0"
             }
           ],
           "dimensions": {
@@ -16419,12 +16419,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 121.0.6115.0",
+        "description": "Run with ash-chrome version 121.0.6116.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16434,8 +16434,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6115.0",
-              "revision": "version:121.0.6115.0"
+              "location": "lacros_version_skew_tests_v121.0.6116.0",
+              "revision": "version:121.0.6116.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/internal.optimization_guide.json b/testing/buildbot/internal.optimization_guide.json
index bfb3716..edb8ffb 100644
--- a/testing/buildbot/internal.optimization_guide.json
+++ b/testing/buildbot/internal.optimization_guide.json
@@ -268,7 +268,115 @@
       }
     ]
   },
-  "optimization_guide-mac": {
+  "optimization_guide-mac-arm64": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=*OptimizationGuide*:*PageContentAnnotations*"
+        ],
+        "merge": {
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "optimization_guide_browser_tests",
+        "swarming": {
+          "dimensions": {
+            "cpu": "arm64",
+            "os": "Mac-13",
+            "pool": "chrome.tests"
+          },
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "browser_tests",
+        "test_id_prefix": "ninja://chrome/test:browser_tests/"
+      },
+      {
+        "args": [
+          "--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*"
+        ],
+        "merge": {
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "optimization_guide_components_unittests",
+        "swarming": {
+          "dimensions": {
+            "cpu": "arm64",
+            "os": "Mac-13",
+            "pool": "chrome.tests"
+          },
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "components_unittests",
+        "test_id_prefix": "ninja://components:components_unittests/"
+      },
+      {
+        "merge": {
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "optimization_guide_unittests",
+        "swarming": {
+          "dimensions": {
+            "cpu": "arm64",
+            "os": "Mac-13",
+            "pool": "chrome.tests"
+          },
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "optimization_guide_unittests",
+        "test_id_prefix": "ninja://components/optimization_guide/internal:optimization_guide_unittests/"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "merge": {
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "model_validation_tests MODEL_VALIDATION_BASE",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "dimensions": {
+            "cpu": "arm64",
+            "os": "Mac-13",
+            "pool": "chrome.tests"
+          },
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "model_validation_tests",
+        "test_id_prefix": "ninja://components/optimization_guide/internal/testing:model_validation_tests/",
+        "variant_id": "MODEL_VALIDATION_BASE"
+      },
+      {
+        "args": [
+          "--chromedriver",
+          "chromedriver",
+          "--binary",
+          "Chromium.app/Contents/MacOS/Chromium"
+        ],
+        "merge": {
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "model_validation_tests MODEL_VALIDATION_TRUNK",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "dimensions": {
+            "cpu": "arm64",
+            "os": "Mac-13",
+            "pool": "chrome.tests"
+          },
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "model_validation_tests",
+        "test_id_prefix": "ninja://components/optimization_guide/internal/testing:model_validation_tests/",
+        "variant_id": "MODEL_VALIDATION_TRUNK"
+      }
+    ]
+  },
+  "optimization_guide-mac-x64": {
     "gtest_tests": [
       {
         "args": [
@@ -281,7 +389,7 @@
         "swarming": {
           "dimensions": {
             "cpu": "x86-64",
-            "os": "Mac-10.15",
+            "os": "Mac-13",
             "pool": "chrome.tests"
           },
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -300,7 +408,7 @@
         "swarming": {
           "dimensions": {
             "cpu": "x86-64",
-            "os": "Mac-10.15",
+            "os": "Mac-13",
             "pool": "chrome.tests"
           },
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -316,7 +424,7 @@
         "swarming": {
           "dimensions": {
             "cpu": "x86-64",
-            "os": "Mac-10.15",
+            "os": "Mac-13",
             "pool": "chrome.tests"
           },
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -338,7 +446,7 @@
         "swarming": {
           "dimensions": {
             "cpu": "x86-64",
-            "os": "Mac-10.15",
+            "os": "Mac-13",
             "pool": "chrome.tests"
           },
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -365,7 +473,7 @@
         "swarming": {
           "dimensions": {
             "cpu": "x86-64",
-            "os": "Mac-10.15",
+            "os": "Mac-13",
             "pool": "chrome.tests"
           },
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index b92ac2e..084fe57 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1222,7 +1222,7 @@
       # asan tests is slower.
       'linux-lacros-asan-lsan-rel': {
         'swarming': {
-          'shards': 20,
+          'shards': 30,
         },
         # TODO(crbug.com/1324240): Enable tests.
         'args': [
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 4491776..60c705a 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -7470,6 +7470,10 @@
       'lacros_skylab_tests': {
         'variants': [
           'CROS_JACUZZI_RELEASE_LKGM',
+        ],
+      },
+      'lacros_skylab_tests_version_skew': {
+        'variants': [
           'CROS_JACUZZI_RELEASE_DEV',
           'CROS_JACUZZI_RELEASE_BETA',
           'CROS_JACUZZI_RELEASE_STABLE',
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 1323e4d..9e427c25 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -70,16 +70,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 121.0.6115.0',
+    'description': 'Run with ash-chrome version 121.0.6116.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6115.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6116.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v121.0.6115.0',
-          'revision': 'version:121.0.6115.0',
+          'location': 'lacros_version_skew_tests_v121.0.6116.0',
+          'revision': 'version:121.0.6116.0',
         },
       ],
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index f4baa1ed..192287f 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -6869,10 +6869,21 @@
         },
         'os_type': 'linux',
       },
-      'optimization_guide-mac': {
+      'optimization_guide-mac-arm64': {
         'mixins': [
           'chrome-swarming-pool',
-          'mac_10.15',
+          'mac_default_arm64',
+        ],
+        'test_suites': {
+           'gtest_tests': 'optimization_guide_gtests',
+           'isolated_scripts': 'model_validation_tests_full',
+        },
+        'os_type': 'mac',
+      },
+      'optimization_guide-mac-x64': {
+        'mixins': [
+          'chrome-swarming-pool',
+          'mac_default_x64',
         ],
         'test_suites': {
            'gtest_tests': 'optimization_guide_gtests',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 7927133..03aa0c4 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -7297,6 +7297,22 @@
             ]
         }
     ],
+    "GinJavaBridgeMojo": [
+        {
+            "platforms": [
+                "android",
+                "android_webview"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "GinJavaBridgeMojo"
+                    ]
+                }
+            ]
+        }
+    ],
     "GoogleLensDesktopContentMenuTranslate": [
         {
             "platforms": [
diff --git a/third_party/angle b/third_party/angle
index 6b89950..9a7e8b7 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit 6b89950496d124a45f026569183fa7083874fb15
+Subproject commit 9a7e8b7bb17fdd3c88c3b1f26f0c605135654ee0
diff --git a/third_party/blink/public/platform/web_theme_engine.h b/third_party/blink/public/platform/web_theme_engine.h
index bfeeb6a..b7b0cab 100644
--- a/third_party/blink/public/platform/web_theme_engine.h
+++ b/third_party/blink/public/platform/web_theme_engine.h
@@ -321,9 +321,6 @@
       const ui::RendererColorMap& forced_colors_map) {
     return false;
   }
-  virtual void AdjustForcedColorsProvider(
-      ui::ColorProviderKey::ForcedColors forced_colors_state,
-      ui::ColorProviderKey::ColorMode color_mode) {}
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_font_face_src_value.cc b/third_party/blink/renderer/core/css/css_font_face_src_value.cc
index cf6fe31..52cf32f 100644
--- a/third_party/blink/renderer/core/css/css_font_face_src_value.cc
+++ b/third_party/blink/renderer/core/css/css_font_face_src_value.cc
@@ -162,7 +162,7 @@
       params.SetCacheAwareLoadingEnabled(kIsCacheAwareLoadingEnabled);
     }
     params.SetFromOriginDirtyStyleSheet(
-        !url_data.IsFromFromOriginCleanStyleSheet());
+        !url_data.IsFromOriginCleanStyleSheet());
     const SecurityOrigin* security_origin = context->GetSecurityOrigin();
 
     // Local fonts are accessible from file: URLs even when
diff --git a/third_party/blink/renderer/core/css/css_image_value.cc b/third_party/blink/renderer/core/css/css_image_value.cc
index 1d1215a..926c2e93 100644
--- a/third_party/blink/renderer/core/css/css_image_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_value.cc
@@ -80,7 +80,7 @@
     params.SetLazyImageDeferred();
   }
 
-  if (!url_data_.IsFromFromOriginCleanStyleSheet()) {
+  if (!url_data_.IsFromOriginCleanStyleSheet()) {
     params.SetFromOriginDirtyStyleSheet(true);
   }
 
diff --git a/third_party/blink/renderer/core/css/css_url_data.h b/third_party/blink/renderer/core/css/css_url_data.h
index 38d9348..1b418bd 100644
--- a/third_party/blink/renderer/core/css/css_url_data.h
+++ b/third_party/blink/renderer/core/css/css_url_data.h
@@ -76,7 +76,7 @@
 
   const Referrer& GetReferrer() const { return referrer_; }
 
-  bool IsFromFromOriginCleanStyleSheet() const {
+  bool IsFromOriginCleanStyleSheet() const {
     return is_from_origin_clean_style_sheet_;
   }
   OriginClean GetOriginClean() const {
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
index 966da47..1f8ab01 100644
--- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -2085,9 +2085,10 @@
 
   const bool is_subgrid_specified = computed_grid_track_list.IsSubgriddedAxis();
   const bool is_subgrid_valid =
-      grid ? grid->CachedPlacementData().line_resolver.SubgridSpanSize(
-                 direction) != kNotFound
-           : false;
+      (grid && grid->HasCachedPlacementData())
+          ? grid->CachedPlacementData().line_resolver.SubgridSpanSize(
+                direction) != kNotFound
+          : false;
   const bool is_subgrid = is_subgrid_specified && is_subgrid_valid;
 
   // Standalone grids with empty track lists should compute to `none`, but
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index be40573b..7ca8299 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -6107,7 +6107,18 @@
          IsScrollableContainerThatShouldBeKeyboardFocusable();
 }
 
-bool Element::IsFocusable() const {
+bool Element::IsFocusableStyleNoLifecycleUpdate() const {
+  DCHECK(!NeedsStyleRecalc()) << this;
+  DocumentLifecycle::DisallowTransitionScope scope(GetDocument().Lifecycle());
+  return IsFocusableStyle();
+}
+
+bool Element::IsFocusable(
+    bool disallow_layout_updates_for_accessibility_only) const {
+  if (UNLIKELY(disallow_layout_updates_for_accessibility_only)) {
+    return isConnected() && IsFocusableStyleNoLifecycleUpdate() &&
+           SupportsFocus();
+  }
   return isConnected() && IsFocusableStyleAfterUpdate() && SupportsFocus();
 }
 
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index 86d06ed3..6a392b0 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -821,7 +821,11 @@
   // focusable (using the mouse). This method can be called when layout is not
   // clean, but the method might trigger a lifecycle update in that case. This
   // method will not trigger a lifecycle update if layout is already clean.
-  virtual bool IsFocusable() const;
+  // If the |disallow_layout_updates_for_accessibility_only| argument is true,
+  // which should only be used by a11y code, layout updates will never be
+  // performed.
+  virtual bool IsFocusable(
+      bool disallow_layout_updates_for_accessibility_only = false) const;
 
   // IsKeyboardFocusable is true for the subset of mouse focusable elements (for
   // which IsFocusable() is true) that are in the tab cycle. This method
@@ -1334,7 +1338,9 @@
   // Similar to IsFocusableStyle, except that it will ensure that any deferred
   // work to create layout objects is completed (e.g. in display-locked trees).
   bool IsFocusableStyleAfterUpdate() const;
-
+  // Similar to IsFocusableStyle, except that it will *never* trigger a style
+  // update. Only call this method if the lifecycle does not need to be updated.
+  bool IsFocusableStyleNoLifecycleUpdate() const;
   // Is the node descendant of this in something clickable/activatable, such
   // that we shouldn't handle events targeting it?
   bool IsClickableControl(Node*);
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 23e62fa..a687d49f 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -1266,10 +1266,8 @@
     payment_request_token_.Activate();
   }
 
-  if (RuntimeEnabledFeatures::CapabilityDelegationFullscreenRequestEnabled(
-          this) &&
-      event->delegatedCapability() ==
-          mojom::blink::DelegatedCapability::kFullscreenRequest) {
+  if (event->delegatedCapability() ==
+      mojom::blink::DelegatedCapability::kFullscreenRequest) {
     UseCounter::Count(this,
                       WebFeature::kCapabilityDelegationOfFullscreenRequest);
     fullscreen_request_token_.Activate();
diff --git a/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc b/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
index 3ecbafe7..f447624 100644
--- a/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
@@ -373,8 +373,7 @@
   String added_contents = PostActionAfterSerializeOpenTag(element, param);
   // Complete the open tag for element when it has child/children.
   if (element->HasChildren() || param->have_added_contents_before_end ||
-      (element->AuthorShadowRoot() &&
-       RuntimeEnabledFeatures::SaveAsWithDeclarativeShadowDOMEnabled())) {
+      element->AuthorShadowRoot()) {
     result.Append('>');
   }
   // Append the added contents generate in  post action of open tag.
@@ -394,8 +393,7 @@
     return;
   // Write end tag when element has child/children.
   if (element->HasChildren() || param->have_added_contents_before_end ||
-      (element->AuthorShadowRoot() &&
-       RuntimeEnabledFeatures::SaveAsWithDeclarativeShadowDOMEnabled())) {
+      element->AuthorShadowRoot()) {
     result.Append("</");
     result.Append(element->nodeName().DeprecatedLower());
     result.Append('>');
@@ -448,9 +446,7 @@
       OpenTagToString(element, param);
 
       // Process the ShadowRoot into a <template> if present.
-      auto* shadow_root = element->AuthorShadowRoot();
-      if (shadow_root &&
-          RuntimeEnabledFeatures::SaveAsWithDeclarativeShadowDOMEnabled()) {
+      if (auto* shadow_root = element->AuthorShadowRoot()) {
         ShadowRootTagToString(shadow_root, param);
         for (Node* child = shadow_root->firstChild(); child;
              child = child->nextSibling()) {
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc
index 8058b97..400871b0 100644
--- a/third_party/blink/renderer/core/frame/web_frame_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -1023,9 +1023,6 @@
 }  // namespace
 
 TEST_F(WebFrameTest, CapabilityDelegationMessageEventTest) {
-  ScopedCapabilityDelegationFullscreenRequestForTest fullscreen_delegation(
-      true);
-
   RegisterMockedHttpURLLoad("single_iframe.html");
   RegisterMockedHttpURLLoad("visible_iframe.html");
 
diff --git a/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
index 3d18b5a..54be06f 100644
--- a/third_party/blink/renderer/core/fullscreen/fullscreen.cc
+++ b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -351,9 +351,7 @@
     return true;
 
   // The algorithm is triggered by a fullscreen request capability delegation.
-  if (RuntimeEnabledFeatures::CapabilityDelegationFullscreenRequestEnabled(
-          document.GetExecutionContext()) &&
-      document.domWindow()->IsFullscreenRequestTokenActive()) {
+  if (document.domWindow()->IsFullscreenRequestTokenActive()) {
     return true;
   }
 
diff --git a/third_party/blink/renderer/core/html/forms/clear_button_element.h b/third_party/blink/renderer/core/html/forms/clear_button_element.h
index 7d9bc00b..bc32f5f 100644
--- a/third_party/blink/renderer/core/html/forms/clear_button_element.h
+++ b/third_party/blink/renderer/core/html/forms/clear_button_element.h
@@ -49,7 +49,7 @@
 
  private:
   void DetachLayoutTree(bool performing_reattach) override;
-  bool IsFocusable() const override { return false; }
+  bool IsFocusable(bool) const override { return false; }
   void DefaultEventHandler(Event&) override;
   bool IsClearButtonElement() const override;
 
diff --git a/third_party/blink/renderer/core/html/forms/spin_button_element.h b/third_party/blink/renderer/core/html/forms/spin_button_element.h
index f53cce0..5eb3d278 100644
--- a/third_party/blink/renderer/core/html/forms/spin_button_element.h
+++ b/third_party/blink/renderer/core/html/forms/spin_button_element.h
@@ -89,7 +89,7 @@
   void StopRepeatingTimer();
   void RepeatingTimerFired(TimerBase*);
   bool ShouldRespondToMouseEvents() const;
-  bool IsFocusable() const override { return false; }
+  bool IsFocusable(bool) const override { return false; }
   void CalculateUpDownStateByMouseLocation(Event&);
 
   Member<SpinButtonOwner> spin_button_owner_;
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc
index 7263b0d..d840e58 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.cc
+++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -141,13 +141,22 @@
          HTMLElement::SupportsFocus();
 }
 
-bool HTMLAnchorElement::IsFocusable() const {
-  if (!IsFocusableStyleAfterUpdate())
-    return false;
-  if (IsLink())
+bool HTMLAnchorElement::IsFocusable(
+    bool disallow_layout_updates_for_accessibility_only) const {
+  if (disallow_layout_updates_for_accessibility_only) {
+    if (!IsFocusableStyleNoLifecycleUpdate()) {
+      return false;
+    }
+  } else {
+    if (!IsFocusableStyleAfterUpdate()) {
+      return false;
+    }
+  }
+  if (IsLink()) {
     return SupportsFocus();
-
-  return HTMLElement::IsFocusable();
+  }
+  return HTMLElement::IsFocusable(
+      disallow_layout_updates_for_accessibility_only);
 }
 
 bool HTMLAnchorElement::IsKeyboardFocusable() const {
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.h b/third_party/blink/renderer/core/html/html_anchor_element.h
index 103fa2c..4d0ce46 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.h
+++ b/third_party/blink/renderer/core/html/html_anchor_element.h
@@ -114,7 +114,8 @@
  private:
   void AttributeChanged(const AttributeModificationParams&) override;
   bool ShouldHaveFocusAppearance() const final;
-  bool IsFocusable() const override;
+  bool IsFocusable(bool disallow_layout_updates_for_accessibility_only =
+                       false) const override;
   bool IsKeyboardFocusable() const override;
   void DefaultEventHandler(Event&) final;
   bool HasActivationBehavior() const override;
diff --git a/third_party/blink/renderer/core/html/html_area_element.cc b/third_party/blink/renderer/core/html/html_area_element.cc
index f3dabed..a6cbcc04 100644
--- a/third_party/blink/renderer/core/html/html_area_element.cc
+++ b/third_party/blink/renderer/core/html/html_area_element.cc
@@ -189,9 +189,11 @@
   return Element::IsKeyboardFocusable();
 }
 
-bool HTMLAreaElement::IsFocusable() const {
+bool HTMLAreaElement::IsFocusable(
+    bool disallow_layout_updates_for_accessibility_only) const {
   // Explicitly skip over the HTMLAnchorElement's mouse focus behavior.
-  return HTMLElement::IsFocusable();
+  return HTMLElement::IsFocusable(
+      disallow_layout_updates_for_accessibility_only);
 }
 
 bool HTMLAreaElement::IsFocusableStyle() const {
diff --git a/third_party/blink/renderer/core/html/html_area_element.h b/third_party/blink/renderer/core/html/html_area_element.h
index 9aee4ccd..6d3f68b6 100644
--- a/third_party/blink/renderer/core/html/html_area_element.h
+++ b/third_party/blink/renderer/core/html/html_area_element.h
@@ -61,7 +61,8 @@
  private:
   void ParseAttribute(const AttributeModificationParams&) override;
   bool IsKeyboardFocusable() const override;
-  bool IsFocusable() const override;
+  bool IsFocusable(bool disallow_layout_updates_for_accessibility_only =
+                       false) const override;
   bool IsFocusableStyle() const override;
   void UpdateSelectionOnFocus(SelectionBehaviorOnFocus,
                               const FocusOptions*) override;
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.cc b/third_party/blink/renderer/core/html/html_dialog_element.cc
index 1a46d05..7c6dcc8 100644
--- a/third_party/blink/renderer/core/html/html_dialog_element.cc
+++ b/third_party/blink/renderer/core/html/html_dialog_element.cc
@@ -201,20 +201,14 @@
 }
 
 void HTMLDialogElement::show(ExceptionState& exception_state) {
-  if (RuntimeEnabledFeatures::PopoverDialogDontThrowEnabled()) {
-    if (FastHasAttribute(html_names::kOpenAttr)) {
-      if (is_modal_) {
-        exception_state.ThrowDOMException(
-            DOMExceptionCode::kInvalidStateError,
-            "The dialog is already open as a modal dialog, and therefore "
-            "cannot be opened as a non-modal dialog.");
-      }
-      return;
+  if (FastHasAttribute(html_names::kOpenAttr)) {
+    if (is_modal_) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kInvalidStateError,
+          "The dialog is already open as a modal dialog, and therefore "
+          "cannot be opened as a non-modal dialog.");
     }
-  } else {
-    if (FastHasAttribute(html_names::kOpenAttr)) {
-      return;
-    }
+    return;
   }
 
   SetBooleanAttribute(html_names::kOpenAttr, true);
@@ -237,6 +231,20 @@
   }
 }
 
+bool HTMLDialogElement::IsFocusable(
+    bool disallow_layout_updates_for_accessibility_only) const {
+  // TODO(crbug.com/1499838) HTMLDialogElement should only need to override
+  // SupportsFocus() to be always-true, and should not need to override
+  // IsFocusable() at all. Dialog focus behavior is to focus the dialog itself
+  // if there are no focusable descendants, which means they support focus.
+  // However, making SupportsFocus always true makes dialogs always keyboard
+  // focusable, and that breaks things.
+  if (UNLIKELY(disallow_layout_updates_for_accessibility_only)) {
+    return isConnected() && IsFocusableStyleNoLifecycleUpdate();
+  }
+  return isConnected() && IsFocusableStyleAfterUpdate();
+}
+
 class DialogCloseWatcherEventListener : public NativeEventListener {
  public:
   explicit DialogCloseWatcherEventListener(HTMLDialogElement* dialog)
@@ -261,24 +269,14 @@
 };
 
 void HTMLDialogElement::showModal(ExceptionState& exception_state) {
-  if (RuntimeEnabledFeatures::PopoverDialogDontThrowEnabled()) {
-    if (FastHasAttribute(html_names::kOpenAttr)) {
-      if (!is_modal_) {
-        exception_state.ThrowDOMException(
-            DOMExceptionCode::kInvalidStateError,
-            "The dialog is already open as a non-modal dialog, and therefore "
-            "cannot be opened as a modal dialog.");
-      }
-      return;
-    }
-  } else {
-    if (FastHasAttribute(html_names::kOpenAttr)) {
-      return exception_state.ThrowDOMException(
+  if (FastHasAttribute(html_names::kOpenAttr)) {
+    if (!is_modal_) {
+      exception_state.ThrowDOMException(
           DOMExceptionCode::kInvalidStateError,
-          "The element already has an 'open' "
-          "attribute, and therefore cannot be "
-          "opened modally.");
+          "The dialog is already open as a non-modal dialog, and therefore "
+          "cannot be opened as a modal dialog.");
     }
+    return;
   }
   if (!isConnected()) {
     return exception_state.ThrowDOMException(
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.h b/third_party/blink/renderer/core/html/html_dialog_element.h
index f33b7fe..c1e24ee1 100644
--- a/third_party/blink/renderer/core/html/html_dialog_element.h
+++ b/third_party/blink/renderer/core/html/html_dialog_element.h
@@ -59,9 +59,8 @@
   void CloseWatcherFiredCancel(Event*);
   void CloseWatcherFiredClose();
 
-  bool IsFocusable() const override {
-    return isConnected() && IsFocusableStyleAfterUpdate();
-  }
+  bool IsFocusable(bool disallow_layout_updates_for_accessibility_only =
+                       false) const override;
 
   // https://html.spec.whatwg.org/C/#the-dialog-element
   // Chooses the focused element when show() or showModal() is invoked.
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc
index f008f015..0a135b22 100644
--- a/third_party/blink/renderer/core/html/html_element.cc
+++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -1308,10 +1308,6 @@
   }
   if (action == PopoverTriggerAction::kShow &&
       GetPopoverData()->visibilityState() != PopoverVisibilityState::kHidden) {
-    if (!RuntimeEnabledFeatures::PopoverDialogDontThrowEnabled()) {
-      maybe_throw_exception(DOMExceptionCode::kInvalidStateError,
-                            "Invalid on popover elements which aren't hidden.");
-    }
     return false;
   }
   if (action == PopoverTriggerAction::kHide &&
@@ -1319,11 +1315,6 @@
     // Important to check that visibility is not kShowing (rather than
     // popoverOpen()), because a hide transition might have been started on this
     // popover already, and we don't want to allow a double-hide.
-    if (!RuntimeEnabledFeatures::PopoverDialogDontThrowEnabled()) {
-      maybe_throw_exception(
-          DOMExceptionCode::kInvalidStateError,
-          "Invalid on popover elements that aren't already showing.");
-    }
     return false;
   }
   if (!isConnected()) {
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc
index ea343bd..6f932e92 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -702,11 +702,13 @@
   return ShouldShowControls() || HTMLElement::SupportsFocus();
 }
 
-bool HTMLMediaElement::IsFocusable() const {
+bool HTMLMediaElement::IsFocusable(
+    bool disallow_layout_updates_for_accessibility_only) const {
   if (!SupportsFocus()) {
     return false;
   }
-  return !IsFullscreen() || HTMLElement::IsFocusable();
+  return !IsFullscreen() || HTMLElement::IsFocusable(
+                                disallow_layout_updates_for_accessibility_only);
 }
 
 bool HTMLMediaElement::IsKeyboardFocusable() const {
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h
index 7ab5d43..21c4319 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.h
+++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -494,7 +494,8 @@
   bool AreAuthorShadowsAllowed() const final { return false; }
 
   bool SupportsFocus() const final;
-  bool IsFocusable() const final;
+  bool IsFocusable(
+      bool disallow_layout_updates_for_accessibility_only = false) const final;
   bool IsKeyboardFocusable() const final;
   int DefaultTabIndex() const final;
   bool LayoutObjectIsNeeded(const DisplayStyle&) const override;
diff --git a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc
index 35be24c..6091eade 100644
--- a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc
@@ -230,7 +230,9 @@
     grid_sizing_tree = grid_data->grid_sizing_tree.CopyForFragmentation();
     intrinsic_block_size = grid_data->intrinsic_block_size;
   } else {
-    grid_sizing_tree = BuildGridSizingTree(&oof_children);
+    grid_sizing_tree = node_.ChildLayoutBlockedByDisplayLock()
+                           ? BuildGridSizingTreeIgnoringChildren()
+                           : BuildGridSizingTree(&oof_children);
     ComputeGridGeometry(grid_sizing_tree, &intrinsic_block_size);
 
     // Subgridded items must be laid out by their parent.
diff --git a/third_party/blink/renderer/core/layout/layout_inline.h b/third_party/blink/renderer/core/layout/layout_inline.h
index 66cf4c5..041be9c 100644
--- a/third_party/blink/renderer/core/layout/layout_inline.h
+++ b/third_party/blink/renderer/core/layout/layout_inline.h
@@ -153,6 +153,7 @@
   gfx::RectF LocalBoundingBoxRectForAccessibility() const final;
 
   PhysicalRect PhysicalLinesBoundingBox() const;
+  PhysicalRect LinesVisualOverflowBoundingBox() const;
   PhysicalRect VisualOverflowRect() const final;
 
   bool HasInlineFragments() const final;
@@ -270,10 +271,6 @@
 
   PhysicalRect CulledInlineVisualOverflowBoundingBox() const;
 
-  // For VisualOverflowRect() only, to get bounding box of visual overflow of
-  // line boxes.
-  PhysicalRect LinesVisualOverflowBoundingBox() const;
-
   // PhysicalRectCollector should be like a function:
   // void (const PhysicalRect&).
   template <typename PhysicalRectCollector>
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
index ee26cdc..9e0d291 100644
--- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
+++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -72,17 +72,18 @@
   Walk(root_frame_view, context);
   paint_invalidator_.ProcessPendingDelayedPaintInvalidations();
 
-#if DCHECK_IS_ON()
-  if (needed_tree_builder_context_update && VLOG_IS_ON(1)) {
-    ShowAllPropertyTrees(root_frame_view);
-  }
-#endif
-
   bool updates_executed = root_frame_view.ExecuteAllPendingUpdates();
   if (updates_executed) {
     needs_invalidate_chrome_client_ = true;
   }
 
+#if DCHECK_IS_ON()
+  if ((needed_tree_builder_context_update || updates_executed) &&
+      VLOG_IS_ON(1)) {
+    ShowAllPropertyTrees(root_frame_view);
+  }
+#endif
+
   // If the page has anything changed, we need to inform the chrome client
   // so that the client will initiate repaint of the contents if needed (e.g.
   // when this page is embedded as a non-composited content of another page).
diff --git a/third_party/blink/renderer/core/url_pattern/url_pattern_component.cc b/third_party/blink/renderer/core/url_pattern/url_pattern_component.cc
index 5b890db..f8c9395c 100644
--- a/third_party/blink/renderer/core/url_pattern/url_pattern_component.cc
+++ b/third_party/blink/renderer/core/url_pattern/url_pattern_component.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_url_pattern_options.h"
 #include "third_party/blink/renderer/core/url_pattern/url_pattern_canon.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
 #include "url/url_util.h"
 
@@ -250,6 +251,10 @@
         "Blink.URLPattern.IncompatiblePatternWithUnicodeSetsMode",
         regexp->IsValid() && !regexp_v->IsValid());
 
+    if (RuntimeEnabledFeatures::URLPatternRegexpUnicodeSetsModeEnabled()) {
+      regexp = regexp_v;
+    }
+
     if (!regexp->IsValid()) {
       // The regular expression failed to compile.  This means that some
       // custom regexp group within the pattern is illegal.  Attempt to
@@ -262,7 +267,9 @@
         String group_value(part.value.data(), part.value.size());
         regexp = MakeGarbageCollected<ScriptRegexp>(
             group_value, case_sensitive, MultilineMode::kMultilineDisabled,
-            UnicodeMode::kUnicode);
+            RuntimeEnabledFeatures::URLPatternRegexpUnicodeSetsModeEnabled()
+                ? UnicodeMode::kUnicodeSets
+                : UnicodeMode::kUnicode);
         if (regexp->IsValid())
           continue;
         exception_state.ThrowTypeError("Invalid " + TypeToString(type) +
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc b/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc
index 19cea691..c172d2e 100644
--- a/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc
+++ b/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc
@@ -1796,6 +1796,10 @@
             ComputeVisualOverflowRect(*child_box, ancestor_for_recursion);
         result.Unite(mapped_overflow_rect);
       } else if (auto* child_text = DynamicTo<LayoutText>(child)) {
+        if (box.IsLayoutInline()) {
+          continue;
+        }
+
         const bool child_visible =
             child_text->StyleRef().Visibility() == EVisibility::kVisible ||
             !child_text->VisualRectRespectsVisibility();
@@ -1820,10 +1824,8 @@
             layout_box->ComputeVisualEffectOverflowOutsets();
         overflow_rect.Expand(outsets);
       }
-    } else if (auto* layout_inline = DynamicTo<LayoutInline>(box)) {
-      overflow_rect = layout_inline->PhysicalLinesBoundingBox();
     } else {
-      overflow_rect = PhysicalRect(box.BorderBoundingBox());
+      overflow_rect = To<LayoutInline>(box).LinesVisualOverflowBoundingBox();
     }
   }
 
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index 3bada6bc..ce04181 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -4211,14 +4211,10 @@
     return false;
   }
 
-  // We should not need layout/style updates at this point.
+  // We should not need style updates at this point.
   CHECK(!elem->NeedsStyleRecalc())
       << "\n* Element: " << elem << "\n* Object: " << ToString(true, true)
       << "\n* LayoutObject: " << GetLayoutObject();
-  CHECK(
-      !GetDocument()->NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(*elem))
-      << "\n* Element: " << elem << "\n* Object: " << ToString(true, true)
-      << "\n* LayoutObject: " << GetLayoutObject();
 
   // Focusable: element supports focus.
   return elem->SupportsFocus();
@@ -4230,13 +4226,13 @@
   }
 
   Element& element = *GetElement();
-  Document& document = *GetDocument();
   CHECK(!element.NeedsStyleRecalc())
       << "\n* Element: " << element << "\n* Object: " << ToString(true, true)
       << "\n* LayoutObject: " << GetLayoutObject();
-  CHECK(!document.NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(element))
-      << "\n* Element: " << element << "\n* Object: " << ToString(true, true)
-      << "\n* LayoutObject: " << GetLayoutObject();
+  if (!element.IsFocusable(
+          /*disallow_layout_updates_for_accessibility_only*/ true)) {
+    return false;
+  }
   return element.IsKeyboardFocusable();
 }
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 9698895..d0781ed 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -561,11 +561,6 @@
       status: "experimental",
     },
     {
-      name: "CapabilityDelegationFullscreenRequest",
-      status: "stable",
-      base_feature: "none",
-    },
-    {
       name: "CaptureController",
       status: {"Android": "", "default": "stable"},
       base_feature: "none",
@@ -2999,13 +2994,6 @@
       name: "PointerEventDeviceId",
       status: "test",
     },
-    // PopoverDialogDontThrow makes popover and dialog elements stop throwing
-    // exceptions when calling their show and hide methods when they are
-    // already in their requested state. See https://github.com/whatwg/html/pull/9142
-    {
-      name: "PopoverDialogDontThrow",
-      status: "stable",
-    },
     {
       name: "Portals",
       // Portals must be enabled by blink::features::kPortals as we require the
@@ -3192,8 +3180,12 @@
     {
       name: "RemotePlaybackBackend",
       settable_from_internals: true,
-      // Tracking bug for the implementation: https://crbug.com/728609
-      status: {"Android": "stable", "default": "experimental"},
+      status: {
+        "Android": "stable",
+        "Win": "stable",
+        "Mac": "stable",
+        "Linux": "stable",
+        "default": "experimental"},
     },
     {
       name: "RemoveDanglingMarkupInTarget",
@@ -3308,10 +3300,6 @@
       status: "experimental",
     },
     {
-      name: "SaveAsWithDeclarativeShadowDOM",
-      status: "stable",
-    },
-    {
       name: "SchedulerYield",
       origin_trial_feature_name: "SchedulerYield",
       depends_on: ["AbortSignalComposition"],
@@ -3964,6 +3952,11 @@
       base_feature: "none",
     },
     {
+      // Kill switch for the regexp flag update from "u" to "v".
+      name: "URLPatternRegexpUnicodeSetsMode",
+      status: "stable",
+    },
+    {
       name: "URLPatternWildcardMoreOften",
       status: "stable",
     },
diff --git a/third_party/blink/renderer/platform/theme/web_theme_engine_default.cc b/third_party/blink/renderer/platform/theme/web_theme_engine_default.cc
index 0f1dc563..8a9652d3 100644
--- a/third_party/blink/renderer/platform/theme/web_theme_engine_default.cc
+++ b/third_party/blink/renderer/platform/theme/web_theme_engine_default.cc
@@ -358,10 +358,6 @@
       {ui::NativeTheme::SystemThemeColor::kWindow, 0xFFFFFFFF},
       {ui::NativeTheme::SystemThemeColor::kWindowText, 0xFF000000},
   };
-  AdjustForcedColorsProvider(ui::ColorProviderKey::ForcedColors::kEmulated,
-                             is_dark_theme
-                                 ? ui::ColorProviderKey::ColorMode::kDark
-                                 : ui::ColorProviderKey::ColorMode::kLight);
   EmulateForcedColors(is_dark_theme, /*is_web_test=*/false);
   ui::NativeTheme::GetInstanceForWeb()->UpdateSystemColorInfo(
       false, true, is_dark_theme ? dark_theme : light_theme);
@@ -384,15 +380,6 @@
     SystemColorInfoState system_color_info_state) {
   base::flat_map<ui::NativeTheme::SystemThemeColor, uint32_t> colors;
 
-  ui::ColorProviderKey::ForcedColors initial_forced_colors_state =
-      system_color_info_state.forced_colors
-          ? ui::ColorProviderKey::ForcedColors::kActive
-          : ui::ColorProviderKey::ForcedColors::kNone;
-  ui::ColorProviderKey::ColorMode initial_color_mode =
-      system_color_info_state.is_dark_mode
-          ? ui::ColorProviderKey::ColorMode::kDark
-          : ui::ColorProviderKey::ColorMode::kLight;
-  AdjustForcedColorsProvider(initial_forced_colors_state, initial_color_mode);
   for (const auto& color : system_color_info_state.colors) {
     colors.insert({NativeSystemThemeColor(color.first), color.second});
   }
@@ -457,25 +444,6 @@
   return did_color_provider_update;
 }
 
-void WebThemeEngineDefault::AdjustForcedColorsProvider(
-    ui::ColorProviderKey::ForcedColors forced_colors_state,
-    ui::ColorProviderKey::ColorMode color_mode) {
-  auto key = ui::NativeTheme::GetInstanceForWeb()->GetColorProviderKey(
-      /*custom_theme=*/nullptr);
-  key.forced_colors = forced_colors_state;
-  key.color_mode = color_mode;
-  ui::ColorProvider* color_provider =
-      ui::ColorProviderManager::Get().GetColorProviderFor(key);
-  CHECK(color_provider);
-
-  const ui::RendererColorMap& emulated_forced_colors_map =
-      ui::CreateRendererColorMap(*color_provider);
-  if (!IsRendererColorMappingEquivalent(forced_colors_provider_,
-                                        emulated_forced_colors_map)) {
-    forced_colors_provider_ = std::move(*color_provider);
-  }
-}
-
 bool WebThemeEngineDefault::ShouldPartBeAffectedByAccentColor(
     WebThemeEngine::Part part,
     WebThemeEngine::State state,
@@ -561,8 +529,11 @@
 
 const ui::ColorProvider* WebThemeEngineDefault::GetColorProviderForPainting(
     mojom::ColorScheme color_scheme) const {
-  if (emulate_forced_colors_ && GetForcedColors() == ForcedColors::kActive) {
-    return &emulated_forced_colors_provider_;
+  if (GetForcedColors() == ForcedColors::kActive) {
+    if (emulate_forced_colors_) {
+      return &emulated_forced_colors_provider_;
+    }
+    return &forced_colors_provider_;
   }
   return color_scheme == mojom::ColorScheme::kLight ? &light_color_provider_
                                                     : &dark_color_provider_;
diff --git a/third_party/blink/renderer/platform/theme/web_theme_engine_default.h b/third_party/blink/renderer/platform/theme/web_theme_engine_default.h
index ece4c0a..6c7e73e 100644
--- a/third_party/blink/renderer/platform/theme/web_theme_engine_default.h
+++ b/third_party/blink/renderer/platform/theme/web_theme_engine_default.h
@@ -53,9 +53,6 @@
       const ui::RendererColorMap& light_colors,
       const ui::RendererColorMap& dark_colors,
       const ui::RendererColorMap& forced_colors_map) override;
-  void AdjustForcedColorsProvider(
-      ui::ColorProviderKey::ForcedColors forced_colors_state,
-      ui::ColorProviderKey::ColorMode color_mode) override;
   void EmulateForcedColors(bool is_dark_theme, bool is_web_test) override;
   bool IsFluentOverlayScrollbarEnabled() const override;
   int GetPaintedScrollbarTrackInset() const override;
@@ -99,9 +96,9 @@
   ui::ColorProvider forced_colors_provider_;
 
   // This provider is used when forced color emulation is enabled, overriding
-  // the light or dark color providers.
-  // TODO(samomekarajr): Remove this provider when we use the forced colors
-  // provider for painting.
+  // the light, dark or forced colors color providers.
+  // TODO(samomekarajr): Remove this provider when we figure out how to change
+  // the ForcedColors key from the renderer.
   ui::ColorProvider emulated_forced_colors_provider_;
 };
 
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 d86d687..55f2991 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
@@ -4526,6 +4526,13 @@
      ]
     },
     "cssom": {
+     "change-rule-with-layers-crash.html": [
+      "63e8ec5207e94e8cae555ee0e0db2d8d6d095a11",
+      [
+       null,
+       {}
+      ]
+     ],
      "declaration-block-all-crash.html": [
       "2d781e5dcff9d9ffdd716af0d08f81171e0ba3ea",
       [
@@ -229955,6 +229962,19 @@
        {}
       ]
      ],
+     "outline-auto-width-001.html": [
+      "fc7dc170661cf763611a148680c8f9e6dc8c064a",
+      [
+       null,
+       [
+        [
+         "/css/css-ui/reference/outline-auto-with-001-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "outline-color-001.html": [
       "82824e47bfc57593f6dea8bfceae5a5e6bf1cb67",
       [
@@ -261278,6 +261298,19 @@
     },
     "zoom": {
      "tentative": {
+      "background-image.html": [
+       "db6baa60db1f9d7b49ee0a3a92def5bc8d5d03f4",
+       [
+        null,
+        [
+         [
+          "/css/zoom/tentative/background-image-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "basic.html": [
        "fcd1761cfad478bba33b2f9ce312eec297a6886b",
        [
@@ -292383,7 +292416,7 @@
     },
     "name": {
      "name-ctl-expected.txt": [
-      "981a4355e4781b6c473b219e9576cd2f5c20a105",
+      "d8c0b4e38f29dc7fe6ba94eb58e13486a066168b",
       []
      ]
     },
@@ -292585,7 +292618,7 @@
     },
     "value": {
      "value-ctl-expected.txt": [
-      "2d7947e359eecfba38b5adfe30ae4d386cd3bab7",
+      "3d8ea132e9500390d4137a3d93176c1114d0fa37",
       []
      ]
     }
@@ -292695,10 +292728,6 @@
      "c1e6fd6c4c281f22e7f92506ec72ca39b6293f23",
      []
     ],
-    "fedcm-logout-rps.https.html.headers": [
-     "90454dbb227b7a3be84fe4618980ef7e74622099",
-     []
-    ],
     "federatedcredential-framed-get.sub.https-expected.txt": [
      "bcd104bf85f0b5a8c60f662d1885975ab6614f01",
      []
@@ -300670,7 +300699,7 @@
        []
       ],
       "animation-name-valid-expected.txt": [
-       "33833702a24b780909e714c19ce303da2c4f039d",
+       "9b6526213894be29f4ef1a15dbeba1f6a6d762b8",
        []
       ],
       "keyframes-name-invalid-expected.txt": [
@@ -301742,7 +301771,7 @@
        []
       ],
       "background-image-valid-expected.txt": [
-       "dcc3591b402e3416b4430e253b442e0993596d03",
+       "7c778b672de4229c78b3eb3b5d0ad23be2afad4d",
        []
       ],
       "background-position-computed-expected.txt": [
@@ -301766,7 +301795,7 @@
        []
       ],
       "background-shorthand-serialization-expected.txt": [
-       "d3d14793a6308a0e40a794354c74804b6d00ff0b",
+       "4ac2d8b1e6fa1b1e1453d2e023591d3a39892261",
        []
       ],
       "background-size-computed-expected.txt": [
@@ -301774,7 +301803,7 @@
        []
       ],
       "background-valid-expected.txt": [
-       "b82b8037c21559c998228d3e6c7de45fa8a9439c",
+       "4d4c730cdcfe03d7ac9c1eb36188af2690ae7041",
        []
       ],
       "border-shorthand-expected.txt": [
@@ -310130,7 +310159,7 @@
        []
       ],
       "font-feature-settings-computed-expected.txt": [
-       "a5117b68c7a418cb298b223d06baf1019b3f2654",
+       "3a20c2ffffd002a9638c67f7fe4217f8552d4274",
        []
       ],
       "font-language-override-computed-expected.txt": [
@@ -310138,7 +310167,7 @@
        []
       ],
       "font-language-override-valid-expected.txt": [
-       "9047a508194f6d1db984ca168a438d15789cb024",
+       "7a7d639bf56bc1a90a7fc51dc33d934dec6d25b8",
        []
       ],
       "font-size-adjust-computed-expected.txt": [
@@ -316473,7 +316502,7 @@
       []
      ],
      "test_font_feature_values_parsing-expected.txt": [
-      "0786bbab6aba812392070efec5526de2f70bdc94",
+      "45e64d63fd1c62f81512da90a2b1260e94d177ae",
       []
      ],
      "variations": {
@@ -316514,7 +316543,7 @@
        []
       ],
       "font-style-parsing-expected.txt": [
-       "519fefa03614ea2f7fa0785b0c768ffd38310d62",
+       "cd6cbfb91e74990720a662626686615fcf0aa272",
        []
       ],
       "font-weight-metrics-ref.html": [
@@ -320296,7 +320325,7 @@
      ],
      "parsing": {
       "content-invalid-expected.txt": [
-       "8e6de6dcc82c411c787f0a991d5ab41ec144d250",
+       "6e476f99ba62c06a08610941a3018698b0fce4bd",
        []
       ],
       "counter-reset-valid-expected.txt": [
@@ -320304,7 +320333,7 @@
        []
       ],
       "list-style-computed.sub-expected.txt": [
-       "43b0f5532ea40c0253f1d4f933c90420532f3bfb",
+       "67a53c25945605e6a40e86e58282e3606aed1df8",
        []
       ],
       "list-style-image-computed.sub-expected.txt": [
@@ -320316,11 +320345,11 @@
        []
       ],
       "list-style-type-valid-expected.txt": [
-       "7f951ab3108887422512b3d37a00cf345c987b8b",
+       "bf7c4a6cde75b96e904d9cac7ab05125f0dda9bf",
        []
       ],
       "list-style-valid-expected.txt": [
-       "4d9b9ad22118b821cfd5b35566ec667e02f1bf0b",
+       "9a7f90e27b39ca1d57bc7e5f13ec4e46a8488bd0",
        []
       ]
      },
@@ -321310,7 +321339,7 @@
      },
      "parsing": {
       "mask-valid.sub-expected.txt": [
-       "de6ce163314832c33b1ff61aa002a99c447f1fad",
+       "0336070e6e3499e8f291b246fa149ec6324f2a81",
        []
       ]
      },
@@ -322439,7 +322468,7 @@
       []
      ],
      "serialize-group-rules-with-decls-expected.txt": [
-      "43c6bdc96ed43d136a642ed5c10849fbf2979b85",
+      "4b93f624afa02ec325649571496701c65ba8f09e",
       []
      ],
      "supports-is-consistent-ref.html": [
@@ -322674,7 +322703,7 @@
      ],
      "parsing": {
       "block-ellipsis-valid-expected.txt": [
-       "e6a3ae3d8212cb17dbb4a5d298f6df2c6c4ac102",
+       "44fafffe6bee42515a362d6529f0faa89a0a65fb",
        []
       ],
       "continue-valid-expected.txt": [
@@ -322682,7 +322711,7 @@
        []
       ],
       "line-clamp-valid-expected.txt": [
-       "f3b1d3cb90716b580f4d5469e38ec25b41ec5b4a",
+       "525238db6235243a49076be2472dc6578e099867",
        []
       ],
       "max-lines-valid-expected.txt": [
@@ -323180,6 +323209,10 @@
       "size-001-expected.txt": [
        "8a02abd1ff485ee68055366480945e9746d490aa",
        []
+      ],
+      "size-invalid-expected.txt": [
+       "46b13aaa6eac34d91b62cd148c8c5f4ea4d6d1c0",
+       []
       ]
      },
      "pseudo-first-margin-print-ref.html": [
@@ -325690,7 +325723,7 @@
        []
       ],
       "shape-outside-valid-expected.txt": [
-       "ce2e5fd3a13e9f604da8430515defb0d116959f0",
+       "cce64c0c57cd5d96a7be497708efdc08c81befd9",
        []
       ],
       "shape-outside-valid-position-expected.txt": [
@@ -327349,7 +327382,7 @@
       }
      },
      "input-preprocessing-expected.txt": [
-      "d950461f5cceae3c6ede6984a5abd0f50133fadd",
+      "6101d4fe92de393d7c6df29b4cc76e6dbeebbedd",
       []
      ],
      "missing-semicolon-ref.html": [
@@ -334859,6 +334892,10 @@
        "c0f7b134ff331fbb4f0684d9ca13cbd1bd6b0a25",
        []
       ],
+      "outline-auto-with-001-ref.html": [
+       "9ae9e60fa3e1c893d07346a796f1a79ff68be44d",
+       []
+      ],
       "outline-offset.html": [
        "63f852ca466249417a93341762069c999b4e6905",
        []
@@ -336466,7 +336503,7 @@
      },
      "urls": {
       "fragment-only-expected.txt": [
-       "37b1f6355559b5c9d79cf43c89008f6713f35639",
+       "e79da1e4b879f3f871eb3f2fb2627fbd4f98297b",
        []
       ],
       "support": {
@@ -339679,11 +339716,11 @@
       []
      ],
      "CSSKeyframesRule-expected.txt": [
-      "3a390c9c490e4e66204c946ea86bec92a73da2ab",
+      "6b30c4b2419c81c3244dbc65ef8ed57dd9996502",
       []
      ],
      "CSSStyleSheet-constructable-baseURL.tentative-expected.txt": [
-      "c50d7706a19f85315522e5d7afe506972c26f7a6",
+      "e0e6df8d61f13e901716a16769483e32fd922043",
       []
      ],
      "CSSStyleSheet-constructable-concat-ref.html": [
@@ -339775,7 +339812,7 @@
       []
      ],
      "serialize-values-expected.txt": [
-      "9c88d0be820f04ca2d639fbb9784412c85b6b769",
+      "ec85812be62dd85a33d3fa01982074077e86559e",
       []
      ],
      "shorthand-values-expected.txt": [
@@ -342314,7 +342351,7 @@
        []
       ],
       "parse-has-expected.txt": [
-       "798dc1920b2a16d37b940aea350e14e71da0e03b",
+       "b83277a2d022d1dd26b99427b26e49518b99afb7",
        []
       ]
      },
@@ -342703,6 +342740,10 @@
     },
     "zoom": {
      "tentative": {
+      "background-image-ref.html": [
+       "6fe548f3435a61b3d34ecd1fa9be538224b3d28e",
+       []
+      ],
       "basic-ref.html": [
        "5de90caf7f0c72041334349b7c4b1044d373bc22",
        []
@@ -343279,7 +343320,7 @@
       []
      ],
      "testdriver.md": [
-      "14eb3dc79b3a2f6db972f8c7b3626ca5da5e0baf",
+      "73af3bb3c8dd72fc283cdc9440fbe05bd768d1d3",
       []
      ],
      "testharness-api.md": [
@@ -343717,7 +343758,7 @@
       []
      ],
      "DOMImplementation-createDocument-expected.txt": [
-      "0767ab8a23c1b2312a181ca841dcf85a13d7feab",
+      "6b0293a836227dec8ad372fcb1fef7cd0c623a37",
       []
      ],
      "DOMImplementation-createHTMLDocument.js": [
@@ -343949,7 +343990,7 @@
       ]
      },
      "Document-createElementNS-expected.txt": [
-      "0ddf72dc5c735209f7d25e47ceb2b56c3c87acbe",
+      "736ed42666a484557ce194107abe97535d41fe67",
       []
      ],
      "Document-createElementNS.js": [
@@ -344013,7 +344054,7 @@
       []
      ],
      "ParentNode-querySelector-escapes-expected.txt": [
-      "6b5527e27c6844b94788328a1afc39a3036c37e8",
+      "649cdad355e29628dcf5b144c4e8f51a0982cb9d",
       []
      ],
      "ProcessingInstruction-in-doctype-expected.txt": [
@@ -344208,7 +344249,7 @@
      []
     ],
     "XMLSerializer-serializeToString-expected.txt": [
-     "bf54dba237a0daed8988853afdf6d2ca444e1a33",
+     "194c32ced6eaa2a7f963f87111f387f6ef0ab30a",
      []
     ],
     "innerhtml-01-expected.txt": [
@@ -344515,23 +344556,23 @@
       []
      ],
      "delete-expected.txt": [
-      "077672f44d12ed427747a0551ea2284add322026",
+      "3e30412cf8e8638cf935c84428142c52d2450ad0",
       []
      ],
      "delete-in-child-of-head.tentative_designMode=off_method=backspace-expected.txt": [
-      "1a9f17c8636c56619e9d5a707036dbc2bd5d1fa0",
+      "de54b6afb6cbbb58e55d5c367011c57a4b345620",
       []
      ],
      "delete-in-child-of-head.tentative_designMode=off_method=forwarddelete-expected.txt": [
-      "0431e644a21e5bbf050d6001ac8c519b8bb99809",
+      "322f10823f83eb3845af66f9536223d5b51b4bc5",
       []
      ],
      "delete-in-child-of-head.tentative_designMode=on_method=backspace-expected.txt": [
-      "1a9f17c8636c56619e9d5a707036dbc2bd5d1fa0",
+      "de54b6afb6cbbb58e55d5c367011c57a4b345620",
       []
      ],
      "delete-in-child-of-head.tentative_designMode=on_method=forwarddelete-expected.txt": [
-      "0431e644a21e5bbf050d6001ac8c519b8bb99809",
+      "322f10823f83eb3845af66f9536223d5b51b4bc5",
       []
      ],
      "delete-in-child-of-html.tentative_designMode=off_method=backspace-expected.txt": [
@@ -344671,7 +344712,7 @@
       []
      ],
      "insert-text-in-void-element.tentative-expected.txt": [
-      "b77630b2bfe5cf4dcb68331203027f55214b9b6f",
+      "604c99116a7e12bf583ed5f77797ed77a95837ae",
       []
      ],
      "inserthtml-do-not-preserve-inline-styles_stylesAtInsertionPoint=bold_stylesInserting=hilitecolor-expected.txt": [
@@ -344679,247 +344720,247 @@
       []
      ],
      "insertparagraph-in-child-of-head.tentative_designMode=off_white-space=normal-expected.txt": [
-      "28f8f8d3f6fb8b24bdd743bf5d5d9dea92d5536a",
+      "61af227f8da1155aae256a4717e7dd2b49d2daa6",
       []
      ],
      "insertparagraph-in-child-of-head.tentative_designMode=off_white-space=pre-expected.txt": [
-      "ed3ec583b47cafcc80b08f8cd698cd4bce5baba7",
+      "ec5deb4fec3a99f716a52851f5b60ecd7014c26e",
       []
      ],
      "insertparagraph-in-child-of-head.tentative_designMode=off_white-space=pre-line-expected.txt": [
-      "e77cbc4b3853247393d3548658ed8ff75031ed07",
+      "1b7c2fb7f4703b480e9b5dc839a0cc108335b8d2",
       []
      ],
      "insertparagraph-in-child-of-head.tentative_designMode=off_white-space=pre-wrap-expected.txt": [
-      "fd602f905cd36cf06dfb039f8336f45963c33e44",
+      "37d44b8f3869a35c00e771c9c392c9bc2484f1d8",
       []
      ],
      "insertparagraph-in-child-of-head.tentative_designMode=on_white-space=normal-expected.txt": [
-      "28f8f8d3f6fb8b24bdd743bf5d5d9dea92d5536a",
+      "61af227f8da1155aae256a4717e7dd2b49d2daa6",
       []
      ],
      "insertparagraph-in-child-of-head.tentative_designMode=on_white-space=pre-expected.txt": [
-      "ed3ec583b47cafcc80b08f8cd698cd4bce5baba7",
+      "ec5deb4fec3a99f716a52851f5b60ecd7014c26e",
       []
      ],
      "insertparagraph-in-child-of-head.tentative_designMode=on_white-space=pre-line-expected.txt": [
-      "e77cbc4b3853247393d3548658ed8ff75031ed07",
+      "1b7c2fb7f4703b480e9b5dc839a0cc108335b8d2",
       []
      ],
      "insertparagraph-in-child-of-head.tentative_designMode=on_white-space=pre-wrap-expected.txt": [
-      "fd602f905cd36cf06dfb039f8336f45963c33e44",
+      "37d44b8f3869a35c00e771c9c392c9bc2484f1d8",
       []
      ],
      "insertparagraph-in-child-of-html.tentative_designMode=off_white-space=normal-expected.txt": [
-      "3a4c8200d9f48b134e7ce639240f6fb7b1a86030",
+      "daddb4171fe945fb2accbe36b7aefedb31c7d3a2",
       []
      ],
      "insertparagraph-in-child-of-html.tentative_designMode=off_white-space=pre-expected.txt": [
-      "f48bdfffe8fe4151a9692ad57fb7e57f44df3d18",
+      "d24a009f7570a5cbc267083325c067f74f158396",
       []
      ],
      "insertparagraph-in-child-of-html.tentative_designMode=off_white-space=pre-line-expected.txt": [
-      "8fe60a2215de09f0cff5a66ce497f7361e2471d8",
+      "aa7b096c7b60a7bd35273fda1cde4ef1174ca652",
       []
      ],
      "insertparagraph-in-child-of-html.tentative_designMode=off_white-space=pre-wrap-expected.txt": [
-      "3856512a80c2da1d4aa83e2b2d53d3c99b77c9ed",
+      "a35d8191a29c8f38483faeda3a3d80bbe6c30f08",
       []
      ],
      "insertparagraph-in-child-of-html.tentative_designMode=on_white-space=normal-expected.txt": [
-      "3a4c8200d9f48b134e7ce639240f6fb7b1a86030",
+      "daddb4171fe945fb2accbe36b7aefedb31c7d3a2",
       []
      ],
      "insertparagraph-in-child-of-html.tentative_designMode=on_white-space=pre-expected.txt": [
-      "f48bdfffe8fe4151a9692ad57fb7e57f44df3d18",
+      "d24a009f7570a5cbc267083325c067f74f158396",
       []
      ],
      "insertparagraph-in-child-of-html.tentative_designMode=on_white-space=pre-line-expected.txt": [
-      "8fe60a2215de09f0cff5a66ce497f7361e2471d8",
+      "aa7b096c7b60a7bd35273fda1cde4ef1174ca652",
       []
      ],
      "insertparagraph-in-child-of-html.tentative_designMode=on_white-space=pre-wrap-expected.txt": [
-      "3856512a80c2da1d4aa83e2b2d53d3c99b77c9ed",
+      "a35d8191a29c8f38483faeda3a3d80bbe6c30f08",
       []
      ],
      "insertparagraph-in-non-splittable-element-expected.txt": [
-      "864a71efd0e546d2956557539548cd95246fed69",
+      "80b29f41329a5794f13edcff20ab0ae3363cd15a",
       []
      ],
      "insertparagraph-with-white-space-style.tentative_white-space=nowrap_command=insertParagraph-expected.txt": [
-      "d9bedbef4c00848371156aaa6dc43c2ca1a09c54",
+      "d3c2cf3a9213fb7b1021c5d7f5b71722d7043fac",
       []
      ],
      "insertparagraph-with-white-space-style.tentative_white-space=nowrap_command=insertText-expected.txt": [
-      "d9bedbef4c00848371156aaa6dc43c2ca1a09c54",
+      "d3c2cf3a9213fb7b1021c5d7f5b71722d7043fac",
       []
      ],
      "insertparagraph-with-white-space-style.tentative_white-space=pre-line_command=insertParagraph-expected.txt": [
-      "928ac6685145189a7bec8d43908c2c04748f85b1",
+      "8af6e4c1eb2d9974fbe160046249d1d14b5389fc",
       []
      ],
      "insertparagraph-with-white-space-style.tentative_white-space=pre-line_command=insertText-expected.txt": [
-      "928ac6685145189a7bec8d43908c2c04748f85b1",
+      "8af6e4c1eb2d9974fbe160046249d1d14b5389fc",
       []
      ],
      "insertparagraph-with-white-space-style.tentative_white-space=pre-wrap_command=insertParagraph-expected.txt": [
-      "b8dee8a31017e738c49dd783eda312f028637584",
+      "683476435f47f77c338883866963130e1fcffbed",
       []
      ],
      "insertparagraph-with-white-space-style.tentative_white-space=pre-wrap_command=insertText-expected.txt": [
-      "b8dee8a31017e738c49dd783eda312f028637584",
+      "683476435f47f77c338883866963130e1fcffbed",
       []
      ],
      "insertparagraph-with-white-space-style.tentative_white-space=pre_command=insertParagraph-expected.txt": [
-      "c20f6012561ec768c98359d61f2f422e3d314161",
+      "f092b5fa94d22120cbb7523a874a776028aec45c",
       []
      ],
      "insertparagraph-with-white-space-style.tentative_white-space=pre_command=insertText-expected.txt": [
-      "c20f6012561ec768c98359d61f2f422e3d314161",
+      "f092b5fa94d22120cbb7523a874a776028aec45c",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=normal_right-white-space=nowrap-expected.txt": [
-      "a4a9d155a50a2b7697b736ca5caec3f0536387ad",
+      "770d21d13c0e1fa7448f950bc8b4808a2ebd0472",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=normal_right-white-space=pre-line-expected.txt": [
-      "565a1c0985957e3eef036fef7da25119daa0f5b3",
+      "2c4404882edfa1415f153e9b4f65d5862e8c2840",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=normal_right-white-space=pre-wrap-expected.txt": [
-      "874798e302ed0fe75747a1f67e370b32dc9ab7a5",
+      "93361f3d605f2d30137e4a7df601694cdac0d5e7",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=nowrap_right-white-space=normal-expected.txt": [
-      "73b1693151362a5c886478bb1fa61eb64fa1a24b",
+      "72871f2481eb868814fd94bf5f1877c6c8c546d6",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=nowrap_right-white-space=pre-expected.txt": [
-      "38bfcfb03c739c23ab5cc7bd919b791da163090f",
+      "c3e8d8cb46984969d468c793d7e40f514cd9bcf3",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=pre-line_right-white-space=normal-expected.txt": [
-      "aab2bafc07469eec35f773425814c95a2350fc7c",
+      "25eb53402838181cd316ac2387cafbe6fb8c92ae",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=pre-line_right-white-space=pre-wrap-expected.txt": [
-      "74da83da3f87e98f62b9ba58ffca76ca54a89505",
+      "1f837b9f65402fa63aaeef0259b27451a68a7272",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=pre-wrap_right-white-space=normal-expected.txt": [
-      "ad689c1d7819eb342fb50a6044a684f3b8aa603e",
+      "e76c14662b7c70973299a94ea4ebdbd4afb79dce",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=pre-wrap_right-white-space=pre-expected.txt": [
-      "76581cd4d65ef37509a0ff46c69ca643497f9c76",
+      "4e4ce46295fde9b5c6a25dff729dfd1d169cb0a8",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=pre-wrap_right-white-space=pre-line-expected.txt": [
-      "6f3e7a8594ebd9ba5195ba53e68930533c4bae95",
+      "139012c3af34bca1a3ed4fd8f964685ea386981a",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=pre_right-white-space=nowrap-expected.txt": [
-      "fc82e925e110857128d3e9555b20c7998418ff61",
+      "5510240dd2b0c2011b8e3379d08b07a9d84af9f6",
       []
      ],
      "join-different-white-space-style-paragraphs_method=backspace_left-white-space=pre_right-white-space=pre-wrap-expected.txt": [
-      "feab26edf6447b6e6d3e2f0118cccf6e5065e80d",
+      "4442992a90cf629101a97e901aba134842b849f8",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=normal_right-white-space=nowrap-expected.txt": [
-      "7a54dfef8ce27671e21027a2d45f6667c337a023",
+      "cab042f3c181fa04899ee0f08a57a2da2ff28e53",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=normal_right-white-space=pre-line-expected.txt": [
-      "ffdd6a063d3f16e3a85dbe8c92f8b56d22fe1753",
+      "15f5e983cf2ebbbe20c769665fe28168c54b18ab",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=normal_right-white-space=pre-wrap-expected.txt": [
-      "6e4690c0b64c996eeb742a1e95a823532b37c893",
+      "ff2cbd88ee4c0e87a2521c85f750da17a658c936",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=nowrap_right-white-space=normal-expected.txt": [
-      "eb27c80c0c7ef415f1456568fa0d7d375817e479",
+      "fb9b6df951ccfe19e78d85a7095859ac73b808d4",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=nowrap_right-white-space=pre-expected.txt": [
-      "12e217e7dc36b733d613531cad66ac16a9cb21ed",
+      "1bf52b7265a8e662ed4f1f4d66106e53230d3a75",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=pre-line_right-white-space=normal-expected.txt": [
-      "f6b9d243fd631760d92a9e9264334d6fea05aef9",
+      "473947d357d232df58b2504d62c67e117000ca7a",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=pre-line_right-white-space=pre-wrap-expected.txt": [
-      "3dbefebeef9f8aeabca8c206d8245e0886bc66dd",
+      "b8fff5d96e85c72fd161c9c75a07f0a71c26bc72",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=pre-wrap_right-white-space=normal-expected.txt": [
-      "00e2baaa8e96b22c242825a06e82eaa46912dde0",
+      "9ddfb481f4567fb6e560c9ef0d51aa029950981b",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=pre-wrap_right-white-space=pre-expected.txt": [
-      "4978049ce3d547b518470cd843fd918cde202ef8",
+      "40fc953bbfd8936cad299abf58e9c180e858c051",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=pre-wrap_right-white-space=pre-line-expected.txt": [
-      "26cdec8dc1470543083b1ea98ca35f101d2e0533",
+      "01885e82505791167d7d2f5699b826c45f66d72d",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=pre_right-white-space=nowrap-expected.txt": [
-      "ae9059c0a69d0330218ebbf2024c5dfcb890704e",
+      "f3e8d8648b3cd08ffbd401490085b6de395c4f78",
       []
      ],
      "join-different-white-space-style-paragraphs_method=forwarddelete_left-white-space=pre_right-white-space=pre-wrap-expected.txt": [
-      "8e028254113bc0f9ed65d6405a726c1f79e0ffac",
+      "d61d969d66b99bcd3a7986c8c9ffcfc9ca19741e",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=normal_right-white-space=nowrap-expected.txt": [
-      "c2702df4dbf05521d3c88bc5d27935511c5ad3d9",
+      "f29543da31c1c0f258d4508831708c2ef11b38c2",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=normal_right-white-space=pre-line-expected.txt": [
-      "2d0dc1de09fda8329de51e7191a61b61ed93323f",
+      "e371bb01b97b9de164c9d9d44649c491ad409754",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=normal_right-white-space=pre-wrap-expected.txt": [
-      "fc4de2e3df6c3c688591adf39e866c64ae7cf97e",
+      "0a1740fa0f4c2c6136bbeaf3ab4d82951b024e20",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=nowrap_right-white-space=normal-expected.txt": [
-      "17aaf765622b73406592970fb9048731d74de696",
+      "6eadd8d48b5bdc92d530cb50e5f0f259eaff4c4d",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=nowrap_right-white-space=pre-expected.txt": [
-      "8faf65a7317993492461d84962d665d351c99dd8",
+      "7104aa7599a434c517730b1cb8c876a2299dd4f9",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=pre-line_right-white-space=normal-expected.txt": [
-      "e0c273b9257d80dbb481f09aed196911f5ed3e10",
+      "e93598c8a5e76909a493bb6f84acf879a6681f39",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=pre-line_right-white-space=pre-wrap-expected.txt": [
-      "045af2bd273186e4000b9d575ad34e3b450bd78c",
+      "d3d623e0b836ffbe9349f0313ccb1a6516f58aa6",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=pre-wrap_right-white-space=normal-expected.txt": [
-      "f8f90f60a357d27bc226a3ca4f4f6b6af2a002b4",
+      "9e1070447126a6e50b2989751f2ecddf226ff942",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=pre-wrap_right-white-space=pre-expected.txt": [
-      "ed14c3eda5e7d1dfae3e9683a7d60991cbafd11c",
+      "4c2025a88904598c48831bd46ed9d74df8d36ce4",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=pre-wrap_right-white-space=pre-line-expected.txt": [
-      "e4c02e1507408283371a775a23edb49365eef48f",
+      "2d410bdcddc81b36e29f5a025ece84c9b49148fb",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=pre_right-white-space=nowrap-expected.txt": [
-      "c201dda56893ed7faed7bde70374206d2cc4b7ae",
+      "131bc3c34a9308d7a066d3f414e0334e1e56f4ba",
       []
      ],
      "join-different-white-space-style-paragraphs_method=select-boundary_left-white-space=pre_right-white-space=pre-wrap-expected.txt": [
-      "a2f0a34d1eaf974bc3b82a4d5693c5011f55123e",
+      "9d01112728b9be0ad2ea6aabca94eb5ad2e1ccda",
       []
      ],
      "link-boundaries-insertion-expected.txt": [
@@ -344939,43 +344980,43 @@
       []
      ],
      "typing-around-link-element-after-joining-paragraphs_action=Backspace-expected.txt": [
-      "ca28dfe9b034b8ce02ec2baf937210fca373121d",
+      "a700162270b5ec4f757c1f1dee844efb245b7c72",
       []
      ],
      "typing-around-link-element-after-joining-paragraphs_action=Delete-expected.txt": [
-      "c3c9e5e821e2bc7bcb3dd9934784f3f6cf16cc75",
+      "b85bc1c7d05bd698017f5ad66cc475a2e08632b9",
       []
      ],
      "typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode-expected.txt": [
-      "bbe92b66831da8ae81eee3fc9a2569fd84b219da",
+      "54421044ee641c832865471437c46dbdf0a882ac",
       []
      ],
      "typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_child=b-expected.txt": [
-      "ad8b7e52027567ad1e36d7cc454fcc01a5cd86ff",
+      "d5653ac1a866b1a60009c3e9ee1e556401eb5e9f",
       []
      ],
      "typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_parent=b-expected.txt": [
-      "fc28545bbbd440bd2274591418d95e79e5802b91",
+      "0245e50085ee220d16c25cbabc40e504a83106f2",
       []
      ],
      "typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_parent=b_child=i-expected.txt": [
-      "7b9312f58414de58600d2a8c204171e2439f3f39",
+      "f79f9e39fe5575ebbcf52e56e670f35cc6dafe20",
       []
      ],
      "typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode-expected.txt": [
-      "1f08ed4d5ee478f9d7b75a11a5df358b324d95f0",
+      "433bbf6ae1191b31419256f491ce0241eea7ce04",
       []
      ],
      "typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_child=b-expected.txt": [
-      "bdd0056185e942d816c5e1f8682827ce3828b8a6",
+      "4a4212ae8edc8ed9aa3bf3ad7aa8781a1cde36f4",
       []
      ],
      "typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_parent=b-expected.txt": [
-      "94114e42036d9781b83939ee9413095f50ad4cdf",
+      "2fd44fac2e4b48adc40ab5f3190625daeef355c1",
       []
      ],
      "typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_parent=b_child=i-expected.txt": [
-      "c688ae42571cdcd4be12ee5daebcdc5dc3891871",
+      "cf6c34a076bb13835cd80f3a51457ae893816103",
       []
      ],
      "typing-space-in-editable-button.tentative-expected.txt": [
@@ -344989,87 +345030,87 @@
     },
     "run": {
      "backcolor-expected.txt": [
-      "1210f039da41c8e830f757ce029740db49eb6249",
+      "9b0553dcd9861af2bc6cb202e74da6dab3ea4202",
       []
      ],
      "bold_3001-last-expected.txt": [
-      "3e2a022fa0d639030e5c3ac0f5e931479a4be9e1",
+      "19b5b017776834ce4f6400cb5e09030df52d1138",
       []
      ],
      "createlink-expected.txt": [
-      "f3dd19a7a62ac919b337e2ca53330c7a816a8627",
+      "fbc121bf6cb60c6b589d40604a800fc85c27ea76",
       []
      ],
      "delete_1-1000-expected.txt": [
-      "d1a7944eb028dd32717b25b1292bf4f90b75b0c6",
+      "07040bbb0ee4e3c41cfa545e96cee7a35dd45c36",
       []
      ],
      "delete_2001-3000-expected.txt": [
-      "dc8b7da1302b5910e0c8d79a97d8a6d42e1c97c7",
+      "718cc8effde1bc4c3e01478c434c1094143b782e",
       []
      ],
      "delete_3001-4000-expected.txt": [
-      "73dcbb2170b20992da00b960dec6ec323c663835",
+      "4e8ad9b2f494f67c0514d7f7856e56debad72bc6",
       []
      ],
      "delete_4001-5000-expected.txt": [
-      "628b3f40eee096a5a7ba2bd0222b791c1dcf1965",
+      "f5c66fc5fea6c2130c624b25a340ba6ad1966a86",
       []
      ],
      "delete_5001-6000-expected.txt": [
-      "baac17ce9c04a8b37e182fabeb4a58fc6f204e8c",
+      "9a50f53f8f05a378153f657ec97cf62508011808",
       []
      ],
      "delete_6001-7000-expected.txt": [
-      "dc7b78f7f24478d31af6cb06865ef60ec07b909d",
+      "f44797ba7dc1620be75b6c0ff640ab970174adb6",
       []
      ],
      "delete_7001-last-expected.txt": [
-      "55443b4b1301ecb4870116681b0cb9fa5fbe0d1d",
+      "5c0586aaf1169e694dcdf80211bfdcf88254ecb5",
       []
      ],
      "fontname_1-1000-expected.txt": [
-      "c48cc0396ff495a5282ea9b0e98ac9b1d16e5c04",
+      "649b0c1831f1ac875a7eb5ec99ca51d7820c94fc",
       []
      ],
      "fontname_1001-2000-expected.txt": [
-      "0cd85ce4ec4d66e412ec321fc54f9d07475628e3",
+      "c25b7ff06b2e194491156134c033bd30af271d95",
       []
      ],
      "fontname_2001-last-expected.txt": [
-      "c6c577a2ad4982fd13b0cbba035895d0c627f388",
+      "aaf8000baff98cab59db7d7f0b75aab04495da68",
       []
      ],
      "fontsize_1-1000-expected.txt": [
-      "2b98d16054da8624b17834a43f2cb89f33ed745e",
+      "a8095e23eb55635dab483cd17b36a8a93f4441d8",
       []
      ],
      "fontsize_1001-2000-expected.txt": [
-      "27c0454497a918c4c8276a2ad913f0e63113b2fd",
+      "3b4933560612031c3beb594334e3e72eb5bd8f66",
       []
      ],
      "fontsize_2001-last-expected.txt": [
-      "05b65dc12b16bc6091ff42639cf2c3b99ab1a026",
+      "2366897dac65817ad89ec68b15a3d106598f82c0",
       []
      ],
      "forecolor_1001-2000-expected.txt": [
-      "b593b39658cb2cb01c3ce410e0c7ca059fc0789e",
+      "98e870729b17b8cf7fa6488ede83aaad8d22dae9",
       []
      ],
      "forecolor_2001-last-expected.txt": [
-      "955801f776617ce74f291fb12df493f7a8624abb",
+      "2c746229a2211d30346c59a567e3916e3d4b2acb",
       []
      ],
      "formatblock_1-1000-expected.txt": [
-      "31e7ff528c51bc91a0051d2ffeeec6112acfecf6",
+      "e0a4428fdd33c7d8e0d733d031923416714479de",
       []
      ],
      "formatblock_1001-2000-expected.txt": [
-      "f1ccb3624cfdbc098a86b332e1b85e98b302c6b8",
+      "f20bb0d108338f1c8509b44f0d5029f5d18e248d",
       []
      ],
      "formatblock_2001-3000-expected.txt": [
-      "59b88edb7530debebd5627e292054f95c63ca1a5",
+      "9e0c88b35f211b073de81e5da30509c8b2d9d385",
       []
      ],
      "formatblock_3001-4000-expected.txt": [
@@ -345077,7 +345118,7 @@
       []
      ],
      "formatblock_4001-last-expected.txt": [
-      "849dd5f2520531e90a13f447868686587c0dc66d",
+      "e14906f3245d84f484d9f6014235d6c3d6eb3603",
       []
      ],
      "forwarddelete_1-1000-expected.txt": [
@@ -345089,155 +345130,155 @@
       []
      ],
      "forwarddelete_2001-3000-expected.txt": [
-      "01d3419245143fb0f112f52603125c93f92d71d6",
+      "a7f182321fce0edaac85e172933186c3cd245662",
       []
      ],
      "forwarddelete_3001-4000-expected.txt": [
-      "eb53f5a10a818d068871363ce3606c967d043cde",
+      "6f880bc6491fa51e423df74aff30173cb35f5b13",
       []
      ],
      "forwarddelete_4001-5000-expected.txt": [
-      "efcafa7aa2e39d44b40f8911760cdec4d64af069",
+      "5c71a87da8649cc9c6ea064bfe6a2ae86cddadf7",
       []
      ],
      "forwarddelete_5001-6000-expected.txt": [
-      "f585c75e305768259dd9700f3e5eefa3cdbc7f80",
+      "69c32527d915426a99328042ab03e0204ddf1ca3",
       []
      ],
      "forwarddelete_6001-7000-expected.txt": [
-      "afcf62a00bf7d57c8a11c255a8799ba93b6b359c",
+      "9e36ee4442b70e7496915c35c385874213c0b278",
       []
      ],
      "forwarddelete_7001-last-expected.txt": [
-      "3fb0abbbd8863a3f024c796cbfef2e1871a542c5",
+      "ce88a37bc232ab3a2a97e4e0ce12a96742d8459c",
       []
      ],
      "hilitecolor-expected.txt": [
-      "429032df316dc084e01383805c233a665b930a2d",
+      "c423830889449cb258eb5b7dc4738b3b4d7c25b9",
       []
      ],
      "indent-expected.txt": [
-      "bfa0cb63e100c24c15f5906b5cd6f6cbcc45edff",
+      "039ae0dd0b3721866ba3471ec06598296e43a91f",
       []
      ],
      "insert-list-items-in-table-cell-expected.txt": [
-      "f3c4339340df96067c14e6f34dc545f764888a9f",
+      "9c5435c2a75b85cd38d8b8a496ee6c2aecb357d4",
       []
      ],
      "inserthorizontalrule-expected.txt": [
-      "849cffbe951da711aa4b346e7608d75d5707ed2d",
+      "4b887f509336c91cafda67a1c25f0bafb3d942e3",
       []
      ],
      "inserthtml-expected.txt": [
-      "d57e5681eead4c4b08a464cc3a3cbbf1fe8811a6",
+      "7a13e4a6b5f695a34813335965f29b11f751133d",
       []
      ],
      "insertimage-expected.txt": [
-      "7694082981ab89336efc3de74e83b44c02919b2e",
+      "1c776fa392068518cb79b402a0c55f444bee5e80",
       []
      ],
      "insertlinebreak-expected.txt": [
-      "5e970c913e3361126804c71994a19824cf72c853",
+      "364ff4293b032f4086def5d38822ced18a521098",
       []
      ],
      "insertorderedlist_1-1000-expected.txt": [
-      "5edada2d9e75e67fda504c8c10e4f6ee45b3ae76",
+      "87d1af97666ee377f4f49bfce1e87201279c222b",
       []
      ],
      "insertorderedlist_1001-last-expected.txt": [
-      "de7aee8c45a80b0ff77afac2ec5bd51097e31644",
+      "33e12f244e7f24ee6824fbce0e5047015a8c0155",
       []
      ],
      "insertparagraph_1-1000-expected.txt": [
-      "ded6227279c63c44c9add6e2815bf8a497e83c9e",
+      "f336698288b6dd24128bf44c14346c606c1d7675",
       []
      ],
      "insertparagraph_1001-2000-expected.txt": [
-      "4918f4dee4081ca7e97a99a475887382f299f7c4",
+      "72eaf4523632aa781aad78cba6d025f67a104c30",
       []
      ],
      "insertparagraph_2001-3000-expected.txt": [
-      "22aeee531fd42053964adfd31f60770169a0d61d",
+      "00ba226a5a36666a5bd937892b1f5910995f9657",
       []
      ],
      "insertparagraph_3001-4000-expected.txt": [
-      "e5dfc7dc3033816f7eed0adfcb450487cbfde682",
+      "914613571749c0b3cca4b8eb3f0411c00e8f6c35",
       []
      ],
      "insertparagraph_4001-5000-expected.txt": [
-      "98557d34b16b74e050f0f7bad60c539935a15c8a",
+      "975e5d02602aebe354c2e100e90e6759b2ddf1b9",
       []
      ],
      "insertparagraph_5001-6000-expected.txt": [
-      "98d097e3be823e76776a82cf37a127e46fdc9e9a",
+      "3b21b8196202156de2ad78505dedad898b71618b",
       []
      ],
      "insertparagraph_6001-last-expected.txt": [
-      "e2db4af5226ab1f2a42cdd3d3c42d2d6d84d849a",
+      "ea29ff9b183ac7c5ca105dfe867dbc2003837192",
       []
      ],
      "inserttext_1-1000-expected.txt": [
-      "89d8a734c16d0d908c53b936d89d7c08b79aa0c2",
+      "f1a8fac715657b1ef13a240fa898bd5c7d31d9b4",
       []
      ],
      "inserttext_1001-2000-expected.txt": [
-      "f990a095569d7943d371558d9a5fe4b96a42e0e2",
+      "a6136d5366716d2ca860a987ab109a5b04ae8347",
       []
      ],
      "insertunorderedlist_1-1000-expected.txt": [
-      "1210d25c2219532ae730b5429d48673bcb0317a3",
+      "7ecdcea030c92d6572feb01ba254ef95711e8be4",
       []
      ],
      "insertunorderedlist_1001-2000-expected.txt": [
-      "5d0e51b5759df6d23f93f24625e86b89df361e6f",
+      "7a4741b59f056daad513b9819e7e358f81a33411",
       []
      ],
      "insertunorderedlist_2001-last-expected.txt": [
-      "0f14c0247cf31f91abcc7dfc6d67b47ad09ded83",
+      "674649aee4990dd308909ccc6cfd1a4113c80d75",
       []
      ],
      "italic_2001-last-expected.txt": [
-      "734ed3b6207241659e6130c0164d1cf8160876e3",
+      "01a6b25f6f0f3f1c69313d11f3911cde391c689c",
       []
      ],
      "justifycenter_1-1000-expected.txt": [
-      "48246ac78071df3f0f9af7d739cb85f26feb26c3",
+      "4bad8d288f230ea838842650be2929cdab17408b",
       []
      ],
      "justifycenter_3001-4000-expected.txt": [
-      "dafee9c8af32cc8cdde63b313f5e230aab057bf3",
+      "9f6ade46d6856a01119bc443492747414362852f",
       []
      ],
      "justifycenter_6001-last-expected.txt": [
-      "8f7faea9d3af135df97dd29e49fea174b438b0c7",
+      "9823701581f5dea97ea736fce1e7fda9affcf7d4",
       []
      ],
      "justifyfull_1-1000-expected.txt": [
-      "a6e6ce5affcb4c4dee77320b046260e57a9d744a",
+      "453522577b104088a663f55f24b3e07d7ebddb3d",
       []
      ],
      "justifyfull_3001-4000-expected.txt": [
-      "d4c4f265e00e88b60d20300406e914fdb8291c03",
+      "0cfaea8aaae8bece677fd082381d910b6fcff83f",
       []
      ],
      "justifyleft_1-1000-expected.txt": [
-      "d60f0df511e25ba602b69cd0f8885a476dee3abd",
+      "13789f75a6c1557e4f76681c1c9337d4ffe8efea",
       []
      ],
      "justifyleft_1001-2000-expected.txt": [
-      "59f2efa9a6bea075ae26b6f1c83a419ee0184e78",
+      "49fefff0bd1fe9c873020cd828c8dced1571c8cf",
       []
      ],
      "justifyleft_2001-last-expected.txt": [
-      "3c2e526fd920127fa4b5d245e6211d151f30118b",
+      "ccd002dd8b24b54a2f35f4ddffd0fe6b5de0046c",
       []
      ],
      "justifyright_1-1000-expected.txt": [
-      "033f1fe6b34feb368b1dbee57037d6f7e1d78d5d",
+      "3f3a3905175b96410d71175d20ac9d0d2431eecf",
       []
      ],
      "justifyright_3001-4000-expected.txt": [
-      "f7cd955b020af6f7b7be6ca591f5adab9220b084",
+      "3a6cb7da347c9925280bdd2e9fa9213c9cb06e9a",
       []
      ],
      "misc-expected.txt": [
@@ -345245,67 +345286,67 @@
       []
      ],
      "multitest_1-1000-expected.txt": [
-      "7c486f3c920b783df7b0b5748a98a7986319ead0",
+      "f7860ef60390dae41eaf88fed51eafc2244a8aae",
       []
      ],
      "multitest_1001-2000-expected.txt": [
-      "eb7926048cb0726e6e2ad092a320c95486983083",
+      "c5b2ed055b152440ee40943ec670832187c3b786",
       []
      ],
      "multitest_2001-3000-expected.txt": [
-      "fb21dfc3009f31cf0051b1cbf9f25b2b41ce0c9b",
+      "dbf4a4610996e1b4ce853c9965da04966e77d40e",
       []
      ],
      "multitest_3001-4000-expected.txt": [
-      "6de4aba2048dfeeb488c5b0cb01f3025b1e031b5",
+      "f5956eee0679fc60c1ec9cdade91508253cfe665",
       []
      ],
      "multitest_4001-5000-expected.txt": [
-      "4ea7a951663be9f555bbd1219cc8e6ea2a584c98",
+      "ec34495fe8eb9032f9750f8019c3b83ec9210efb",
       []
      ],
      "multitest_5001-6000-expected.txt": [
-      "1d6cfe3aab21811d1fbc3b2e4d59d7d30175ae78",
+      "75fffb157bd83be969e5b1ee28e8eba23e5cab17",
       []
      ],
      "multitest_6001-7000-expected.txt": [
-      "2b4b87982c27855dbf52132eeabaa205954c6535",
+      "7edef9a2274082cd61c6926616d7777216920b30",
       []
      ],
      "multitest_7001-8000-expected.txt": [
-      "ee3365ef2c3e24febe24bb079e9167156c1d300a",
+      "bd645a3c3b67d18635e07282c197c7c3cd954380",
       []
      ],
      "multitest_8001-9000-expected.txt": [
-      "4c75d3b06cd3d3d4e3badda12447ee5ed5f6dacf",
+      "faff60ce52ff862711e433db357fc783e968309c",
       []
      ],
      "multitest_9001-last-expected.txt": [
-      "0e4485316c77799acdd7c5a62703283fe6e3d8fa",
+      "3c33fbf5691453ba0b8bb29b013adeedc49462f0",
       []
      ],
      "outdent_1-1000-expected.txt": [
-      "1f65c854dee77526da0fa8d5b21b284e39224fc6",
+      "3d5ec008ff03e073e37f6c24aa0b4ff25b4520f6",
       []
      ],
      "outdent_1001-2000-expected.txt": [
-      "2f6acce4060178e0d457b620249bc8de050b6f8b",
+      "b31c646539e93a02ffa2140c24fff3a4ae3e64c1",
       []
      ],
      "outdent_2001-last-expected.txt": [
-      "8488646b3327633111c1fa555b1424cf2f8a6627",
+      "feee928b46290e2b6861c66b27952e84b684c00e",
       []
      ],
      "removeformat-expected.txt": [
-      "a3021dda3625b1d0404bc5a2b5d42d91b8dc8d74",
+      "6d4e200465d1bd17d99124c02a47d991e043a2ba",
       []
      ],
      "strikethrough_1-1000-expected.txt": [
-      "4dc2ee0b510c27c094f89c324505c9fe41d13e31",
+      "688ffbf2710e9639a58fc7bb1bd291008c47c0c3",
       []
      ],
      "underline_1-1000-expected.txt": [
-      "f4215dd94fd9e1a1a7c47a64c6a514494f232d92",
+      "b2d00095f969418e8471298969144d153374a650",
       []
      ],
      "undo-redo-after-mutation-expected.txt": [
@@ -345313,7 +345354,7 @@
       []
      ],
      "unlink-expected.txt": [
-      "2d416ba7c4cb2111ac5f70d8856d9d591d40dd34",
+      "c9323e6c6e429aa78dd2b9f0db66499cab5c71e4",
       []
      ]
     }
@@ -349039,7 +349080,7 @@
       ]
      },
      "script.window-expected.txt": [
-      "557127b2aeaa82894487c3301010dd93747f504d",
+      "b600492cda52a6aa8bd4a1af90b5473bae0f6d2b",
       []
      ]
     },
@@ -349281,19 +349322,19 @@
       []
      ],
      "processing.any-expected.txt": [
-      "6106e8434e327a82a978c5dce01f314f14146ef7",
+      "bb678f54e8c1d3accaf3b64b852cf80f638d8bc9",
       []
      ],
      "processing.any.serviceworker-expected.txt": [
-      "6106e8434e327a82a978c5dce01f314f14146ef7",
+      "bb678f54e8c1d3accaf3b64b852cf80f638d8bc9",
       []
      ],
      "processing.any.sharedworker-expected.txt": [
-      "6106e8434e327a82a978c5dce01f314f14146ef7",
+      "bb678f54e8c1d3accaf3b64b852cf80f638d8bc9",
       []
      ],
      "processing.any.worker-expected.txt": [
-      "6106e8434e327a82a978c5dce01f314f14146ef7",
+      "bb678f54e8c1d3accaf3b64b852cf80f638d8bc9",
       []
      ],
      "resources": {
@@ -349953,15 +349994,15 @@
        "6247f6d63211cd39dffca9fc507aefcdee586eba",
        []
       ],
-      "fenced-frame-local-network-access-target.https.html": [
+      "fenced-frame-private-network-access-target.https.html": [
        "2b55e056f39834bbad4af96d2dc2549fbc400bf7",
        []
       ],
-      "fenced-frame-local-network-access.https.html": [
+      "fenced-frame-private-network-access.https.html": [
        "98f118432e0ee13b8b089977bd3c640343005497",
        []
       ],
-      "fenced-frame-local-network-access.https.html.headers": [
+      "fenced-frame-private-network-access.https.html.headers": [
        "6247f6d63211cd39dffca9fc507aefcdee586eba",
        []
       ],
@@ -350010,7 +350051,7 @@
        []
       ],
       "support.sub.js": [
-       "3d71b2d298d8507a49856f174d7f8c715f9eaa3b",
+       "0cb757ca640d97353b218ae5c257199962e2b9bd",
        []
       ],
       "worker-blob-fetcher.html": [
@@ -354111,7 +354152,7 @@
         ]
        },
        "open-features-tokenization-screenx-screeny-expected.txt": [
-        "2800b95b5cc25cfa12d06a3e6fb3438ed2e2b106",
+        "d2f3d86accfc3f0157ad795c7ba9a08d1a30bbe8",
         []
        ],
        "resources": {
@@ -357773,7 +357814,13 @@
        "document-lastModified.html.headers": [
         "377e3b52dcba014fa1d121b72a6459677e55e460",
         []
-       ]
+       ],
+       "support": {
+        "document-lastModified-utils.js": [
+         "bbcde1894a8f0a3d97e1a2e441d2e9abb88b1ffe",
+         []
+        ]
+       }
       }
      },
      "elements": {
@@ -358255,7 +358302,7 @@
       },
       "the-innertext-and-outertext-properties": {
        "getter-expected.txt": [
-        "ec2b2e109ec27b526e51a251bd119daecd22c90b",
+        "17da65704d744d5aeea22be040dc168f229bf85e",
         []
        ],
        "getter-tests.js": [
@@ -358347,11 +358394,11 @@
       []
      ],
      "reflection-embedded-expected.txt": [
-      "7c14d4684b22edabcb8cab6d17060ce32e9e4ecb",
+      "185bba2e3e1e3e784cf0b063603355737e8d7124",
       []
      ],
      "reflection-metadata-expected.txt": [
-      "0c6f84f3c4bae7b7b63a3f8291af52dc770e48ce",
+      "6fa281705c3b404cd376c558a9f4961f1874d385",
       []
      ],
      "reflection-original.html": [
@@ -361788,7 +361835,7 @@
        ]
       },
       "structured-cloning-error-stack-optional.sub.window-expected.txt": [
-       "6660e52db2776c2370308ea6b5d5a69ce265c557",
+       "9a873fa832b674e5e91e4ae815198e4b19ef44d8",
        []
       ]
      },
@@ -361890,7 +361937,7 @@
          []
         ],
         "windows-1251_include=xml-expected.txt": [
-         "506c9e1a2774da28685cd25ef4373c2575aff861",
+         "6f481bb83361310acc80539e902793eea65a9f49",
          []
         ],
         "windows-1252_include=base-href-expected.txt": [
@@ -361918,7 +361965,7 @@
          []
         ],
         "windows-1252_include=xml-expected.txt": [
-         "1b9283744d5ffda7357bd1d4c359ab9a99dbe5d2",
+         "42163d703126e4fc43980a0a17f490d92e3f1005",
          []
         ]
        }
@@ -363460,7 +363507,7 @@
         "HTMLElement": {
          "HTMLTrackElement": {
           "src-expected.txt": [
-           "0f322768fec5c2c1f765dabaab612ff74b77910a",
+           "24e72099a1dfb15e044788bb43cede6fa996dc4b",
            []
           ]
          }
@@ -364574,19 +364621,19 @@
        ],
        "sizes": {
         "parse-a-sizes-attribute-display-none-expected.txt": [
-         "c0930862cb3da5ec026716a61f379fcb4bea33b1",
+         "a94cd75dd633ac1e46edf84774143df571c6c7c6",
          []
         ],
         "parse-a-sizes-attribute-quirks-mode-expected.txt": [
-         "3480fd7753dc8ba22949da04b4de831fe29467e2",
+         "43f1fe5a14424be995fc2c152fb109356cfc605c",
          []
         ],
         "parse-a-sizes-attribute-standards-mode-expected.txt": [
-         "87ac83355c780c938be588b99f19a0776789892a",
+         "0e197e106b6997619c22a30db14390093c750064",
          []
         ],
         "parse-a-sizes-attribute-width-1000px-expected.txt": [
-         "53dc4d6d64f8f494c898b00638cab12c6db9dd20",
+         "cc1f728b25f2bd1bca53396b089d830785a458d7",
          []
         ],
         "sizes-auto-expected.txt": [
@@ -367435,7 +367482,7 @@
         ]
        },
        "script-charset-01-expected.txt": [
-        "d207c23707d826e4d3ba2abcb8722407cf2ba46d",
+        "e7c84202595943580c6dde4f1a28e5bb1712722f",
         []
        ],
        "script-defer-xhtml-expected.txt": [
@@ -367800,11 +367847,11 @@
        []
       ],
       "inheritance-bogus-meta-expected.txt": [
-       "800734cb0370dcd127a9ef5762929ddd9285a7ee",
+       "bbd49c5bd99c1cfa3d44352e1de1784db4c8acd3",
        []
       ],
       "inheritance-bogus-meta-utf-8-expected.txt": [
-       "abb65b2bca339d42fffca0bcf92cccb592cb2660",
+       "02fe5a6e126e8a4f905bab1131cf6191b2d67230",
        []
       ],
       "references": {
@@ -367974,35 +368021,35 @@
        []
       ],
       "html5lib_innerHTML_adoption01-expected.txt": [
-       "c8303bebab9b7546a308c56f2b7d3bb78a209005",
+       "88d5d8c50a7d61a81dc17472c057f17203fd4399",
        []
       ],
       "html5lib_innerHTML_webkit02-expected.txt": [
-       "c5f12fbd0c3355c0ebc3988ccfb45b1b004f8733",
+       "b05873bceddf6f360591c59fa6814167cc29d32b",
        []
       ],
       "html5lib_tests25_run_type=uri-expected.txt": [
-       "53788d1469932ccc489bfaedda809cfd4c131e4c",
+       "d9dfca3c268b6b05febd7c9982f8e2e47d6c8a9a",
        []
       ],
       "html5lib_tests25_run_type=write-expected.txt": [
-       "53788d1469932ccc489bfaedda809cfd4c131e4c",
+       "d9dfca3c268b6b05febd7c9982f8e2e47d6c8a9a",
        []
       ],
       "html5lib_tests25_run_type=write_single-expected.txt": [
-       "53788d1469932ccc489bfaedda809cfd4c131e4c",
+       "d9dfca3c268b6b05febd7c9982f8e2e47d6c8a9a",
        []
       ],
       "html5lib_webkit02_run_type=uri-expected.txt": [
-       "a2530ef9f1808147d80365a62d472cacf90f6501",
+       "ce5211833e9627d934afb8d4a4bbe8f2b238270a",
        []
       ],
       "html5lib_webkit02_run_type=write-expected.txt": [
-       "a2530ef9f1808147d80365a62d472cacf90f6501",
+       "ce5211833e9627d934afb8d4a4bbe8f2b238270a",
        []
       ],
       "html5lib_webkit02_run_type=write_single-expected.txt": [
-       "a2530ef9f1808147d80365a62d472cacf90f6501",
+       "ce5211833e9627d934afb8d4a4bbe8f2b238270a",
        []
       ],
       "inhead-noscript-head-expected.txt": [
@@ -368098,7 +368145,7 @@
      },
      "serializing-html-fragments": {
       "serializing-expected.txt": [
-       "f975885d9f4fd6bd2689babc76dc26419e4b78c4",
+       "9ef3d8badfe34fed4dc13b68c4a73b2fb25c42b6",
        []
       ]
      },
@@ -368122,15 +368169,15 @@
          []
         ],
         "link-rel-stylesheet-disabled.tentative.sub-expected.txt": [
-         "1d514baff8570125b288f18de88d869d849d9e17",
+         "2526e0c52674de5d5f09c7500f3b86091571f0f3",
          []
         ],
         "math-font-script-src.tentative.sub-expected.txt": [
-         "1897410a61aa326c0983b0622b3e40f1faf8a59d",
+         "ffe589c792b909164243283833c7f882b041ca8b",
          []
         ],
         "math-script-src.tentative.sub-expected.txt": [
-         "75a6f13ea8726bca4439ddeaf9c7a31b2fcb1a0f",
+         "f14dfd86aa4ef0aae8a7eb9a593e6be1a74cc041",
          []
         ],
         "meta-csp-img-src-asterisk.tentative.sub-expected.txt": [
@@ -368138,7 +368185,7 @@
          []
         ],
         "meta-viewport-link-stylesheet-media.tentative.sub-expected.txt": [
-         "0a3db624c5efd04807cae4b419ab3232c78a87e5",
+         "1c930b1631d9abf63776554d9a6d9567c14c773f",
          []
         ],
         "picture-source-br-img.tentative.sub-expected.txt": [
@@ -368158,7 +368205,7 @@
          []
         ],
         "svg-script-src.tentative.sub-expected.txt": [
-         "0fd215fd3fa33ba9e4e6e02b075e0d631f096260",
+         "69639c0523fd83ca48b9ec9c9dc6ce2e29f21fff",
          []
         ],
         "svg-script-xlinkhref.tentative.sub-expected.txt": [
@@ -370394,7 +370441,7 @@
    },
    "inert": {
     "inert-inlines-around-selection-range-in-contenteditable-expected.txt": [
-     "1e5b9812efe8ed350622666f23543961f0fb275d",
+     "ad32cc1fe1dcd06a914147f4b3100a047cbb085b",
      []
     ]
    },
@@ -370716,7 +370763,7 @@
      []
     ],
     "input-events-get-target-ranges-deleting-range-across-editing-host-boundaries.tentative-expected.txt": [
-     "b58dd0b75298aea5399c412b5252047c16de879c",
+     "f05aab4561d191b60b61e27cac4def612659e9ef",
      []
     ],
     "input-events-get-target-ranges.js": [
@@ -374773,11 +374820,11 @@
       []
      ],
      "parsing.any-expected.txt": [
-      "29e055bea550cbb6f733efe5e0039398f4259b14",
+      "63a3fbe5c967e3cc40d1bd764c266cea2614234e",
       []
      ],
      "parsing.any.worker-expected.txt": [
-      "29e055bea550cbb6f733efe5e0039398f4259b14",
+      "63a3fbe5c967e3cc40d1bd764c266cea2614234e",
       []
      ],
      "resources": {
@@ -376696,7 +376743,7 @@
      []
     ],
     "pointerevent_support.js": [
-     "19f0c2e6175e6dce3edfd8290447bcc988839833",
+     "f67038ead4cfac0d664ec3cedd04beb22b807d3b",
      []
     ],
     "pointerlock": {
@@ -377387,7 +377434,7 @@
    "private-aggregation": {
     "resources": {
      "protected-audience-helper-module.js": [
-      "53b79c0a893e8f6f5f0f8cea67e11b0da37e5bf8",
+      "be4f01379e236938c255a366afca97bdc2e79675",
       []
      ],
      "protected_audience_event_level_report_handler.py": [
@@ -379870,7 +379917,7 @@
      []
     ],
     "testdriver.js": [
-     "0327e1759a9efe3eb698227dc44c5b20262013d6",
+     "ddf723cb3ee8a5b8412cc264fd3e54e780c0ad12",
      []
     ],
     "testdriver.js.headers": [
@@ -380127,7 +380174,7 @@
       []
      ],
      "animation-shorthand-expected.txt": [
-      "63c5718e43dc30c260f4a78e52d9975bb760531d",
+      "80deb0384257fcae561c789e54d7608f30b81848",
       []
      ],
      "animation-update-ref.html": [
@@ -380540,7 +380587,7 @@
      []
     ],
     "modify-line-flex-row.tentative-expected.txt": [
-     "fce007896eaedd1ee57de4cea8395db5584e7618",
+     "2c52fb30ffa7e4bc6221e05834d28c030b68fa0c",
      []
     ],
     "modify.tentative-expected.txt": [
@@ -380552,7 +380599,7 @@
      []
     ],
     "script-and-style-elements-expected.txt": [
-     "ea0f2caff26ed9270613ef313e51162d6e81dd89",
+     "bfb7c0c8a38c389d0642166907c14f5b269e96ac",
      []
     ],
     "setBaseAndExtent-expected.txt": [
@@ -381683,7 +381730,7 @@
       []
      ],
      "local-url-inherit-controller.https-expected.txt": [
-      "8e8673397b7e0d71072773ea3128089731386132",
+      "a71326e7006e8caa61d2be23b88df2bc1445212c",
       []
      ],
      "multi-globals": {
@@ -383471,7 +383518,7 @@
       []
      ],
      "worker-interception-redirect.https-expected.txt": [
-      "5555a5ff6904ccc26e2e2f5298bdd3130679aaeb",
+      "26fc548b5cb51ae3c6bda4244f0589a1661d1162",
       []
      ],
      "xhr-content-length.https.window-expected.txt": [
@@ -383498,14 +383545,6 @@
       "4a1523b1c217cc4ca67f34b0fea6f927e0998c0c",
       []
      ],
-     "getinnerhtml-expected.txt": [
-      "a58d46d609d0ea616dba82c206d0dbfe8840a776",
-      []
-     ],
-     "getinnerhtml.tentative-expected.txt": [
-      "a58d46d609d0ea616dba82c206d0dbfe8840a776",
-      []
-     ],
      "support": {
       "declarative-child-frame.html": [
        "603c47743b807ecc00a483d328edcacb7ebb8d57",
@@ -385858,7 +385897,7 @@
     "interact": {
      "scripted": {
       "async-01-expected.txt": [
-       "990ceb8b973594ce569c0819fd8db420436a854d",
+       "a3a1135a2af17cb37be71fad65f641870df349d4",
        []
       ],
       "defer-01-expected.txt": [
@@ -386080,7 +386119,7 @@
      ],
      "parsing": {
       "fill-valid-expected.txt": [
-       "c60d7192c7d971ad32581adb6f7430cc877945c2",
+       "3be9002245f498fc7c38b8e49d0bc858a1a22f47",
        []
       ],
       "image-rendering-computed-expected.txt": [
@@ -386096,7 +386135,7 @@
        []
       ],
       "stroke-valid-expected.txt": [
-       "e7e4757679c5e22057dd187dfc4a660338c68ad6",
+       "4da72f55373dd8490c9a3c296ac2086877d9c617",
        []
       ]
      },
@@ -386276,7 +386315,7 @@
        ]
       },
       "serialization-expected.txt": [
-       "d548f291b0f85d9bf5a7bfe387d6d7d0d66290e5",
+       "1e5c9163da0d63a79800d7a5faffff6085c7a9f0",
        []
       ]
      }
@@ -386610,19 +386649,19 @@
      ],
      "parsing": {
       "shape-inside-valid-expected.txt": [
-       "7d9ccb9a31501b7fbf23449eaaf94b27f9972e20",
+       "559dd0488d0af44c31b851c59f4b42b32d7c3bc3",
        []
       ],
       "shape-subtract-valid-expected.txt": [
-       "42dbd50e7d6ca67bace72f4feacb5c28ad854606",
+       "fa65eda657d74e57e01d6b5090ae8734bc12881b",
        []
       ],
       "text-decoration-fill-valid-expected.txt": [
-       "0c3e387f6e1324a1d3c5c5d06b8d2614a017daab",
+       "46b17dcc39086cde98954dc54987a353fb8b9bba",
        []
       ],
       "text-decoration-stroke-valid-expected.txt": [
-       "a481d22baecea06dbe6de622f5133d27c6f12e23",
+       "aeff9bbced4378854d00eff4e8041920b1fac156",
        []
       ]
      },
@@ -387838,7 +387877,7 @@
      []
     ],
     "url-setters-a-area.window_include=file-expected.txt": [
-     "3eb6bf2cbb3d05563ed0589369b957a6a9158e78",
+     "3f4d392a972a94f0d13d07e6445cad93fb59ec22",
      []
     ],
     "url-setters-a-area.window_include=javascript-expected.txt": [
@@ -387858,7 +387897,7 @@
      []
     ],
     "url-setters.any.worker_include=file-expected.txt": [
-     "691e438e041007c3cb0c05332abbbd44889c1466",
+     "9b64d7fe444298c3f19ac661985f0f33e1c4a19d",
      []
     ],
     "url-setters.any.worker_include=javascript-expected.txt": [
@@ -387870,7 +387909,7 @@
      []
     ],
     "url-setters.any_include=file-expected.txt": [
-     "691e438e041007c3cb0c05332abbbd44889c1466",
+     "9b64d7fe444298c3f19ac661985f0f33e1c4a19d",
      []
     ],
     "url-setters.any_include=javascript-expected.txt": [
@@ -388772,7 +388811,7 @@
     "animation-model": {
      "animation-types": {
       "accumulation-per-property-001-expected.txt": [
-       "a5936d85c63d65ee04ba9ca2a26ba73aa24a1c5a",
+       "f89b59fe8503a47d0b07fdfec5a3a0b09fb7a5fd",
        []
       ],
       "accumulation-per-property-002-expected.txt": [
@@ -388780,7 +388819,7 @@
        []
       ],
       "addition-per-property-001-expected.txt": [
-       "89f3400ae103bbc99be01c1618b857355474a9f6",
+       "c88df621df5238d693d32c22899b3fb4bed41350",
        []
       ],
       "addition-per-property-002-expected.txt": [
@@ -388788,11 +388827,11 @@
        []
       ],
       "interpolation-per-property-001-expected.txt": [
-       "62e8399c92aad4e9c916aa31f18708a016075a83",
+       "5edf710c91c757301f872e27cd8cc5ebb0118f3a",
        []
       ],
       "interpolation-per-property-002-expected.txt": [
-       "ddce1f40c203d924507716f275e8e0daac40d7ba",
+       "cb351cfd300484b5ed67fd8a6d02bcf1f8af8109",
        []
       ],
       "property-list.js": [
@@ -389431,7 +389470,7 @@
     },
     "resources": {
      "helpers.js": [
-      "4b3311eee6290e62cfb5f504f0319ad7a64d28b9",
+      "3fb89711ab7a2927da2d397c053660ef6e040af9",
       []
      ],
      "iframe-parent.html": [
@@ -391072,7 +391111,7 @@
        []
       ],
       "keys.py": [
-       "3794a4296f6072d7fbd49d4069ad40af5fd438e7",
+       "4771f4d255c9f1b93d61ce18d8cfb9fc7242f1df",
        []
       ],
       "screenshot.py": [
@@ -391663,14 +391702,6 @@
      "add17319159a4f34907d1e4cecb030c1f3713c41",
      []
     ],
-    "softsign.https.any-expected.txt": [
-     "0eba8b5c2c7c8e5c3336339cddfc255b43ca3b8c",
-     []
-    ],
-    "softsign.https.any.worker-expected.txt": [
-     "ddcea72e5dd20aa0add9189e67cbb255199c98d4",
-     []
-    ],
     "squeeze.https.any-expected.txt": [
      "aff3ed0a7384d881e9fe87bfc5662a88af3ebfe1",
      []
@@ -393262,7 +393293,7 @@
        []
       ],
       "getCueAsHTML-expected.txt": [
-       "49b6199ab5791d45a707c8b3b37d0b264b7c4a8f",
+       "6205b1f1e63d0bf0ce070403330368981b6141b4",
        []
       ],
       "lineAlign-expected.txt": [
@@ -396870,7 +396901,7 @@
      []
     ],
     "overridemimetype-blob-expected.txt": [
-     "a2f39785299e05a70ff0158b22899ebb6ad913c2",
+     "6f86cc332d449cff05f4bb64e0605885b1ebf9a5",
      []
     ],
     "resources": {
@@ -397376,7 +397407,7 @@
      []
     ],
     "send-content-type-charset-expected.txt": [
-     "2fdae1f37e17d8728041b81f3ae6ee18417e6b08",
+     "1f5705fcd9c4f6f2ffa0aa13b7c0774efec1c25f",
      []
     ],
     "send-no-response-event-order-expected.txt": [
@@ -397388,7 +397419,7 @@
      []
     ],
     "setrequestheader-combining.window-expected.txt": [
-     "21c2b74a80dc88fc27e8b5cd8109c05a691e9dd7",
+     "ed6f4511b1ade69268b43e25b446f2a5274b9e64",
      []
     ],
     "setrequestheader-header-allowed-expected.txt": [
@@ -427525,7 +427556,7 @@
       ]
      ],
      "report-only-cross-origin-frame.sub.html": [
-      "9393eb2a937a58cb54ac610a592d6a9edd85f681",
+      "3e47e810e9aaec01172de060c9f9c9c050c331c6",
       [
        null,
        {}
@@ -431768,7 +431799,7 @@
     ],
     "fedcm-login-status": {
      "confirm-idp-login.https.html": [
-      "54126c4d6b337f295046a12f297748f17f4e2fc0",
+      "0f8df72b615b5fadb9e17decd69c670652d06d21",
       [
        null,
        {
@@ -431804,13 +431835,6 @@
       }
      ]
     ],
-    "fedcm-logout-rps.https.html": [
-     "51b123003c1e39466a31c68904a4f5633f063697",
-     [
-      null,
-      {}
-     ]
-    ],
     "fedcm-manifest-not-in-list.https.html": [
      "8d85d9eb36783af221d030b95e73b397ba1a1b10",
      [
@@ -465078,6 +465102,13 @@
        {}
       ]
      ],
+     "HTMLLinkElement-load-event-002.html": [
+      "79780813a1ffea3782b8dd4ada85fb3a62330ad7",
+      [
+       null,
+       {}
+      ]
+     ],
      "HTMLLinkElement-load-event.html": [
       "7062f1545061f23c88d38f9f3195dfbcaa133538",
       [
@@ -504311,32 +504342,96 @@
        }
       ]
      ],
-     "send-on-discard.tentative.https.window.js": [
-      "e1ff9b9e3a68e9672fd87b0a098f74bf8e344452",
-      [
-       "fetch/fetch-later/send-on-discard.tentative.https.window.html",
-       {
-        "script_metadata": [
-         [
-          "script",
-          "/resources/testharness.js"
-         ],
-         [
-          "script",
-          "/resources/testharnessreport.js"
-         ],
-         [
-          "script",
-          "/common/utils.js"
-         ],
-         [
-          "script",
-          "/pending-beacon/resources/pending_beacon-helper.js"
+     "send-on-discard": {
+      "not-send-after-abort.tentative.https.window.js": [
+       "c49e0bde87b803ee9b31a6410310511f40b6ac1c",
+       [
+        "fetch/fetch-later/send-on-discard/not-send-after-abort.tentative.https.window.html",
+        {
+         "script_metadata": [
+          [
+           "script",
+           "/resources/testharness.js"
+          ],
+          [
+           "script",
+           "/resources/testharnessreport.js"
+          ],
+          [
+           "script",
+           "/common/utils.js"
+          ],
+          [
+           "script",
+           "/pending-beacon/resources/pending_beacon-helper.js"
+          ]
          ]
-        ]
-       }
+        }
+       ]
+      ],
+      "send-multiple-with-activate-after.tentative.https.window.js": [
+       "03078b2b51647cecaee424edf8b4fefaed65540c",
+       [
+        "fetch/fetch-later/send-on-discard/send-multiple-with-activate-after.tentative.https.window.html",
+        {
+         "script_metadata": [
+          [
+           "script",
+           "/resources/testharness.js"
+          ],
+          [
+           "script",
+           "/resources/testharnessreport.js"
+          ],
+          [
+           "script",
+           "/common/utils.js"
+          ],
+          [
+           "script",
+           "/pending-beacon/resources/pending_beacon-helper.js"
+          ],
+          [
+           "timeout",
+           "long"
+          ]
+         ],
+         "timeout": "long"
+        }
+       ]
+      ],
+      "send-multiple.tentative.https.window.js": [
+       "25ce98d446eaba4b9e0f7d834f647da49d229d37",
+       [
+        "fetch/fetch-later/send-on-discard/send-multiple.tentative.https.window.html",
+        {
+         "script_metadata": [
+          [
+           "script",
+           "/resources/testharness.js"
+          ],
+          [
+           "script",
+           "/resources/testharnessreport.js"
+          ],
+          [
+           "script",
+           "/common/utils.js"
+          ],
+          [
+           "script",
+           "/pending-beacon/resources/pending_beacon-helper.js"
+          ],
+          [
+           "timeout",
+           "long"
+          ]
+         ],
+         "timeout": "long"
+        }
+       ]
       ]
-     ]
+     }
     },
     "h1-parsing": {
      "lone-cr.window.js": [
@@ -509318,7 +509413,7 @@
       ]
      ],
      "component-auction.https.window.js": [
-      "cfaf174225185100227dcb6de568b5c26cb8a005",
+      "83980541f39798fab385a28af528ca616698ea08",
       [
        "fledge/tentative/component-auction.https.window.html?1-5",
        {
@@ -549336,7 +549431,7 @@
         ]
        ],
        "document-lastModified-01.html": [
-        "4d9d870f6a65b7344b7d3c7d4402a0ef3d6c0b15",
+        "81f67390d1a4cdf2538ab7cd7478be1cc2f43677",
         [
          null,
          {
@@ -562014,6 +562109,15 @@
         }
        ]
       ],
+      "invoketarget-fullscreen-behavior.tentative.html": [
+       "09f896942ba5fec4c8970b31bcf0a38d22e7c2fc",
+       [
+        null,
+        {
+         "testdriver": true
+        }
+       ]
+      ],
       "invoketarget-on-details-behavior.tentative.html": [
        "06215f829d95753ff40e37665ba07a652c4afc60",
        [
@@ -578005,7 +578109,7 @@
      ]
     ],
     "longtask-in-childiframe-crossorigin.html": [
-     "b8607f90dd6363b5034cded2cf5ca2d357e2bd1b",
+     "03f3dbf337d357da8c862aa9d150e91992623d31",
      [
       null,
       {}
@@ -578040,7 +578144,7 @@
      ]
     ],
     "longtask-in-sibling-iframe-crossorigin.html": [
-     "d66fe0c63ba363333c7f1cdc3b75712cddf7de84",
+     "25f1918f14df9a63e25eed8476a7f641055cf253",
      [
       null,
       {}
@@ -584258,6 +584362,106 @@
       ]
      ]
     },
+    "navigation-activation": {
+     "activation-after-bfcache-cross-origin.html": [
+      "3a0b8804b4091ac48e4f06ed11be7479f001c1e1",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-after-bfcache.html": [
+      "4c246e9d624a0be06d5549685c81f8754fc13a29",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-history-pushState.html": [
+      "bcc56136f7e2e8352f0c152442ab027e0bb3105c",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-history-replaceState.html": [
+      "70dc7b8eedee59e40a53155750b6ddd70e7faffa",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-initial-about-blank.html": [
+      "402093809ca653393fefaa65cfece2289bebe524",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-push-cross-origin.html": [
+      "15651bf78aac90b6d8770174eb347779f286450e",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-push.html": [
+      "99548314c4606044eaa9530c9c76848488e6a500",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-reload.html": [
+      "f65afc74bc1458d27f5363d01a8093d0632636cf",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-replace-cross-origin.html": [
+      "a835b7f4c52a29a6fcc3c79c1344ece9d919b7de",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-replace.html": [
+      "71624fd7cece6156d023a4f21fceed288f492ada",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-same-document-then-cross-document.html": [
+      "3daa4de66ee3aa069c08ae682290b52d6a519714",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-traverse-not-in-entries.html": [
+      "c8386615a24f6ce5f50b7a60102559efb55003ab",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-traverse-then-clobber.html": [
+      "c02837624098d9e4b5bcfba5e67704ffb4c765f8",
+      [
+       null,
+       {}
+      ]
+     ],
+     "activation-traverse.html": [
+      "218fe8626910a888a31b080fa4f3cc77b9953d4d",
+      [
+       null,
+       {}
+      ]
+     ]
+    },
     "navigation-history-entry": {
      "after-detach.html": [
       "c4ecfec44d69eaf7183691e69a1d21dd544d8ff7",
@@ -584428,21 +584632,21 @@
       ]
      ],
      "no-referrer-dynamic-url-censored.html": [
-      "7a5544c4196be057e372f523c77e293de70c6292",
+      "f16f82822059229b7ee8c22d467707b4a554596d",
       [
        null,
        {}
       ]
      ],
      "no-referrer-from-meta-url-censored.html": [
-      "fc563f509e79c8bcc98487bcde12d3068cc3d456",
+      "6e759d595d240f2851ea25252c93c213ea0f48a3",
       [
        null,
        {}
       ]
      ],
      "no-referrer-url-censored.html": [
-      "e7eb1afc7d1d2d80df8131bcc449187093f0deb2",
+      "e88d4453db3edaec5e9f3ac9437ab9ff399f2357",
       [
        null,
        {}
@@ -620634,7 +620838,7 @@
      ]
     ],
     "requestStorageAccess-dedicated-worker.tentative.sub.https.window.js": [
-     "86caf8191828712fc02733a55c87d54022c97d8c",
+     "f2d766575db00ca877570bc31e91810b978af7cd",
      [
       "storage-access-api/requestStorageAccess-dedicated-worker.tentative.sub.https.window.html",
       {
@@ -641639,7 +641843,7 @@
      ]
     ],
     "partitioned-web-locks.tentative.https.html": [
-     "680474dea9838e643d612711bb405a2faf0c07fd",
+     "aa9c9b6984253b16a5fae5c2d06271d2a4374fee",
      [
       null,
       {}
@@ -675982,7 +676186,7 @@
      ]
     ],
     "responsexml-document-properties.htm": [
-     "a9f14f8212a412eca94c694baba1bdeb112282e1",
+     "1d2811bec7dab88aa4408f6bd4e1ffe0e384afd1",
      [
       null,
       {}
@@ -690467,7 +690671,7 @@
          ]
         ],
         "clip.py": [
-         "5d2385ed4a187c25d33a1b39dc5c4e43262350d1",
+         "740ee531906cb7ca9a01626f6369712200238d0e",
          [
           null,
           {}
@@ -690481,7 +690685,7 @@
          ]
         ],
         "invalid.py": [
-         "a0c0acc5b4d61677f33fc26b423a79f81d71a4a3",
+         "9eb459afb5d4295f39938c92915f75caf8ef210a",
          [
           null,
           {}
@@ -690872,7 +691076,7 @@
       "input": {
        "perform_actions": {
         "invalid.py": [
-         "0269a1bc8f32a06bade66795fe61ba77aa85cbcf",
+         "631b3026c1771c5f6d7aa45ee7271bd2cdc56975",
          [
           null,
           {
@@ -690948,14 +691152,14 @@
          ]
         ],
         "pointer_pen.py": [
-         "04fb24edccd3f33b4a22bd0fb0daf3af451a560a",
+         "5cdacbbb489ac35cae842f9b0307405779eec8d6",
          [
           null,
           {}
          ]
         ],
         "pointer_touch.py": [
-         "c1c430765f7dfded519931c0fabd290886608b48",
+         "3b91b93487929be0df2d66e80e6b5c8be42470d0",
          [
           null,
           {}
@@ -691084,7 +691288,7 @@
          ]
         ],
         "url_patterns.py": [
-         "c16993d1ec3f14d8716e6ec3a099c1a7477febdf",
+         "be44709d7f5ecf9ab97ffb2a83ab8921818ff939",
          [
           null,
           {}
@@ -692903,7 +693107,7 @@
         ]
        ],
        "pointer_pen.py": [
-        "fcd1aba9474eb44e066dde3e755058a939d1d87f",
+        "b846f7e7ed59350cbb72f7faa3746cc7742d4664",
         [
          null,
          {
@@ -692912,7 +693116,7 @@
         ]
        ],
        "pointer_touch.py": [
-        "6c8e2f3fa6e2a9cb909ba8a0865d9f3d720003d4",
+        "ab49f1eed6d117a1b913e47763d6bf348429e6d8",
         [
          null,
          {
diff --git a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-login-status/confirm-idp-login.https.html b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-login-status/confirm-idp-login.https.html
index 54126c4..0f8df72 100644
--- a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-login-status/confirm-idp-login.https.html
+++ b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-login-status/confirm-idp-login.https.html
@@ -28,7 +28,7 @@
   // just the accounts endpoint.
   // (This is not technically spec-compliant)
   await select_manifest(t, test_options);
-  await window.test_driver.confirm_idp_login();
+  await window.test_driver.click_fedcm_dialog_button("ConfirmIdpLoginContinue");
 
   // Now wait for the account chooser.
   type = await fedcm_get_dialog_type_promise(t);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/position-fallback-container-query.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/position-fallback-container-query.html
new file mode 100644
index 0000000..b4ef806
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/position-fallback-container-query.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<title>@position-fallback with container query responding to fallback widths</title>
+<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#fallback">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+  #relative {
+    background: maroon;
+    position: relative;
+    width: 195px;
+    height: 200px;
+  }
+  #target1 {
+    container-type: inline-size;
+    container-name: target1;
+    position-fallback: --fallback1;
+    background: green;
+    position: absolute;
+    top: 0px;
+    left: 100px;
+    width: 100px;
+    height: 100px;
+  }
+  @position-fallback --fallback1 {
+    @try {
+      top: 100px;
+      left: 0px;
+      width: 150px;
+    }
+  }
+  @container (width > 100px) {
+    #inner1 {
+      background-color: lime;
+      width: 100px;
+      height: 100px;
+    }
+  }
+
+  #target2 {
+    container-type: inline-size;
+    container-name: target2;
+    position-fallback: --fallback2;
+    background: orange;
+    position: absolute;
+    top: 0px;
+    left: 100px;
+    width: 100px;
+  }
+  @position-fallback --fallback2 {
+    @try {
+      top: 100px;
+      left: 0px;
+      width: 150px;
+    }
+    @try {
+      top: 0px;
+      left: 0px;
+      width: 150px;
+    }
+  }
+  @container target2 (width = 150px) {
+    #inner2 {
+      background-color: yellow;
+      width: 100px;
+      height: 150px;
+    }
+  }
+</style>
+<div id="relative">
+  <div id="target1">
+    <div id="inner1"></div>
+  </div>
+  <div id="target2">
+    <div id="inner2"></div>
+  </div>
+</div>
+<script>
+  test(() => {
+    assert_equals(getComputedStyle(inner1).backgroundColor, "rgb(0, 255, 0)");
+    assert_equals(getComputedStyle(inner1).width, "100px");
+    assert_equals(getComputedStyle(inner1).height, "100px");
+    assert_equals(getComputedStyle(target1).top, "100px");
+    assert_equals(getComputedStyle(target1).left, "0px");
+    assert_equals(getComputedStyle(target1).width, "150px");
+  }, "Size container query responds to fallback width");
+
+  test(() => {
+    assert_equals(getComputedStyle(inner2).backgroundColor, "rgb(255, 255, 0)");
+    assert_equals(getComputedStyle(inner2).width, "100px");
+    assert_equals(getComputedStyle(inner2).height, "150px");
+    assert_equals(getComputedStyle(target2).top, "0px");
+    assert_equals(getComputedStyle(target2).left, "0px");
+    assert_equals(getComputedStyle(target2).width, "150px");
+  }, "Size container query responds to fallback width and applies height to not fit the first fallback");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/position-fallback-pseudo-element.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/position-fallback-pseudo-element.html
new file mode 100644
index 0000000..e2f95b9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/position-fallback-pseudo-element.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>@position-fallback for ::before and ::after pseudo elements</title>
+<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#fallback">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+  #container {
+    background: maroon;
+    position: relative;
+    width: 195px;
+    height: 200px;
+  }
+  #target::before {
+    position-fallback: --fallback;
+    background: lime;
+    position: absolute;
+    left: 200px;
+    top: 200px;
+    width: 100px;
+    height: 200px;
+    content: "";
+  }
+  #target::after {
+    position-fallback: --fallback;
+    background: green;
+    position: absolute;
+    left: 100px;
+    width: 100px;
+    height: 100px;
+    content: "";
+  }
+  @position-fallback --fallback {
+    @try {
+      top: 100px;
+      left: 50px;
+    }
+    @try {
+      top: 0px;
+      left: 0px;
+    }
+  }
+</style>
+<div id="container">
+  <div id="target"></div>
+</div>
+<script>
+  test(() => {
+    const before_style = getComputedStyle(target, "::before");
+    assert_equals(before_style.top, "0px");
+    assert_equals(before_style.left, "0px");
+  }, "::before using second fallback");
+  test(() => {
+    const after_style = getComputedStyle(target, "::after");
+    assert_equals(after_style.top, "100px");
+    assert_equals(after_style.left, "50px");
+  }, "::after using first fallback");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/outline-auto-width-001.html b/third_party/blink/web_tests/external/wpt/css/css-ui/outline-auto-width-001.html
new file mode 100644
index 0000000..fc7dc170
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/outline-auto-width-001.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<html lang=en>
+<meta charset=utf-8>
+<title>CSS-UI test: Outline width and auto style</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<meta name=flags content="">
+<meta name=assert content="outline-width is ignored when outline-style is auto">
+<link rel=help href="https://drafts.csswg.org/css-ui-4/#outline-style">
+<link rel="match" href="reference/outline-auto-with-001-ref.html">
+<style>
+div {
+    outline-style: auto;
+    outline-width: 100px;
+    width: 100px;
+    height: 100px;
+    margin: 1em;
+}
+div + div {
+    outline-width: 0;
+}
+</style>
+
+<p>Test passes if there are two identical box frames below.
+
+<div></div>
+<div></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/reference/outline-auto-with-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-ui/reference/outline-auto-with-001-ref.html
new file mode 100644
index 0000000..9ae9e60
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/reference/outline-auto-with-001-ref.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<html lang=en>
+<meta charset=utf-8>
+<title>CSS-UI test reference</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<style>
+div {
+    outline-style: auto;
+    width: 100px;
+    height: 100px;
+    margin: 1em;
+}
+</style>
+
+<p>Test passes if there are two identical box frames below.
+
+<div></div>
+<div></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/block-with-overflowing-text-ref.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/block-with-overflowing-text-ref.html
new file mode 100644
index 0000000..8d9c430f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/block-with-overflowing-text-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: block with overflowing text is rendered correctly (ref)</title>
+<link rel="help" href="https://drafts.csswg.org/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<style>
+#target {
+  text-shadow: red -20px -50px;
+  position: relative;
+  top: 100px;
+  left: 100px;
+}
+
+body {
+  background: pink;
+}
+</style>
+
+<div id="target">This text should render correctly</div>
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/block-with-overflowing-text.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/block-with-overflowing-text.html
new file mode 100644
index 0000000..b3f8f42
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/block-with-overflowing-text.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: block with overflowing text is rendered correctly</title>
+<link rel="help" href="https://drafts.csswg.org/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="block-with-overflowing-text-ref.html">
+<meta name="fuzzy" content="block-with-overflowing-text-ref.html:maxDifference=0-2;totalPixels=0-1200">
+
+
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/rendering-utils.js"></script>
+<style>
+#target {
+  text-shadow: red -20px -50px;
+  position: relative;
+  top: 100px;
+  left: 100px;
+  view-transition-name: target;
+}
+
+.hidden {
+  view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+html::view-transition-group(root) { visibility: hidden; }
+
+html::view-transition-group(target) {
+  animation: unset;
+}
+
+html::view-transition-old(target) {
+  animation: unset;
+  opacity: 0;
+}
+
+html::view-transition-new(target) {
+  animation: unset;
+  opacity: 1;
+}
+
+html::view-transition {
+  background: pink;
+}
+</style>
+
+<div id="target">This text should render correctly</div>
+<div class="hidden"></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+  let transition = document.startViewTransition();
+  transition.ready.then(takeScreenshot);
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text-and-box-decorations-ref.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text-and-box-decorations-ref.html
new file mode 100644
index 0000000..e0a75e73
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text-and-box-decorations-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: span with overflowing text is rendered correctly (ref)</title>
+<link rel="help" href="https://drafts.csswg.org/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<style>
+span {
+  text-shadow: red -2px -5px;
+  border: 2px solid black;
+  box-shadow: 3px 3px red, -1em 0 .4em olive;
+}
+
+body {
+  background: pink;
+}
+</style>
+
+<span>This text should render correctly</span>
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text-and-box-decorations.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text-and-box-decorations.html
new file mode 100644
index 0000000..a2bf59ec
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text-and-box-decorations.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: span with overflowing text is rendered correctly</title>
+<link rel="help" href="https://drafts.csswg.org/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="span-with-overflowing-text-and-box-decorations-ref.html">
+<meta name="fuzzy" content="span-with-overflowing-text-and-box-decorations-ref.html:maxDifference=0-3;totalPixels=0-4900">
+
+
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/rendering-utils.js"></script>
+<style>
+span {
+  text-shadow: red -2px -5px;
+  border: 2px solid black;
+  box-shadow: 3px 3px red, -1em 0 .4em olive;
+  view-transition-name: target;
+}
+
+.hidden {
+  view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+html::view-transition-group(root) { visibility: hidden; }
+
+html::view-transition-group(target) {
+  animation: unset;
+}
+
+html::view-transition-old(target) {
+  animation: unset;
+  opacity: 0;
+}
+
+html::view-transition-new(target) {
+  animation: unset;
+  opacity: 1;
+}
+
+html::view-transition {
+  background: pink;
+}
+</style>
+
+<span>This text should render correctly</span>
+<div class="hidden"></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+  let transition = document.startViewTransition();
+  transition.ready.then(takeScreenshot);
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text-ref.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text-ref.html
index 76fc367..4ec4d4cc 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text-ref.html
@@ -6,7 +6,7 @@
 
 <style>
 span {
-  text-shadow: red 2px 5px;
+  text-shadow: red -2px -5px;
 }
 
 body {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text.html
index 4abee4e..f3f0f53 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/span-with-overflowing-text.html
@@ -4,14 +4,14 @@
 <link rel="help" href="https://drafts.csswg.org/css-view-transitions-1/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <link rel="match" href="span-with-overflowing-text-ref.html">
-<meta name="fuzzy" content="span-with-overflowing-text-ref.html:maxDifference=0-2;totalPixels=0-1100">
+<meta name="fuzzy" content="span-with-overflowing-text-ref.html:maxDifference=0-3;totalPixels=0-1100">
 
 
 <script src="/common/reftest-wait.js"></script>
 <script src="/common/rendering-utils.js"></script>
 <style>
 span {
-  text-shadow: red 2px 5px;
+  text-shadow: red -2px -5px;
   view-transition-name: target;
 }
 
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-load-event-002.html b/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-load-event-002.html
new file mode 100644
index 0000000..7978081
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/cssom/HTMLLinkElement-load-event-002.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Link element load event doesn't block the parser.</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://html.spec.whatwg.org/#link-type-stylesheet">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+  let NUM_LOADS = 0;
+
+  function sheetUrl(token) {
+    return "stylesheet-same-origin.css?" + token;
+  }
+
+  function createLink(token) {
+    let link = document.createElement("link");
+    link.rel = "stylesheet";
+    link.href = sheetUrl(token);
+    return link;
+  }
+
+  function waitForEnoughTimeToLoadSheet(token) {
+    return new Promise(resolve => {
+      let link = createLink(token);
+      link.onload = resolve;
+      document.head.appendChild(link);
+    });
+  }
+
+  promise_test(async function (t) {
+    let link = createLink("removed");
+    link.addEventListener("load", t.unreached_func("got unexpected load event"));
+    link.addEventListener("error", t.unreached_func("got unexpected error event"));
+    document.head.appendChild(link);
+    link.remove();
+
+    await waitForEnoughTimeToLoadSheet("removed-wait");
+  }, "Load event doesn't fire on removed link");
+
+  promise_test(async function (t) {
+    let link = createLink("changed-initial");
+    let sawLoad = false;
+    let load = new Promise(resolve => {
+      link.addEventListener("load", function(e) {
+        assert_false(sawLoad, "Should only see load event once");
+        sawLoad = true;
+        resolve();
+      });
+    });
+    link.addEventListener("error", t.unreached_func("got unexpected error event"));
+    document.head.appendChild(link);
+    link.href = sheetUrl("changed-change");
+
+    await waitForEnoughTimeToLoadSheet("changed-wait");
+    await load;
+
+    assert_true(sawLoad, "Should've seen the load event only once");
+  }, "Load event doesn't fire for removed sheet");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/zoom/tentative/background-image-ref.html b/third_party/blink/web_tests/external/wpt/css/zoom/tentative/background-image-ref.html
new file mode 100644
index 0000000..6fe548f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/zoom/tentative/background-image-ref.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<style>
+div {
+  width: 10px;
+  height: 10px;
+  background-image: image-set(url("/images/pattern.png") 2x);
+}
+</style>
+<div></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/zoom/tentative/background-image.html b/third_party/blink/web_tests/external/wpt/css/zoom/tentative/background-image.html
new file mode 100644
index 0000000..db6baa6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/zoom/tentative/background-image.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>Zoom affects background-image intrinsic sizes</title>
+<link rel="match" href="background-image-ref.html">
+<style>
+div {
+  width: 20px;
+  height: 20px;
+  zoom: 0.5;
+  background-image: url("/images/pattern.png"); /* 20x20 */
+}
+</style>
+<div></div>
diff --git a/third_party/blink/web_tests/external/wpt/docs/writing-tests/testdriver.md b/third_party/blink/web_tests/external/wpt/docs/writing-tests/testdriver.md
index 14eb3dc7..73af3bb 100644
--- a/third_party/blink/web_tests/external/wpt/docs/writing-tests/testdriver.md
+++ b/third_party/blink/web_tests/external/wpt/docs/writing-tests/testdriver.md
@@ -102,7 +102,7 @@
 ### Federated Credential Management ###
 ```eval_rst
 .. js:autofunction:: test_driver.cancel_fedcm_dialog
-.. js:autofunction:: test_driver.confirm_idp_login
+.. js:autofunction:: test_driver.click_fedcm_dialog_button
 .. js:autofunction:: test_driver.select_fedcm_account
 .. js:autofunction:: test_driver.get_fedcm_account_list
 .. js:autofunction:: test_driver.get_fedcm_dialog_title
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-focusability.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-focusability.html
new file mode 100644
index 0000000..afd02c7d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-focusability.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>dialog element: focusability</title>
+<link rel=help href="https://github.com/whatwg/html/pull/8199">
+<link rel=author href="mailto:masonf@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+
+<button id="before">before</button>
+<dialog id="dialog" open>
+  <button id="within">button</button>
+</dialog>
+<button id="after">after</button>
+
+<script>
+  function navigateForward() {
+    const TAB = '\ue004';
+    return test_driver.send_keys(document.body, TAB);
+  }
+  async function assert_focus_order(elements) {
+    assert_true(elements.length >= 2);
+    elements[0].focus();
+    for(let i=0;i<elements.length;++i) {
+      assert_equals(document.activeElement,elements[i],`Focus order mismatch at step ${i+1}/${elements.length}`);
+      await navigateForward();
+    }
+  }
+
+  async_test((t) => {
+    window.onload = async () => {
+      await assert_focus_order([before,within,after]);
+      t.done();
+    };
+  }, "The dialog element itself should not be keyboard focusable.");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js
index 19f0c2e..f67038e 100644
--- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js
+++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js
@@ -401,6 +401,10 @@
   var pointerId = pointerType + "Pointer1";
   return new test_driver.Actions()
     .addPointer(pointerId, pointerType)
+    // WebDriver initializes the pointer position (0, 0), therefore, we need
+    // to move different position first.  Otherwise, moving to (0, 0) may be
+    // ignored.
+    .pointerMove(1, 1)
     .pointerMove(0, 0)
     .send();
 }
diff --git a/third_party/blink/web_tests/external/wpt/resources/testdriver.js b/third_party/blink/web_tests/external/wpt/resources/testdriver.js
index 0327e17..ddf723cb 100644
--- a/third_party/blink/web_tests/external/wpt/resources/testdriver.js
+++ b/third_party/blink/web_tests/external/wpt/resources/testdriver.js
@@ -699,21 +699,22 @@
         },
 
         /**
-         * Accepts a FedCM "Confirm IDP login" dialog.
+         * Clicks a button on the Federated Credential Management dialog
          *
-         * Matches the `Confirm IDP Login
-         * <https://fedidcg.github.io/FedCM/#webdriver-confirmidplogin>`_
+         * Matches the `Click dialog button
+         * <https://fedidcg.github.io/FedCM/#webdriver-clickdialogbutton>`_
          * WebDriver command.
          *
+         * @param {String} dialog_button - String enum representing the dialog button to click.
          * @param {WindowProxy} context - Browsing context in which
          *                                to run the call, or null for the current
          *                                browsing context.
          *
-         * @returns {Promise} Fulfilled after the IDP login has started,
+         * @returns {Promise} Fulfilled after the button is clicked,
          *                    or rejected in case the WebDriver command errors
          */
-        confirm_idp_login: function(context=null) {
-          return window.test_driver_internal.confirm_idp_login(context);
+        click_fedcm_dialog_button: function(dialog_button, context=null) {
+          return window.test_driver_internal.click_fedcm_dialog_button(dialog_button, context);
         },
 
         /**
@@ -1097,8 +1098,8 @@
             throw new Error("cancel_fedcm_dialog() is not implemented by testdriver-vendor.js");
         },
 
-        async confirm_idp_login(context=null) {
-            throw new Error("confirm_idp_login() is not implemented by testdriver-vendor.js");
+        async click_fedcm_dialog_button(dialog_button, context=null) {
+            throw new Error("click_fedcm_dialog_button() is not implemented by testdriver-vendor.js");
         },
 
         async select_fedcm_account(account_index, context=null) {
diff --git a/third_party/blink/web_tests/external/wpt/urlpattern/resources/urlpatterntestdata.json b/third_party/blink/web_tests/external/wpt/urlpattern/resources/urlpatterntestdata.json
index 4a05e4c..058079b 100644
--- a/third_party/blink/web_tests/external/wpt/urlpattern/resources/urlpatterntestdata.json
+++ b/third_party/blink/web_tests/external/wpt/urlpattern/resources/urlpatterntestdata.json
@@ -2829,5 +2829,29 @@
       "search": { "input": "q=*&v=?&hmm={}&umm=()", "groups": {} },
       "hash": { "input": "foo", "groups": {} }
     }
+  },
+  {
+    "pattern": [{ "pathname": "/([[a-z]--a])" }],
+    "inputs": [{ "pathname": "/a" }],
+    "expected_match": null
+  },
+  {
+    "pattern": [{ "pathname": "/([[a-z]--a])" }],
+    "inputs": [{ "pathname": "/z" }],
+    "expected_match": {
+      "pathname": { "input": "/z", "groups": { "0": "z" } }
+    }
+  },
+    {
+    "pattern": [{ "pathname": "/([\\d&&[0-1]])" }],
+    "inputs": [{ "pathname": "/0" }],
+    "expected_match": {
+      "pathname": { "input": "/0", "groups": { "0": "0" } }
+    }
+  },
+  {
+    "pattern": [{ "pathname": "/([\\d&&[0-1]])" }],
+    "inputs": [{ "pathname": "/3" }],
+    "expected_match": null
   }
 ]
diff --git a/third_party/blink/web_tests/external/wpt/web-locks/partitioned-web-locks.tentative.https.html b/third_party/blink/web_tests/external/wpt/web-locks/partitioned-web-locks.tentative.https.html
index 680474d..aa9c9b6 100644
--- a/third_party/blink/web_tests/external/wpt/web-locks/partitioned-web-locks.tentative.https.html
+++ b/third_party/blink/web_tests/external/wpt/web-locks/partitioned-web-locks.tentative.https.html
@@ -41,18 +41,17 @@
     HTTPS_NOTSAMESITE_ORIGIN + self.location.pathname);
 
   // Step 1.
-  navigator.locks.request('testLock', {mode: 'exclusive', ifAvailable: true},
+  let lock_id = next_lock_id++;
+  let [ promise, release ] = makePromiseAndResolveFunc();
+  let released = navigator.locks.request('testLock', {mode: 'exclusive', ifAvailable: true},
         lock => {
           if (lock === null) {
             assert_true(false)
             return;
           }
-          let lock_id = next_lock_id++;
-          let release;
-          const promise = new Promise(r => { release = r; });
-          held.set(lock_id, release);
           return promise;
         });
+  held.set(lock_id, { release, released });
 
   // Step 2.
   const w = window.open(target_url);
@@ -60,10 +59,14 @@
 
   // Step 7.
   t.add_cleanup(() => {
-    w.close()
+    w.close();
+    let released = [];
     for(let i = 1; i < next_lock_id; i++){
-      held.get(i)();
+      let h = held.get(i);
+      h.release();
+      released.push(h.released);
     }
+    return Promise.allSettled(released);
   });
 
   // Step 8.
@@ -124,19 +127,17 @@
 
   // Nested Step 1.
   // Request the weblock for the top-level site.
-  navigator.locks.request('testLock', {mode: 'exclusive', ifAvailable: true},
+  let lock_id = next_lock_id_2++;
+  let [ promise, release ] = makePromiseAndResolveFunc();
+  let released = navigator.locks.request('testLock', {mode: 'exclusive', ifAvailable: true},
         lock => {
           if (lock === null) {
             assert_true(false)
             return;
           }
-          // Obtain and store the release functions for clean-up.
-          let lock_id = next_lock_id_2++;
-          let release;
-          const promise = new Promise(r => { release = r; });
-          held_2.set(lock_id, release);
           return promise;
         }).catch(error => alert(error.message));
+  held_2.set(lock_id, { release, released });
 
   // Nested Step 2.
   // Open the nested iframes. The script in the innermost child iframe
@@ -146,10 +147,14 @@
 
   // Nested Step 10.
   t.add_cleanup(() => {
-    w.close()
-    for(let i = 1; i < next_lock_id_2; i++){
-      held_2.get(i)();
+    w.close();
+    let released = [];
+    for(let i = 1; i < next_lock_id; i++){
+      let h = held_2.get(i);
+      h.release();
+      released.push(h.released);
     }
+    return Promise.allSettled(released);
   });
 
   // Nested Step 11.
diff --git a/third_party/blink/web_tests/external/wpt/web-locks/resources/helpers.js b/third_party/blink/web_tests/external/wpt/web-locks/resources/helpers.js
index 4b3311ee..3fb8971 100644
--- a/third_party/blink/web_tests/external/wpt/web-locks/resources/helpers.js
+++ b/third_party/blink/web_tests/external/wpt/web-locks/resources/helpers.js
@@ -69,9 +69,17 @@
    * @returns
    */
   self.requestLockAndHold = (t, name, options = {}) => {
-    return navigator.locks.request(name, options, () => {
-      return new Promise(resolve => t.add_cleanup(resolve));
+    let [promise, resolve] = self.makePromiseAndResolveFunc();
+    const released = navigator.locks.request(name, options, () => promise);
+    // Add a cleanup function that releases the lock by resolving the promise,
+    // and then waits until the lock is really released, to avoid contaminating
+    // following tests with temporarily held locks.
+    t.add_cleanup(() => {
+      resolve();
+      // Cleanup shouldn't fail if the request is aborted.
+      return released.catch(() => undefined);
     });
+    return released;
   };
 
   self.makePromiseAndResolveFunc = () => {
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/capture_screenshot/clip.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/capture_screenshot/clip.py
index 5d2385ed..740ee53 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/capture_screenshot/clip.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/capture_screenshot/clip.py
@@ -66,51 +66,6 @@
     assert comparison.equal()
 
 
-async def test_clip_element_with_scroll_into_view(
-    bidi_session, top_context, inline, compare_png_bidi
-):
-    element_styles = "background-color: black; width: 50px; height:50px;"
-
-    # Render an element inside of viewport for the reference.
-    reference_data = await get_reference_screenshot(
-        bidi_session,
-        inline,
-        top_context["context"],
-        f"""<div style="{element_styles}"></div>""",
-    )
-
-    viewport_dimensions = await get_viewport_dimensions(bidi_session, top_context)
-
-    # Render the same element outside of viewport.
-    url = inline(
-        f"""<div style="{element_styles} margin-top: {viewport_dimensions["height"]}px"></div>"""
-    )
-    await bidi_session.browsing_context.navigate(
-        context=top_context["context"], url=url, wait="complete"
-    )
-    element = await bidi_session.script.evaluate(
-        await_promise=False,
-        expression="document.querySelector('div')",
-        target=ContextTarget(top_context["context"]),
-    )
-    expected_size = await get_physical_element_dimensions(
-        bidi_session, top_context, element
-    )
-
-    assert await get_page_y_offset(bidi_session, top_context) == 0
-
-    data = await bidi_session.browsing_context.capture_screenshot(
-        context=top_context["context"],
-        clip=ElementOptions(element=element, scroll_into_view=True),
-    )
-
-    assert png_dimensions(data) == expected_size
-    assert await get_page_y_offset(bidi_session, top_context) >= 0
-
-    comparison = await compare_png_bidi(reference_data, data)
-    assert comparison.equal()
-
-
 async def test_clip_viewport(bidi_session, top_context, inline, compare_png_bidi):
     url = inline("<input>")
     await bidi_session.browsing_context.navigate(
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/capture_screenshot/invalid.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/capture_screenshot/invalid.py
index a0c0acc..9eb459a 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/capture_screenshot/invalid.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/capture_screenshot/invalid.py
@@ -82,17 +82,6 @@
         )
 
 
-@pytest.mark.parametrize("value", [42, "foo", {}, []])
-async def test_params_clip_element_scroll_into_view_invalid_type(
-    bidi_session, top_context, value
-):
-    with pytest.raises(error.InvalidArgumentException):
-        await bidi_session.browsing_context.capture_screenshot(
-            context=top_context["context"],
-            clip=ElementOptions(element={}, scroll_into_view=value),
-        )
-
-
 @pytest.mark.parametrize("value", [None, False, "foo", {}, []])
 async def test_params_clip_viewport_x_invalid_type(bidi_session, top_context, value):
     with pytest.raises(error.InvalidArgumentException):
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/invalid.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/invalid.py
index 0269a1b..631b302 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/invalid.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/invalid.py
@@ -48,8 +48,8 @@
         "pressure": 0.0,
         "tangentialPressure": 0.0,
         "twist": 0,
-        "tiltX": 0,
-        "tiltY": 0,
+        "altitudeAngle": 0,
+        "azimuthAngle": 0,
     }
 
     if pointer_action == "pointerMove":
@@ -574,42 +574,6 @@
         await perform_actions([{"type": "pointer", "id": "foo", "actions": [action]}])
 
 
-@pytest.mark.parametrize("pointer_action", ["pointerDown", "pointerMove", "pointerUp"])
-@pytest.mark.parametrize("tilt", ["tiltX", "tiltY"])
-@pytest.mark.parametrize("value", [None, "foo", True, 0.1, [], {}])
-async def test_params_pointer_action_common_properties_tilt_invalid_type(
-    perform_actions, pointer_action, tilt, value
-):
-    action = create_pointer_action(
-        pointer_action,
-        {
-            "tiltX": value if tilt == "tiltX" else 0,
-            "tiltY": value if tilt == "tiltY" else 0,
-        },
-    )
-
-    with pytest.raises(InvalidArgumentException):
-        await perform_actions([{"type": "pointer", "id": "foo", "actions": [action]}])
-
-
-@pytest.mark.parametrize("pointer_action", ["pointerDown", "pointerMove", "pointerUp"])
-@pytest.mark.parametrize("tilt", ["tiltX", "tiltY"])
-@pytest.mark.parametrize("value", [-91, 91])
-async def test_params_pointer_action_common_properties_tilt_invalid_value(
-    perform_actions, pointer_action, tilt, value
-):
-    action = create_pointer_action(
-        pointer_action,
-        {
-            "tiltX": value if tilt == "tiltX" else 0,
-            "tiltY": value if tilt == "tiltY" else 0,
-        },
-    )
-
-    with pytest.raises(InvalidArgumentException):
-        await perform_actions([{"type": "pointer", "id": "foo", "actions": [action]}])
-
-
 @pytest.mark.parametrize("coordinate", ["x", "y"])
 @pytest.mark.parametrize("value", [None, "foo", True, 0.1, [], {}])
 async def test_params_wheel_action_scroll_coordinate_invalid_type(
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/pointer_pen.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/pointer_pen.py
index 04fb24ed..5cdacbbb 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/pointer_pen.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/pointer_pen.py
@@ -76,7 +76,7 @@
     (
         actions.add_pointer(pointer_type="pen")
         .pointer_move(x=0, y=0, origin=get_element_origin(pointerArea))
-        .pointer_down(button=0, pressure=0.36, tilt_x=-72, tilt_y=9, twist=86)
+        .pointer_down(button=0, pressure=0.36, altitude_angle=0.3, azimuth_angle=0.2419, twist=86)
         .pointer_move(x=10, y=10, origin=get_element_origin(pointerArea))
         .pointer_up(button=0)
         .pointer_move(x=80, y=50, origin=get_element_origin(pointerArea))
@@ -110,8 +110,8 @@
     assert round(events[3]["width"], 2) == 1
     assert round(events[3]["height"], 2) == 1
     assert round(events[3]["pressure"], 2) == 0.36
-    assert events[3]["tiltX"] == -72
-    assert events[3]["tiltY"] == 9
+    assert events[3]["tiltX"] == 72
+    assert events[3]["tiltY"] == 38
     assert events[3]["twist"] == 86
     assert events[6]["type"] == "pointermove"
     assert events[6]["pageX"] == pytest.approx(center["x"] + 10, abs=1.0)
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/pointer_touch.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/pointer_touch.py
index c1c4307..3b91b934 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/pointer_touch.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/input/perform_actions/pointer_touch.py
@@ -81,8 +81,6 @@
             width=23,
             height=31,
             pressure=0.78,
-            tilt_x=21,
-            tilt_y=-8,
             twist=355,
         )
         .pointer_move(
@@ -92,8 +90,6 @@
             width=39,
             height=35,
             pressure=0.91,
-            tilt_x=-19,
-            tilt_y=62,
             twist=345,
         )
         .pointer_up(button=0)
@@ -135,13 +131,9 @@
     assert round(events[3]["pressure"], 2) == 0.91
 
 
-async def test_touch_pointer_properties_tilt_twist(
+async def test_touch_pointer_properties_angle_twist(
     bidi_session, top_context, get_element, load_static_test_page
 ):
-    # This test only covers the tilt/twist properties which are
-    # more specific to pen-type pointers, but which the spec allows
-    # for generic touch pointers. Seperating this out gives better
-    # coverage of the basic properties in test_touch_pointer_properties
     await load_static_test_page(page="test_actions_pointer.html")
 
     pointerArea = await get_element("#pointerArea")
@@ -158,8 +150,8 @@
             width=23,
             height=31,
             pressure=0.78,
-            tilt_x=21,
-            tilt_y=-8,
+            altitude_angle=1.2,
+            azimuth_angle=6,
             twist=355,
         )
         .pointer_move(
@@ -169,8 +161,8 @@
             width=39,
             height=35,
             pressure=0.91,
-            tilt_x=-19,
-            tilt_y=62,
+            altitude_angle=0.5,
+            azimuth_angle=1.8,
             twist=345,
         )
         .pointer_up(button=0)
@@ -195,10 +187,10 @@
         "pointerleave",
     ] == event_types
     assert events[2]["type"] == "pointerdown"
-    assert events[2]["tiltX"] == 21
-    assert events[2]["tiltY"] == -8
+    assert events[2]["tiltX"] == 20
+    assert events[2]["tiltY"] == -6
     assert events[2]["twist"] == 355
     assert events[3]["type"] == "pointermove"
-    assert events[3]["tiltX"] == -19
-    assert events[3]["tiltY"] == 62
+    assert events[3]["tiltX"] == -23
+    assert events[3]["tiltY"] == 61
     assert events[3]["twist"] == 345
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/network/add_intercept/url_patterns.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/network/add_intercept/url_patterns.py
index c16993d..be44709 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/network/add_intercept/url_patterns.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/network/add_intercept/url_patterns.py
@@ -1,7 +1,6 @@
 import asyncio
 
 import pytest
-import pytest_asyncio
 
 from .. import assert_before_request_sent_event
 
@@ -59,18 +58,15 @@
 )
 async def test_pattern_patterns_matching(
     wait_for_event,
-    setup_network_test,
+    subscribe_events,
+    top_context,
     add_intercept,
     fetch,
     substitute_host,
     patterns,
     url_template,
 ):
-    await setup_network_test(
-        events=[
-            "network.beforeRequestSent",
-        ]
-    )
+    await subscribe_events(events=["network.beforeRequestSent"],  contexts=[top_context["context"]])
 
     for pattern in patterns:
         for key in pattern:
@@ -108,18 +104,15 @@
 )
 async def test_pattern_patterns_not_matching(
     wait_for_event,
-    setup_network_test,
+    subscribe_events,
+    top_context,
     add_intercept,
     fetch,
     substitute_host,
     pattern,
     url_template,
 ):
-    await setup_network_test(
-        events=[
-            "network.beforeRequestSent",
-        ]
-    )
+    await subscribe_events(events=["network.beforeRequestSent"],  contexts=[top_context["context"]])
 
     for key in pattern:
         pattern[key] = substitute_host(pattern[key])
@@ -160,18 +153,15 @@
 )
 async def test_string_patterns_matching(
     wait_for_event,
-    setup_network_test,
+    subscribe_events,
+    top_context,
     add_intercept,
     fetch,
     substitute_host,
     pattern,
     url_template,
 ):
-    await setup_network_test(
-        events=[
-            "network.beforeRequestSent",
-        ]
-    )
+    await subscribe_events(events=["network.beforeRequestSent"],  contexts=[top_context["context"]])
 
     intercept = await add_intercept(
         phases=["beforeRequestSent"],
@@ -204,18 +194,15 @@
 )
 async def test_string_patterns_not_matching(
     wait_for_event,
-    setup_network_test,
+    subscribe_events,
+    top_context,
     add_intercept,
     fetch,
     substitute_host,
     pattern,
     url_template,
 ):
-    await setup_network_test(
-        events=[
-            "network.beforeRequestSent",
-        ]
-    )
+    await subscribe_events(events=["network.beforeRequestSent"],  contexts=[top_context["context"]])
 
     await add_intercept(
         phases=["beforeRequestSent"],
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/classic/perform_actions/pointer_pen.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/classic/perform_actions/pointer_pen.py
index fcd1aba..b846f7e7 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/classic/perform_actions/pointer_pen.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/classic/perform_actions/pointer_pen.py
@@ -78,7 +78,7 @@
     pointerArea = session.find.css("#pointerArea", all=False)
     center = get_inview_center(pointerArea.rect, get_viewport_rect(session))
     pen_chain.pointer_move(0, 0, origin=pointerArea) \
-        .pointer_down(pressure=0.36, tilt_x=-72, tilt_y=9, twist=86) \
+        .pointer_down(pressure=0.36, altitude_angle=0.3, azimuth_angle=0.2419, twist=86) \
         .pointer_move(10, 10, origin=pointerArea) \
         .pointer_up() \
         .pointer_move(80, 50, origin=pointerArea) \
@@ -98,8 +98,8 @@
     assert round(events[3]["width"], 2) == 1
     assert round(events[3]["height"], 2) == 1
     assert round(events[3]["pressure"], 2) == 0.36
-    assert events[3]["tiltX"] == -72
-    assert events[3]["tiltY"] == 9
+    assert events[3]["tiltX"] == 72
+    assert events[3]["tiltY"] == 38
     assert events[3]["twist"] == 86
     assert events[6]["type"] == "pointermove"
     assert events[6]["pageX"] == pytest.approx(center["x"]+10, abs=1.0)
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/classic/perform_actions/pointer_touch.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/classic/perform_actions/pointer_touch.py
index 6c8e2f3..ab49f1e 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/classic/perform_actions/pointer_touch.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/classic/perform_actions/pointer_touch.py
@@ -73,8 +73,8 @@
     pointerArea = session.find.css("#pointerArea", all=False)
     center = get_inview_center(pointerArea.rect, get_viewport_rect(session))
     touch_chain.pointer_move(0, 0, origin=pointerArea) \
-        .pointer_down(width=23, height=31, pressure=0.78, tilt_x=21, tilt_y=-8, twist=355) \
-        .pointer_move(10, 10, origin=pointerArea, width=39, height=35, pressure=0.91, tilt_x=-19, tilt_y=62, twist=345) \
+        .pointer_down(width=23, height=31, pressure=0.78, twist=355) \
+        .pointer_move(10, 10, origin=pointerArea, width=39, height=35, pressure=0.91, twist=345) \
         .pointer_up() \
         .pointer_move(80, 50, origin=pointerArea) \
         .perform()
@@ -101,13 +101,31 @@
     assert round(events[3]["pressure"], 2) == 0.91
 
 
-def test_touch_pointer_properties_tilt_twist(session, test_actions_pointer_page, touch_chain):
-    # This test only covers the tilt/twist properties which are
-    # more specific to pen-type pointers, but which the spec allows
-    # for generic touch pointers. Seperating this out gives better
-    # coverage of the basic properties in test_touch_pointer_properties
+def test_touch_pointer_properties_angle_twist(session, test_actions_pointer_page, touch_chain):
     pointerArea = session.find.css("#pointerArea", all=False)
-    center = get_inview_center(pointerArea.rect, get_viewport_rect(session))
+    touch_chain.pointer_move(0, 0, origin=pointerArea) \
+        .pointer_down(width=23, height=31, pressure=0.78, altitude_angle=1.2, azimuth_angle=6, twist=355) \
+        .pointer_move(10, 10, origin=pointerArea, width=39, height=35, pressure=0.91, altitude_angle=0.5, azimuth_angle=1.8, twist=345) \
+        .pointer_up() \
+        .pointer_move(80, 50, origin=pointerArea) \
+        .perform()
+    events = get_events(session)
+    assert len(events) == 7
+    event_types = [e["type"] for e in events]
+    assert ["pointerover", "pointerenter", "pointerdown", "pointermove",
+            "pointerup", "pointerout", "pointerleave"] == event_types
+    assert events[2]["type"] == "pointerdown"
+    assert events[2]["tiltX"] == 20
+    assert events[2]["tiltY"] == -6
+    assert events[2]["twist"] == 355
+    assert events[3]["type"] == "pointermove"
+    assert events[3]["tiltX"] == -23
+    assert events[3]["tiltY"] == 61
+    assert events[3]["twist"] == 345
+
+
+def test_touch_pointer_properties_tilt_twist(session, test_actions_pointer_page, touch_chain):
+    pointerArea = session.find.css("#pointerArea", all=False)
     touch_chain.pointer_move(0, 0, origin=pointerArea) \
         .pointer_down(width=23, height=31, pressure=0.78, tilt_x=21, tilt_y=-8, twist=355) \
         .pointer_move(10, 10, origin=pointerArea, width=39, height=35, pressure=0.91, tilt_x=-19, tilt_y=62, twist=345) \
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/support/keys.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/support/keys.py
index 3794a42..4771f4d2 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/support/keys.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/support/keys.py
@@ -243,10 +243,10 @@
         )),
         ("EQUALS", OrderedDict(
             [
-                ("code", ""),
+                ("code", "NumpadEqual"),
                 ("ctrl", False),
                 ("key", "="),
-                ("location", 0),
+                ("location", 3),
                 ("meta", False),
                 ("shift", False),
                 ("value", u"\ue019")
@@ -606,7 +606,7 @@
         )),
         ("PAUSE", OrderedDict(
             [
-                ("code", ""),
+                ("code", "Pause"),
                 ("ctrl", False),
                 ("key", "Pause"),
                 ("location", 0),
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webdriver/tests/bidi/input/perform_actions/key_events-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webdriver/tests/bidi/input/perform_actions/key_events-expected.txt
index 405018f..5c2ad113 100644
--- a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webdriver/tests/bidi/input/perform_actions/key_events-expected.txt
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webdriver/tests/bidi/input/perform_actions/key_events-expected.txt
@@ -1,29 +1,29 @@
 This is a wdspec test.
-[FAIL] test_non_printable_key_sends_events[\ue00c-ESCAPE]
+[FAIL] test_non_printable_key_sends_events[\\ue00c-ESCAPE]
   webdriver.bidi.modules.script.ScriptEvaluateResultException: ReferenceError: allEvents is not defined
-[FAIL] test_non_printable_key_sends_events[\ue014-RIGHT]
+[FAIL] test_non_printable_key_sends_events[\\ue014-RIGHT]
   webdriver.bidi.modules.script.ScriptEvaluateResultException: ReferenceError: allEvents is not defined
-[PASS] test_key_modifier_key[\ue00a-ALT]
-[PASS] test_key_modifier_key[\ue009-CONTROL]
-[PASS] test_key_modifier_key[\ue03d-META]
-[PASS] test_key_modifier_key[\ue008-SHIFT]
-[PASS] test_key_modifier_key[\ue052-R_ALT]
-[PASS] test_key_modifier_key[\ue051-R_CONTROL]
-[PASS] test_key_modifier_key[\ue053-R_META]
-[PASS] test_key_modifier_key[\ue050-R_SHIFT]
+[PASS] test_key_modifier_key[\\ue00a-ALT]
+[PASS] test_key_modifier_key[\\ue009-CONTROL]
+[PASS] test_key_modifier_key[\\ue03d-META]
+[PASS] test_key_modifier_key[\\ue008-SHIFT]
+[PASS] test_key_modifier_key[\\ue052-R_ALT]
+[PASS] test_key_modifier_key[\\ue051-R_CONTROL]
+[PASS] test_key_modifier_key[\\ue053-R_META]
+[PASS] test_key_modifier_key[\\ue050-R_SHIFT]
 [PASS] test_key_printable_key[a-KeyA0]
 [PASS] test_key_printable_key[a-KeyA1]
 [PASS] test_key_printable_key["-Quote]
 [PASS] test_key_printable_key[,-Comma]
-[PASS] test_key_printable_key[\xe0-]
-[PASS] test_key_printable_key[\u0416-]
+[PASS] test_key_printable_key[\\xe0-]
+[PASS] test_key_printable_key[\\u0416-]
 [PASS] test_key_printable_key[@-Digit2]
-[PASS] test_key_printable_key[\u2603-]
-[PASS] test_key_printable_key[\uf6c2-]
+[PASS] test_key_printable_key[\\u2603-]
+[PASS] test_key_printable_key[\\uf6c2-]
 [FAIL] test_key_printable_sequence[True]
-  AssertionError: assert [{'code': '', 'key': '\uf6c2', 'type': 'keydown'}, {'code': '', 'key': '\uf6c2', 'type': 'keypress'}, {'code': '', 'key': '\uf6c2', 'type': 'keyup'}, {'code': 'KeyA', 'key': 'a', 'type': 'keydown'}, {'code': 'KeyA', 'key': 'a', 'type': 'keypress'}, {'code': 'KeyA', 'key': 'a', 'type': 'keyup'}, {'code': 'KeyB', 'key': 'b', 'type': 'keydown'}, {'code': 'KeyB', 'key': 'b', 'type': 'keypress'}, {'code': 'KeyB', 'key': 'b', 'type': 'keyup'}] == [{'code': 'KeyA', 'key': 'a', 'type': 'keydown'}, {'code': 'KeyA', 'key': 'a', 'type': 'keypress'}, {'code': 'KeyA', 'key': 'a', 'type': 'keyup'}, {'code': 'KeyB', 'key': 'b', 'type': 'keydown'}, {'code': 'KeyB', 'key': 'b', 'type': 'keypress'}, {'code': 'KeyB', 'key': 'b', 'type': 'keyup'}]
+  AssertionError: assert [{'code': '', 'key': '\\uf6c2', 'type': 'keydown'}, {'code': '', 'key': '\\uf6c2', 'type': 'keypress'}, {'code': '', 'key': '\\uf6c2', 'type': 'keyup'}, {'code': 'KeyA', 'key': 'a', 'type': 'keydown'}, {'code': 'KeyA', 'key': 'a', 'type': 'keypress'}, {'code': 'KeyA', 'key': 'a', 'type': 'keyup'}, {'code': 'KeyB', 'key': 'b', 'type': 'keydown'}, {'code': 'KeyB', 'key': 'b', 'type': 'keypress'}, {'code': 'KeyB', 'key': 'b', 'type': 'keyup'}] == [{'code': 'KeyA', 'key': 'a', 'type': 'keydown'}, {'code': 'KeyA', 'key': 'a', 'type': 'keypress'}, {'code': 'KeyA', 'key': 'a', 'type': 'keyup'}, {'code': 'KeyB', 'key': 'b', 'type': 'keydown'}, {'code': 'KeyB', 'key': 'b', 'type': 'keypress'}, {'code': 'KeyB', 'key': 'b', 'type': 'keyup'}]
 [FAIL] test_key_printable_sequence[False]
-  AssertionError: assert [{'code': '', 'key': '\uf6c2', 'type': 'keydown'}, {'code': '', 'key': '\uf6c2', 'type': 'keypress'}, {'code': '', 'key': '\uf6c2', 'type': 'keyup'}, {'code': 'KeyA', 'key': 'a', 'type': 'keydown'}, {'code': 'KeyA', 'key': 'a', 'type': 'keypress'}, {'code': 'KeyA', 'key': 'a', 'type': 'keyup'}, {'code': 'KeyB', 'key': 'b', 'type': 'keydown'}, {'code': 'KeyB', 'key': 'b', 'type': 'keypress'}, {'code': 'KeyB', 'key': 'b', 'type': 'keyup'}, {'code': 'KeyA', 'key': 'a', 'type': 'keydown'}, {'code': 'KeyA', 'key': 'a', 'type': 'keypress'}, {'code': 'KeyB', 'key': 'b', 'type': 'keydown'}, {'code': 'KeyB', 'key': 'b', 'type': 'keypress'}] == [{'code': 'KeyA', 'key': 'a', 'type': 'keydown'}, {'code': 'KeyA', 'key': 'a', 'type': 'keypress'}, {'code': 'KeyB', 'key': 'b', 'type': 'keydown'}, {'code': 'KeyB', 'key': 'b', 'type': 'keypress'}]
+  AssertionError: assert [{'code': '', 'key': '\\uf6c2', 'type': 'keydown'}, {'code': '', 'key': '\\uf6c2', 'type': 'keypress'}, {'code': '', 'key': '\\uf6c2', 'type': 'keyup'}, {'code': 'KeyA', 'key': 'a', 'type': 'keydown'}, {'code': 'KeyA', 'key': 'a', 'type': 'keypress'}, {'code': 'KeyA', 'key': 'a', 'type': 'keyup'}, {'code': 'KeyB', 'key': 'b', 'type': 'keydown'}, {'code': 'KeyB', 'key': 'b', 'type': 'keypress'}, {'code': 'KeyB', 'key': 'b', 'type': 'keyup'}, {'code': 'KeyA', 'key': 'a', 'type': 'keydown'}, {'code': 'KeyA', 'key': 'a', 'type': 'keypress'}, {'code': 'KeyB', 'key': 'b', 'type': 'keydown'}, {'code': 'KeyB', 'key': 'b', 'type': 'keypress'}] == [{'code': 'KeyA', 'key': 'a', 'type': 'keydown'}, {'code': 'KeyA', 'key': 'a', 'type': 'keypress'}, {'code': 'KeyB', 'key': 'b', 'type': 'keydown'}, {'code': 'KeyB', 'key': 'b', 'type': 'keypress'}]
 [PASS] test_key_special_key_sends_keydown[ADD-expected0]
 [PASS] test_key_special_key_sends_keydown[ALT-expected1]
 [PASS] test_key_special_key_sends_keydown[BACKSPACE-expected2]
@@ -36,7 +36,8 @@
 [PASS] test_key_special_key_sends_keydown[DOWN-expected9]
 [PASS] test_key_special_key_sends_keydown[END-expected10]
 [PASS] test_key_special_key_sends_keydown[ENTER-expected11]
-[PASS] test_key_special_key_sends_keydown[EQUALS-expected12]
+[FAIL] test_key_special_key_sends_keydown[EQUALS-expected12]
+  AssertionError: assert ({'code': '', 'ctrl': False, 'key': '=', 'location': 0, 'meta': False, 'shift': False} == {'code': 'NumpadEqual', 'ctrl': False, 'key': '=', 'location': 3, 'meta': False, 'shift': False}
 [PASS] test_key_special_key_sends_keydown[ESCAPE-expected13]
 [PASS] test_key_special_key_sends_keydown[F1-expected14]
 [PASS] test_key_special_key_sends_keydown[F10-expected15]
@@ -69,7 +70,8 @@
 [PASS] test_key_special_key_sends_keydown[NUMPAD9-expected42]
 [PASS] test_key_special_key_sends_keydown[PAGE_DOWN-expected43]
 [PASS] test_key_special_key_sends_keydown[PAGE_UP-expected44]
-[PASS] test_key_special_key_sends_keydown[PAUSE-expected45]
+[FAIL] test_key_special_key_sends_keydown[PAUSE-expected45]
+  AssertionError: assert ({'code': '', 'ctrl': False, 'key': 'Pause', 'location': 0, 'meta': False, 'shift': False} == {'code': 'Pause', 'ctrl': False, 'key': 'Pause', 'location': 0, 'meta': False, 'shift': False}
 [FAIL] test_key_special_key_sends_keydown[RETURN-expected46]
   AssertionError: assert ({'code': 'Enter', 'ctrl': False, 'key': '', 'location': 0, 'meta': False, 'shift': False} == {'code': 'Enter', 'ctrl': False, 'key': 'Enter', 'location': 0, 'meta': False, 'shift': False}
 [PASS] test_key_special_key_sends_keydown[RIGHT-expected47]
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webdriver/tests/classic/perform_actions/key_events-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webdriver/tests/classic/perform_actions/key_events-expected.txt
new file mode 100644
index 0000000..30d1472a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webdriver/tests/classic/perform_actions/key_events-expected.txt
@@ -0,0 +1,97 @@
+This is a wdspec test.
+[PASS] test_keyup_only_sends_no_events
+[PASS] test_modifier_key_sends_correct_events[\\ue00a-ALT]
+[PASS] test_modifier_key_sends_correct_events[\\ue009-CONTROL]
+[PASS] test_modifier_key_sends_correct_events[\\ue03d-META]
+[PASS] test_modifier_key_sends_correct_events[\\ue008-SHIFT]
+[PASS] test_modifier_key_sends_correct_events[\\ue052-R_ALT]
+[PASS] test_modifier_key_sends_correct_events[\\ue051-R_CONTROL]
+[PASS] test_modifier_key_sends_correct_events[\\ue053-R_META]
+[PASS] test_modifier_key_sends_correct_events[\\ue050-R_SHIFT]
+[PASS] test_non_printable_key_sends_events[\\ue00c-ESCAPE]
+[PASS] test_non_printable_key_sends_events[\\ue014-RIGHT]
+[PASS] test_printable_key_sends_correct_events[a-KeyA0]
+[PASS] test_printable_key_sends_correct_events[a-KeyA1]
+[PASS] test_printable_key_sends_correct_events["-Quote]
+[PASS] test_printable_key_sends_correct_events[,-Comma]
+[PASS] test_printable_key_sends_correct_events[\\xe0-]
+[PASS] test_printable_key_sends_correct_events[\\u0416-]
+[PASS] test_printable_key_sends_correct_events[@-Digit2]
+[PASS] test_printable_key_sends_correct_events[\\u2603-]
+[PASS] test_printable_key_sends_correct_events[\\uf6c2-]
+[PASS] test_sequence_of_keydown_printable_keys_sends_events
+[PASS] test_sequence_of_keydown_printable_characters_sends_events
+[PASS] test_special_key_sends_keydown[ADD-expected0]
+[PASS] test_special_key_sends_keydown[ALT-expected1]
+[PASS] test_special_key_sends_keydown[BACKSPACE-expected2]
+[PASS] test_special_key_sends_keydown[CANCEL-expected3]
+[PASS] test_special_key_sends_keydown[CLEAR-expected4]
+[PASS] test_special_key_sends_keydown[CONTROL-expected5]
+[PASS] test_special_key_sends_keydown[DECIMAL-expected6]
+[PASS] test_special_key_sends_keydown[DELETE-expected7]
+[PASS] test_special_key_sends_keydown[DIVIDE-expected8]
+[PASS] test_special_key_sends_keydown[DOWN-expected9]
+[PASS] test_special_key_sends_keydown[END-expected10]
+[PASS] test_special_key_sends_keydown[ENTER-expected11]
+[FAIL] test_special_key_sends_keydown[EQUALS-expected12]
+  AssertionError: assert ({'code': '', 'ctrl': False, 'key': '=', 'location': 0, 'meta': False, 'shift': False} == {'code': 'NumpadEqual', 'ctrl': False, 'key': '=', 'location': 3, 'meta': False, 'shift': False}
+[PASS] test_special_key_sends_keydown[ESCAPE-expected13]
+[PASS] test_special_key_sends_keydown[F1-expected14]
+[PASS] test_special_key_sends_keydown[F10-expected15]
+[PASS] test_special_key_sends_keydown[F11-expected16]
+[PASS] test_special_key_sends_keydown[F12-expected17]
+[PASS] test_special_key_sends_keydown[F2-expected18]
+[PASS] test_special_key_sends_keydown[F3-expected19]
+[PASS] test_special_key_sends_keydown[F4-expected20]
+[PASS] test_special_key_sends_keydown[F5-expected21]
+[PASS] test_special_key_sends_keydown[F6-expected22]
+[PASS] test_special_key_sends_keydown[F7-expected23]
+[PASS] test_special_key_sends_keydown[F8-expected24]
+[PASS] test_special_key_sends_keydown[F9-expected25]
+[PASS] test_special_key_sends_keydown[HELP-expected26]
+[PASS] test_special_key_sends_keydown[HOME-expected27]
+[PASS] test_special_key_sends_keydown[INSERT-expected28]
+[PASS] test_special_key_sends_keydown[LEFT-expected29]
+[PASS] test_special_key_sends_keydown[META-expected30]
+[PASS] test_special_key_sends_keydown[MULTIPLY-expected31]
+[PASS] test_special_key_sends_keydown[NULL-expected32]
+[PASS] test_special_key_sends_keydown[NUMPAD0-expected33]
+[PASS] test_special_key_sends_keydown[NUMPAD1-expected34]
+[PASS] test_special_key_sends_keydown[NUMPAD2-expected35]
+[PASS] test_special_key_sends_keydown[NUMPAD3-expected36]
+[PASS] test_special_key_sends_keydown[NUMPAD4-expected37]
+[PASS] test_special_key_sends_keydown[NUMPAD5-expected38]
+[PASS] test_special_key_sends_keydown[NUMPAD6-expected39]
+[PASS] test_special_key_sends_keydown[NUMPAD7-expected40]
+[PASS] test_special_key_sends_keydown[NUMPAD8-expected41]
+[PASS] test_special_key_sends_keydown[NUMPAD9-expected42]
+[PASS] test_special_key_sends_keydown[PAGE_DOWN-expected43]
+[PASS] test_special_key_sends_keydown[PAGE_UP-expected44]
+[FAIL] test_special_key_sends_keydown[PAUSE-expected45]
+  AssertionError: assert ({'code': '', 'ctrl': False, 'key': 'Pause', 'location': 0, 'meta': False, 'shift': False} == {'code': 'Pause', 'ctrl': False, 'key': 'Pause', 'location': 0, 'meta': False, 'shift': False}
+[PASS] test_special_key_sends_keydown[RETURN-expected46]
+[PASS] test_special_key_sends_keydown[RIGHT-expected47]
+[PASS] test_special_key_sends_keydown[R_ALT-expected48]
+[PASS] test_special_key_sends_keydown[R_ARROWDOWN-expected49]
+[PASS] test_special_key_sends_keydown[R_ARROWLEFT-expected50]
+[PASS] test_special_key_sends_keydown[R_ARROWRIGHT-expected51]
+[PASS] test_special_key_sends_keydown[R_ARROWUP-expected52]
+[PASS] test_special_key_sends_keydown[R_CONTROL-expected53]
+[PASS] test_special_key_sends_keydown[R_DELETE-expected54]
+[PASS] test_special_key_sends_keydown[R_END-expected55]
+[PASS] test_special_key_sends_keydown[R_HOME-expected56]
+[PASS] test_special_key_sends_keydown[R_INSERT-expected57]
+[PASS] test_special_key_sends_keydown[R_META-expected58]
+[PASS] test_special_key_sends_keydown[R_PAGEDOWN-expected59]
+[PASS] test_special_key_sends_keydown[R_PAGEUP-expected60]
+[PASS] test_special_key_sends_keydown[R_SHIFT-expected61]
+[PASS] test_special_key_sends_keydown[SEMICOLON-expected62]
+[PASS] test_special_key_sends_keydown[SEPARATOR-expected63]
+[PASS] test_special_key_sends_keydown[SHIFT-expected64]
+[PASS] test_special_key_sends_keydown[SPACE-expected65]
+[PASS] test_special_key_sends_keydown[SUBTRACT-expected66]
+[PASS] test_special_key_sends_keydown[TAB-expected67]
+[PASS] test_special_key_sends_keydown[UP-expected68]
+[PASS] test_special_key_sends_keydown[ZENKAKUHANKAKU-expected69]
+[PASS] test_space_char_equals_pua
+Harness: the test ran to completion.
diff --git a/third_party/catapult b/third_party/catapult
index 96c026e..84fb1a2 160000
--- a/third_party/catapult
+++ b/third_party/catapult
@@ -1 +1 @@
-Subproject commit 96c026ec93f9db606de6421c6ec970666f583581
+Subproject commit 84fb1a2dd0db549933ae487a763ce77d6bcb171a
diff --git a/third_party/chromium-variations b/third_party/chromium-variations
index 769b143..09c3574 160000
--- a/third_party/chromium-variations
+++ b/third_party/chromium-variations
@@ -1 +1 @@
-Subproject commit 769b143ec5dfc2af98d14e3fed7bd0f1df01927f
+Subproject commit 09c35745a7a4fd1be89f5f2988d8333925a97cb1
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal
index b8b21fe..108ae7c 160000
--- a/third_party/devtools-frontend-internal
+++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@
-Subproject commit b8b21fe11c921d47a352bad33425a50ea3c7df64
+Subproject commit 108ae7ce925d5b6a4691eee6f6e5bafe9e41b8bc
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index 921aae6f..fd66b84 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit 921aae6ff160beed8abea8959036b4f0ba1eed6a
+Subproject commit fd66b840a076b7c161543dc94828ee2ce0bcc4c1
diff --git a/third_party/libaom/BUILD.gn b/third_party/libaom/BUILD.gn
index 622da28..57433d0 100644
--- a/third_party/libaom/BUILD.gn
+++ b/third_party/libaom/BUILD.gn
@@ -95,12 +95,18 @@
   # via global function pointer symbols, which hides the object dependency at
   # link time. On Mac, this results in undefined references to the intrinsic
   # symbols.
+  # TODO(aomedia:3511): Re-enable this build flag
+  # //build/config/compiler:default_init_stack_vars is removed from all libaom
+  # targets. It introduces -ftrivial-auto-var-init=pattern compiler flag and
+  # causes a huge performance issue (over 13% slowdown for AV1 real-time
+  # encoder) with initializing local variables on the stack.
   source_set("libaom_intrinsics_sse2") {
     # TODO(jianj): Align this with libvpx as this is not used there.
     check_includes = false
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     configs += [ ":libaom_config" ]
+    configs -= [ "//build/config/compiler:default_init_stack_vars" ]
     if (!is_win || is_clang) {
       cflags = [ "-msse2" ]
     }
@@ -115,6 +121,7 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     configs += [ ":libaom_config" ]
+    configs -= [ "//build/config/compiler:default_init_stack_vars" ]
     if (!is_win || is_clang) {
       cflags = [ "-msse3" ]
     }
@@ -126,6 +133,7 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     configs += [ ":libaom_config" ]
+    configs -= [ "//build/config/compiler:default_init_stack_vars" ]
     if (!is_win || is_clang) {
       cflags = [ "-mssse3" ]
     }
@@ -140,6 +148,7 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     configs += [ ":libaom_config" ]
+    configs -= [ "//build/config/compiler:default_init_stack_vars" ]
     if (!is_win || is_clang) {
       cflags = [ "-msse4.1" ]
     }
@@ -154,6 +163,7 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     configs += [ ":libaom_config" ]
+    configs -= [ "//build/config/compiler:default_init_stack_vars" ]
     if (!is_win || is_clang) {
       cflags = [ "-msse4.2" ]
     }
@@ -165,6 +175,7 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     configs += [ ":libaom_config" ]
+    configs -= [ "//build/config/compiler:default_init_stack_vars" ]
     if (is_win) {
       cflags = [ "/arch:AVX" ]
     } else {
@@ -178,6 +189,7 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     configs += [ ":libaom_config" ]
+    configs -= [ "//build/config/compiler:default_init_stack_vars" ]
     if (is_win) {
       cflags = [ "/arch:AVX2" ]
     } else {
@@ -201,6 +213,7 @@
       cflags = [ "-mfpu=neon" ]
     }
     configs += [ ":libaom_config" ]
+    configs -= [ "//build/config/compiler:default_init_stack_vars" ]
 
     sources = aom_av1_common_intrin_neon
     sources += aom_dsp_common_intrin_neon
@@ -215,6 +228,7 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     configs += [ ":libaom_config" ]
+    configs -= [ "//build/config/compiler:default_init_stack_vars" ]
     if (!is_win || is_clang) {
       cflags = [ "-march=armv8-a+crc" ]
     }
@@ -226,6 +240,7 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     configs += [ ":libaom_config" ]
+    configs -= [ "//build/config/compiler:default_init_stack_vars" ]
     if (!is_win || is_clang) {
       cflags = [ "-march=armv8.2-a+dotprod" ]
     }
@@ -240,6 +255,7 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     configs += [ ":libaom_config" ]
+    configs -= [ "//build/config/compiler:default_init_stack_vars" ]
     if (!is_win || is_clang) {
       cflags = [ "-march=armv8.2-a+dotprod+i8mm" ]
     }
@@ -257,6 +273,7 @@
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [ "//build/config/compiler:no_chromium_code" ]
   configs += [ ":libaom_config" ]
+  configs -= [ "//build/config/compiler:default_init_stack_vars" ]
 
   sources = aom_av1_common_sources
   sources += aom_av1_decoder_sources
diff --git a/third_party/libvpx/generate_gni.sh b/third_party/libvpx/generate_gni.sh
index be1f486..dbeedaae 100755
--- a/third_party/libvpx/generate_gni.sh
+++ b/third_party/libvpx/generate_gni.sh
@@ -370,6 +370,9 @@
 EOF
 }
 
+# Fetch the latest tags; used in creating vpx_version.h.
+git -C "${LIBVPX_SRC_DIR}" fetch --tags
+
 find_duplicates
 
 echo "Create temporary directory."
@@ -594,10 +597,9 @@
 cd $BASE_DIR
 rm -rf $TEMP_DIR
 
-gn format --in-place $BASE_DIR/BUILD.gn
-gn format --in-place $BASE_DIR/libvpx_srcs.gni
-
 cd $BASE_DIR/$LIBVPX_SRC_DIR
 update_readme
 
 cd $BASE_DIR
+git cl format > /dev/null \
+  || echo "ERROR: 'git cl format' failed. Please run 'git cl format' manually."
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium
index e8a0b27..d03c7ab6 100644
--- a/third_party/metrics_proto/README.chromium
+++ b/third_party/metrics_proto/README.chromium
@@ -1,8 +1,8 @@
 Name: Metrics Protos
 Short Name: metrics_proto
 URL: This is the canonical public repository
-Version: 577946032
-Date: 2023-10-30 UTC
+Version: 579983285
+Date: 2023-11-06 UTC
 License: BSD
 License File: LICENSE
 Shipped: yes
diff --git a/third_party/metrics_proto/system_profile.proto b/third_party/metrics_proto/system_profile.proto
index 0c9ecfe..3c7b4f7 100644
--- a/third_party/metrics_proto/system_profile.proto
+++ b/third_party/metrics_proto/system_profile.proto
@@ -1228,7 +1228,7 @@
   optional LinkedAndroidPhoneData linked_android_phone_data = 29;
 
   // Demo mode related dimension information.
-  // Next Tag: 4
+  // Next Tag: 6
   message DemoModeDimensions {
     optional string country = 1;
 
@@ -1246,6 +1246,16 @@
       FEATURE_AWARE_DEVICE = 2;
     }
     repeated CustomizationFacet customization_facet = 3 [packed = true];
+
+    // The Demo Mode highlights app version. The version number is used to
+    // identify the Omaha Chrome Component - Demo Mode App package that was
+    // downloaded onto the device.
+    optional string app_version = 4;
+
+    // The Demo Mode resources version. The version number is used to identify
+    // the Omaha Chrome Component - Demo Mode Resources bundle that was
+    // downloaded onto the device.
+    optional string resources_version = 5;
   }
   optional DemoModeDimensions demo_mode_dimensions = 41;
 
diff --git a/third_party/perfetto b/third_party/perfetto
index 86ba297..ed90e27 160000
--- a/third_party/perfetto
+++ b/third_party/perfetto
@@ -1 +1 @@
-Subproject commit 86ba297f4358f76eced618085b9aa669446a6c51
+Subproject commit ed90e2735442263d54f02f2aa7410762f653d9c8
diff --git a/third_party/rust/BUILD.gn.hbs b/third_party/rust/BUILD.gn.hbs
index b48d403..a061046f 100644
--- a/third_party/rust/BUILD.gn.hbs
+++ b/third_party/rust/BUILD.gn.hbs
@@ -8,9 +8,9 @@
 import("//build/rust/cargo_crate.gni")
 
 {{#each rules}}
-{{#if this.1.concrete}}
-cargo_crate("{{this.0}}") {
-  {{#with this.1.concrete}}
+{{#if this.detail.crate}}
+cargo_crate("{{this.name}}") {
+  {{#with this.detail.crate}}
   {{#if crate_name}}
   crate_name = "{{crate_name}}"
   {{/if}}
@@ -18,12 +18,6 @@
   epoch = "{{epoch}}"
   {{/if}}
   crate_type = "{{crate_type}}"
-  {{#unless public_visibility}}
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
-  {{/unless}}
   crate_root = "{{crate_root}}"
   sources = [
     {{#each sources}}
@@ -142,16 +136,22 @@
   output_dir = "{{output_dir}}"
   {{/if}}
   {{/with}}
+  {{#unless this.gn_visibility.public}}
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
+  {{/unless}}
 }
 {{/if}}
-{{#if this.1.group}}
-group("{{this.0}}") {
-  {{#with this.1.group}}
-  public_deps = [":{{concrete_target}}"]
-  {{#if testonly}}
+{{#if this.detail.testonly_alias}}
+group("{{this.name}}") {
+  {{#with this.detail.testonly_alias}}
+  public_deps = [":{{real_target}}"]
+  {{/with}}
+  {{#if this.gn_visibility.testonly}}
   testonly = true
   {{/if}}
-  {{/with}}
 }
 {{/if}}
 {{/each}}
diff --git a/third_party/rust/aho_corasick/v0_7/BUILD.gn b/third_party/rust/aho_corasick/v0_7/BUILD.gn
index 343f269..33070c0 100644
--- a/third_party/rust/aho_corasick/v0_7/BUILD.gn
+++ b/third_party/rust/aho_corasick/v0_7/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "aho_corasick"
   epoch = "0.7"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/aho_corasick/v0_7/crate/src/ahocorasick.rs",
@@ -58,4 +54,8 @@
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
   deps = [ "//third_party/rust/memchr/v2:lib" ]
   features = [ "std" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/anstyle/v1/BUILD.gn b/third_party/rust/anstyle/v1/BUILD.gn
index 31016af..fe38b2d 100644
--- a/third_party/rust/anstyle/v1/BUILD.gn
+++ b/third_party/rust/anstyle/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "anstyle"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/anstyle/v1/crate/examples/dump.rs",
@@ -38,4 +34,8 @@
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
   features = [ "std" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/anyhow/v1/BUILD.gn b/third_party/rust/anyhow/v1/BUILD.gn
index b4a136a..a52500d0 100644
--- a/third_party/rust/anyhow/v1/BUILD.gn
+++ b/third_party/rust/anyhow/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "anyhow"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/anyhow/v1/crate/build.rs",
@@ -69,6 +65,10 @@
   features = [ "std" ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
diff --git a/third_party/rust/autocfg/v1/BUILD.gn b/third_party/rust/autocfg/v1/BUILD.gn
index 8232872d..347dd4f0 100644
--- a/third_party/rust/autocfg/v1/BUILD.gn
+++ b/third_party/rust/autocfg/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "autocfg"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/autocfg/v1/crate/examples/integers.rs",
@@ -40,4 +36,8 @@
   library_configs += [ "//build/config/compiler:no_chromium_code" ]
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/base64/v0_13/BUILD.gn b/third_party/rust/base64/v0_13/BUILD.gn
index e5acbe1d..8bce3ff 100644
--- a/third_party/rust/base64/v0_13/BUILD.gn
+++ b/third_party/rust/base64/v0_13/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "base64"
   epoch = "0.13"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/base64/v0_13/crate/benches/benchmarks.rs",
@@ -57,4 +53,8 @@
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
   features = [ "std" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/clap/v4/BUILD.gn b/third_party/rust/clap/v4/BUILD.gn
index 5d7719d..1e44230 100644
--- a/third_party/rust/clap/v4/BUILD.gn
+++ b/third_party/rust/clap/v4/BUILD.gn
@@ -178,10 +178,6 @@
   crate_name = "clap"
   epoch = "4"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/clap/v4/crate/examples/cargo-example-derive.rs",
@@ -343,4 +339,8 @@
     "suggestions",
     "usage",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/clap_builder/v4/BUILD.gn b/third_party/rust/clap_builder/v4/BUILD.gn
index 8a3b5cd..17a947f 100644
--- a/third_party/rust/clap_builder/v4/BUILD.gn
+++ b/third_party/rust/clap_builder/v4/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "clap_builder"
   epoch = "4"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/clap_builder/v4/crate/src/builder/action.rs",
@@ -98,4 +94,8 @@
     "suggestions",
     "usage",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/clap_lex/v0_5/BUILD.gn b/third_party/rust/clap_lex/v0_5/BUILD.gn
index c86f50a..76101196 100644
--- a/third_party/rust/clap_lex/v0_5/BUILD.gn
+++ b/third_party/rust/clap_lex/v0_5/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "clap_lex"
   epoch = "0.5"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/clap_lex/v0_5/crate/src/ext.rs",
@@ -32,4 +28,8 @@
   library_configs += [ "//build/config/compiler:no_chromium_code" ]
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/codespan_reporting/v0_11/BUILD.gn b/third_party/rust/codespan_reporting/v0_11/BUILD.gn
index cc79253..bc04f627 100644
--- a/third_party/rust/codespan_reporting/v0_11/BUILD.gn
+++ b/third_party/rust/codespan_reporting/v0_11/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "codespan_reporting"
   epoch = "0.11"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/codespan_reporting/v0_11/crate/examples/custom_files.rs",
@@ -51,4 +47,8 @@
     "//third_party/rust/termcolor/v1:lib",
     "//third_party/rust/unicode_width/v0_1:lib",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/cxxbridge_macro/v1/BUILD.gn b/third_party/rust/cxxbridge_macro/v1/BUILD.gn
index 8e5ff718..71ead3f 100644
--- a/third_party/rust/cxxbridge_macro/v1/BUILD.gn
+++ b/third_party/rust/cxxbridge_macro/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "cxxbridge_macro"
   epoch = "1"
   crate_type = "proc-macro"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/cxxbridge_macro/v1/crate/src/clang.rs",
@@ -74,4 +70,8 @@
     "//third_party/rust/quote/v1:lib",
     "//third_party/rust/syn/v2:lib",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/getrandom/v0_2/BUILD.gn b/third_party/rust/getrandom/v0_2/BUILD.gn
index eb497d0..0cf273e 100644
--- a/third_party/rust/getrandom/v0_2/BUILD.gn
+++ b/third_party/rust/getrandom/v0_2/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "getrandom"
   epoch = "0.2"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/getrandom/v0_2/crate/benches/buffer.rs",
@@ -69,4 +65,8 @@
     deps += [ "//third_party/rust/libc/v0_2:lib" ]
   }
   features = [ "std" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/hex/v0_4/BUILD.gn b/third_party/rust/hex/v0_4/BUILD.gn
index 29cc7f9..460cffc 100644
--- a/third_party/rust/hex/v0_4/BUILD.gn
+++ b/third_party/rust/hex/v0_4/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "hex"
   epoch = "0.4"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/hex/v0_4/crate/benches/hex.rs",
@@ -42,6 +38,10 @@
     "alloc",
     "std",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
diff --git a/third_party/rust/hex_literal/v0_4/BUILD.gn b/third_party/rust/hex_literal/v0_4/BUILD.gn
index 302224ca..6830d7b 100644
--- a/third_party/rust/hex_literal/v0_4/BUILD.gn
+++ b/third_party/rust/hex_literal/v0_4/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "hex_literal"
   epoch = "0.4"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/hex_literal/v0_4/crate/src/lib.rs",
@@ -37,6 +33,10 @@
   library_configs += [ "//build/config/compiler:no_chromium_code" ]
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
diff --git a/third_party/rust/itoa/v1/BUILD.gn b/third_party/rust/itoa/v1/BUILD.gn
index cd7c900..8cf912f 100644
--- a/third_party/rust/itoa/v1/BUILD.gn
+++ b/third_party/rust/itoa/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "itoa"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/itoa/v1/crate/benches/bench.rs",
@@ -35,4 +31,8 @@
   library_configs += [ "//build/config/compiler:no_chromium_code" ]
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/libc/v0_2/BUILD.gn b/third_party/rust/libc/v0_2/BUILD.gn
index 24fa9b2..d447331 100644
--- a/third_party/rust/libc/v0_2/BUILD.gn
+++ b/third_party/rust/libc/v0_2/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "libc"
   epoch = "0.2"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/libc/v0_2/crate/build.rs",
@@ -259,4 +255,8 @@
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/link_cplusplus/v1/BUILD.gn b/third_party/rust/link_cplusplus/v1/BUILD.gn
index 3f32cc1..a8075e6 100644
--- a/third_party/rust/link_cplusplus/v1/BUILD.gn
+++ b/third_party/rust/link_cplusplus/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "link_cplusplus"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/link_cplusplus/v1/crate/build.rs",
@@ -35,4 +31,8 @@
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/log/v0_4/BUILD.gn b/third_party/rust/log/v0_4/BUILD.gn
index 835587bd..5cc83080 100644
--- a/third_party/rust/log/v0_4/BUILD.gn
+++ b/third_party/rust/log/v0_4/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "log"
   epoch = "0.4"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/log/v0_4/crate/benches/value.rs",
@@ -47,6 +43,10 @@
   deps = [ "//third_party/rust/cfg_if/v1:lib" ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
diff --git a/third_party/rust/memchr/v2/BUILD.gn b/third_party/rust/memchr/v2/BUILD.gn
index 3817c9e..cfed85e 100644
--- a/third_party/rust/memchr/v2/BUILD.gn
+++ b/third_party/rust/memchr/v2/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "memchr"
   epoch = "2"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/memchr/v2/crate/build.rs",
@@ -69,4 +65,8 @@
   features = [ "std" ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/ppv_lite86/v0_2/BUILD.gn b/third_party/rust/ppv_lite86/v0_2/BUILD.gn
index cbae7eeb..da46714 100644
--- a/third_party/rust/ppv_lite86/v0_2/BUILD.gn
+++ b/third_party/rust/ppv_lite86/v0_2/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "ppv_lite86"
   epoch = "0.2"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/ppv_lite86/v0_2/crate/src/generic.rs",
@@ -41,4 +37,8 @@
     "simd",
     "std",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/rand/v0_8/BUILD.gn b/third_party/rust/rand/v0_8/BUILD.gn
index 8a863fb..bea7ba93 100644
--- a/third_party/rust/rand/v0_8/BUILD.gn
+++ b/third_party/rust/rand/v0_8/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "rand"
   epoch = "0.8"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/rand/v0_8/crate/src/distributions/bernoulli.rs",
@@ -76,6 +72,10 @@
     "std",
     "std_rng",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
diff --git a/third_party/rust/rand_chacha/v0_3/BUILD.gn b/third_party/rust/rand_chacha/v0_3/BUILD.gn
index 5839fb7..6dd3e74 100644
--- a/third_party/rust/rand_chacha/v0_3/BUILD.gn
+++ b/third_party/rust/rand_chacha/v0_3/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "rand_chacha"
   epoch = "0.3"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/rand_chacha/v0_3/crate/src/chacha.rs",
@@ -42,4 +38,8 @@
     "//third_party/rust/rand_core/v0_6:lib",
   ]
   features = [ "std" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/rand_core/v0_6/BUILD.gn b/third_party/rust/rand_core/v0_6/BUILD.gn
index e72ccdcf..cd71c85 100644
--- a/third_party/rust/rand_core/v0_6/BUILD.gn
+++ b/third_party/rust/rand_core/v0_6/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "rand_core"
   epoch = "0.6"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/rand_core/v0_6/crate/src/block.rs",
@@ -47,4 +43,8 @@
     "getrandom",
     "std",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/rand_pcg/v0_3/BUILD.gn b/third_party/rust/rand_pcg/v0_3/BUILD.gn
index f137946..309a1b8 100644
--- a/third_party/rust/rand_pcg/v0_3/BUILD.gn
+++ b/third_party/rust/rand_pcg/v0_3/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "rand_pcg"
   epoch = "0.3"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/rand_pcg/v0_3/crate/src/lib.rs",
@@ -41,6 +37,10 @@
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
   deps = [ "//third_party/rust/rand_core/v0_6:lib" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
diff --git a/third_party/rust/regex/v1/BUILD.gn b/third_party/rust/regex/v1/BUILD.gn
index 1debc4d..3ad7a88 100644
--- a/third_party/rust/regex/v1/BUILD.gn
+++ b/third_party/rust/regex/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "regex"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/regex/v1/crate/examples/shootout-regex-dna-bytes.rs",
@@ -123,6 +119,10 @@
     "unicode-script",
     "unicode-segment",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
@@ -132,10 +132,6 @@
   crate_name = "regex"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/regex/v1/crate/examples/shootout-regex-dna-bytes.rs",
@@ -244,4 +240,8 @@
     "unicode-script",
     "unicode-segment",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/regex_syntax/v0_6/BUILD.gn b/third_party/rust/regex_syntax/v0_6/BUILD.gn
index 44d9285..36b2574 100644
--- a/third_party/rust/regex_syntax/v0_6/BUILD.gn
+++ b/third_party/rust/regex_syntax/v0_6/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "regex_syntax"
   epoch = "0.6"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/regex_syntax/v0_6/crate/benches/bench.rs",
@@ -73,4 +69,8 @@
     "unicode-script",
     "unicode-segment",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/rstest/v0_17/BUILD.gn b/third_party/rust/rstest/v0_17/BUILD.gn
index 25da875..fedd1982 100644
--- a/third_party/rust/rstest/v0_17/BUILD.gn
+++ b/third_party/rust/rstest/v0_17/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "rstest"
   epoch = "0.17"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/rstest/v0_17/crate/src/lib.rs",
@@ -112,6 +108,10 @@
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
   deps = [ "//third_party/rust/rstest_macros/v0_17:lib" ]
   build_deps = [ "//third_party/rust/rustc_version/v0_4:buildrs_support" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
diff --git a/third_party/rust/rstest_macros/v0_17/BUILD.gn b/third_party/rust/rstest_macros/v0_17/BUILD.gn
index 79e4da6..b9f1c52 100644
--- a/third_party/rust/rstest_macros/v0_17/BUILD.gn
+++ b/third_party/rust/rstest_macros/v0_17/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "rstest_macros"
   epoch = "0.17"
   crate_type = "proc-macro"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/rstest_macros/v0_17/crate/build.rs",
@@ -62,4 +58,8 @@
   build_deps = [ "//third_party/rust/rustc_version/v0_4:buildrs_support" ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/rstest_reuse/v0_5/BUILD.gn b/third_party/rust/rstest_reuse/v0_5/BUILD.gn
index 71410a10..02170d1 100644
--- a/third_party/rust/rstest_reuse/v0_5/BUILD.gn
+++ b/third_party/rust/rstest_reuse/v0_5/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "rstest_reuse"
   epoch = "0.5"
   crate_type = "proc-macro"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/rstest_reuse/v0_5/crate/build.rs",
@@ -58,6 +54,10 @@
   build_deps = [ "//third_party/rust/rustc_version/v0_4:buildrs_support" ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
diff --git a/third_party/rust/rustc_demangle/v0_1/BUILD.gn b/third_party/rust/rustc_demangle/v0_1/BUILD.gn
index 63b663a..66bdad8 100644
--- a/third_party/rust/rustc_demangle/v0_1/BUILD.gn
+++ b/third_party/rust/rustc_demangle/v0_1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "rustc_demangle"
   epoch = "0.1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/rustc_demangle/v0_1/crate/src/legacy.rs",
@@ -34,4 +30,8 @@
   library_configs += [ "//build/config/compiler:no_chromium_code" ]
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/rustc_version/v0_4/BUILD.gn b/third_party/rust/rustc_version/v0_4/BUILD.gn
index 4aea03c..8c489f83 100644
--- a/third_party/rust/rustc_version/v0_4/BUILD.gn
+++ b/third_party/rust/rustc_version/v0_4/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "rustc_version"
   epoch = "0.4"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/rustc_version/v0_4/crate/src/lib.rs",
@@ -35,4 +31,8 @@
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
   deps = [ "//third_party/rust/semver/v1:lib" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/rustversion/v1/BUILD.gn b/third_party/rust/rustversion/v1/BUILD.gn
index 98e39405..d837a19 100644
--- a/third_party/rust/rustversion/v1/BUILD.gn
+++ b/third_party/rust/rustversion/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "rustversion"
   epoch = "1"
   crate_type = "proc-macro"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/rustversion/v1/crate/build/build.rs",
@@ -59,4 +55,8 @@
   build_root = "crate/build/build.rs"
   build_sources = [ "crate/build/build.rs" ]
   build_script_outputs = [ "version.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/ryu/v1/BUILD.gn b/third_party/rust/ryu/v1/BUILD.gn
index 03ad708..4502314 100644
--- a/third_party/rust/ryu/v1/BUILD.gn
+++ b/third_party/rust/ryu/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "ryu"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/ryu/v1/crate/benches/bench.rs",
@@ -60,4 +56,8 @@
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/semver/v1/BUILD.gn b/third_party/rust/semver/v1/BUILD.gn
index 745b9c6..e0ed8ef 100644
--- a/third_party/rust/semver/v1/BUILD.gn
+++ b/third_party/rust/semver/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "semver"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/semver/v1/crate/benches/parse.rs",
@@ -51,4 +47,8 @@
   features = [ "std" ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/serde_derive/v1/BUILD.gn b/third_party/rust/serde_derive/v1/BUILD.gn
index bb5867a..f47f198 100644
--- a/third_party/rust/serde_derive/v1/BUILD.gn
+++ b/third_party/rust/serde_derive/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "serde_derive"
   epoch = "1"
   crate_type = "proc-macro"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/serde_derive/v1/crate/src/bound.rs",
@@ -57,4 +53,8 @@
     "//third_party/rust/quote/v1:lib",
     "//third_party/rust/syn/v2:lib",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/serde_json/v1/BUILD.gn b/third_party/rust/serde_json/v1/BUILD.gn
index 28c1301..63f3c2d 100644
--- a/third_party/rust/serde_json/v1/BUILD.gn
+++ b/third_party/rust/serde_json/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "serde_json"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/serde_json/v1/crate/build.rs",
@@ -110,6 +106,10 @@
   features = [ "std" ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
diff --git a/third_party/rust/small_ctor/v0_1/BUILD.gn b/third_party/rust/small_ctor/v0_1/BUILD.gn
index 7ac1f18dd5..bdcd18a 100644
--- a/third_party/rust/small_ctor/v0_1/BUILD.gn
+++ b/third_party/rust/small_ctor/v0_1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "small_ctor"
   epoch = "0.1"
   crate_type = "proc-macro"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/small_ctor/v0_1/crate/examples/hello.rs",
@@ -33,6 +29,10 @@
   library_configs += [ "//build/config/compiler:no_chromium_code" ]
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
diff --git a/third_party/rust/strsim/v0_10/BUILD.gn b/third_party/rust/strsim/v0_10/BUILD.gn
index 9f96510..46ed6896 100644
--- a/third_party/rust/strsim/v0_10/BUILD.gn
+++ b/third_party/rust/strsim/v0_10/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "strsim"
   epoch = "0.10"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/strsim/v0_10/crate/benches/benches.rs",
@@ -37,4 +33,8 @@
   library_configs += [ "//build/config/compiler:no_chromium_code" ]
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/syn/v1/BUILD.gn b/third_party/rust/syn/v1/BUILD.gn
index 44f38263..61440b7 100644
--- a/third_party/rust/syn/v1/BUILD.gn
+++ b/third_party/rust/syn/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "syn"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/syn/v1/crate/benches/file.rs",
@@ -140,4 +136,8 @@
   ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/termcolor/v1/BUILD.gn b/third_party/rust/termcolor/v1/BUILD.gn
index 7c97c7b..57ca2ef 100644
--- a/third_party/rust/termcolor/v1/BUILD.gn
+++ b/third_party/rust/termcolor/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "termcolor"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [ "//third_party/rust/termcolor/v1/crate/src/lib.rs" ]
   inputs = [ "//third_party/rust/termcolor/v1/crate/README.md" ]
@@ -35,4 +31,8 @@
   if (is_win) {
     deps += [ "//third_party/rust/winapi_util/v0_1:lib" ]
   }
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/unicode_ident/v1/BUILD.gn b/third_party/rust/unicode_ident/v1/BUILD.gn
index f204f05..cb35196 100644
--- a/third_party/rust/unicode_ident/v1/BUILD.gn
+++ b/third_party/rust/unicode_ident/v1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "unicode_ident"
   epoch = "1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/unicode_ident/v1/crate/benches/xid.rs",
@@ -42,4 +38,8 @@
   library_configs += [ "//build/config/compiler:no_chromium_code" ]
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/unicode_linebreak/v0_1/BUILD.gn b/third_party/rust/unicode_linebreak/v0_1/BUILD.gn
index a96dd421..28f4fe0 100644
--- a/third_party/rust/unicode_linebreak/v0_1/BUILD.gn
+++ b/third_party/rust/unicode_linebreak/v0_1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "unicode_linebreak"
   epoch = "0.1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/unicode_linebreak/v0_1/crate/build.rs",
@@ -39,4 +35,8 @@
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
   build_script_outputs = [ "tables.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/unicode_width/v0_1/BUILD.gn b/third_party/rust/unicode_width/v0_1/BUILD.gn
index 7cf76ae..7b56a93 100644
--- a/third_party/rust/unicode_width/v0_1/BUILD.gn
+++ b/third_party/rust/unicode_width/v0_1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "unicode_width"
   epoch = "0.1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/unicode_width/v0_1/crate/src/lib.rs",
@@ -35,4 +31,8 @@
   library_configs += [ "//build/config/compiler:no_chromium_code" ]
   executable_configs -= [ "//build/config/compiler:chromium_code" ]
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/winapi/v0_3/BUILD.gn b/third_party/rust/winapi/v0_3/BUILD.gn
index bf081cd..81e6c116 100644
--- a/third_party/rust/winapi/v0_3/BUILD.gn
+++ b/third_party/rust/winapi/v0_3/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "winapi"
   epoch = "0.3"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/winapi/v0_3/crate/build.rs",
@@ -450,4 +446,8 @@
   ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/winapi_util/v0_1/BUILD.gn b/third_party/rust/winapi_util/v0_1/BUILD.gn
index 768274f..286f145 100644
--- a/third_party/rust/winapi_util/v0_1/BUILD.gn
+++ b/third_party/rust/winapi_util/v0_1/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "winapi_util"
   epoch = "0.1"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/winapi_util/v0_1/crate/src/console.rs",
@@ -40,4 +36,8 @@
   if (is_win) {
     deps += [ "//third_party/rust/winapi/v0_3:lib" ]
   }
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
diff --git a/third_party/rust/wycheproof/v0_4/BUILD.gn b/third_party/rust/wycheproof/v0_4/BUILD.gn
index c7299351..71945958 100644
--- a/third_party/rust/wycheproof/v0_4/BUILD.gn
+++ b/third_party/rust/wycheproof/v0_4/BUILD.gn
@@ -11,10 +11,6 @@
   crate_name = "wycheproof"
   epoch = "0.4"
   crate_type = "rlib"
-
-  # Only for usage from third-party crates. Add the crate to
-  # third_party.toml to use it from first-party code.
-  visibility = [ "//third_party/rust/*" ]
   crate_root = "crate/src/lib.rs"
   sources = [
     "//third_party/rust/wycheproof/v0_4/crate/src/aead.rs",
@@ -61,6 +57,10 @@
     "//third_party/rust/serde/v1:lib",
     "//third_party/rust/serde_json/v1:lib",
   ]
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
 }
 group("test_support") {
   public_deps = [ ":lib" ]
diff --git a/third_party/sqlite/src b/third_party/sqlite/src
index ca75d93..a7a54e1 160000
--- a/third_party/sqlite/src
+++ b/third_party/sqlite/src
@@ -1 +1 @@
-Subproject commit ca75d938c18c99dc33b769fbdac8fc4c71befa33
+Subproject commit a7a54e1dd9b6124c725a35552d48d6ce0e3c1ef9
diff --git a/third_party/webrtc b/third_party/webrtc
index 8005606..bd396fd 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit 80056062f5066192fc602eb06bd47e4570ee766b
+Subproject commit bd396fdffae452216e1984dec3cea73937192479
diff --git a/tools/cast3p/runtime.version b/tools/cast3p/runtime.version
index b9e56cd..34c866a 100644
--- a/tools/cast3p/runtime.version
+++ b/tools/cast3p/runtime.version
@@ -1 +1 @@
-387321
+388081
diff --git a/tools/crates/gnrt/lib/gn.rs b/tools/crates/gnrt/lib/gn.rs
index 6cd31169..7bc80245f 100644
--- a/tools/crates/gnrt/lib/gn.rs
+++ b/tools/crates/gnrt/lib/gn.rs
@@ -26,7 +26,7 @@
 /// * Binary targets for crate executables
 #[derive(Serialize)]
 pub struct BuildFile {
-    pub rules: Vec<(String, Rule)>,
+    pub rules: Vec<Rule>,
 }
 
 /// Identifies a package version. A package's dependency list uses this to refer
@@ -39,17 +39,39 @@
     pub epoch: Option<String>,
 }
 
-#[derive(Debug, Serialize)]
-pub struct RuleCommon {
+/// Defines what other GN targets can depend on this one.
+#[derive(Debug, Default, Serialize)]
+pub struct GnVisibility {
     pub testonly: bool,
     /// Controls the visibility constraint on the GN target. If this is true, no
     /// visibility constraint is generated. If false, it's defined so that only
     /// other third party Rust crates can depend on this target.
-    pub public_visibility: bool,
+    pub public: bool,
 }
 
+/// A GN rule in a generated build file.
+#[derive(Debug, Serialize)]
+pub struct Rule {
+    /// The GN rule name, which can be unrelated to the Cargo package name.
+    pub name: String,
+    pub gn_visibility: GnVisibility,
+    pub detail: RuleDetail,
+}
+
+#[derive(Debug, Serialize)]
+#[serde(rename_all = "snake_case")]
+#[allow(clippy::large_enum_variant)]
+pub enum RuleDetail {
+    /// A concrete build rule for a Rust bin or lib crate.
+    Crate(CrateDetail),
+    /// An alias to a concrete rule with different visibility.
+    TestonlyAlias(TestonlyAliasDetail),
+}
+
+/// A concrete build rule. Refer to //build/rust/cargo_crate.gni for fields
+/// undocumented here.
 #[derive(Clone, Debug, Default, Serialize)]
-pub struct RuleConcrete {
+pub struct CrateDetail {
     pub crate_name: Option<String>,
     pub epoch: Option<Epoch>,
     pub crate_type: String,
@@ -69,33 +91,17 @@
     pub build_script_sources: Vec<String>,
     pub build_script_inputs: Vec<String>,
     pub build_script_outputs: Vec<String>,
+    /// Data passed unchanged from gnrt_config.toml to the build file template.
     pub extra_kv: HashMap<String, serde_json::Value>,
     /// Whether this rule depends on the main lib target in its group (e.g. a
     /// bin target alongside a lib inside a package).
     pub dep_on_lib: bool,
 }
 
-/// Describes a single GN build rule for a crate configuration. Each field
-/// corresponds directly to a argument to the `cargo_crate()` template defined
-/// in build/rust/cargo_crate.gni.
-///
-/// For undocumented fields, refer to the docs in the above file.
-#[derive(Debug, Serialize)]
-#[serde(rename_all = "snake_case")]
-#[allow(clippy::large_enum_variant)]
-pub enum Rule {
-    Concrete {
-        #[serde(flatten)]
-        common: RuleCommon,
-        #[serde(flatten)]
-        details: RuleConcrete,
-    },
-    /// The rule is an alias to a different concrete rule.
-    Group {
-        #[serde(flatten)]
-        common: RuleCommon,
-        concrete_target: String,
-    },
+#[derive(Clone, Debug, Serialize)]
+pub struct TestonlyAliasDetail {
+    /// The actual GN rule to alias. This matches a `Rule`'s `name` field.
+    pub real_target: String,
 }
 
 /// Set of rule dependencies with a shared condition.
@@ -173,7 +179,7 @@
     paths: &paths::ChromiumPaths,
     details: &CrateFiles,
     extra_config: &BuildConfig,
-) -> (String, Rule) {
+) -> Rule {
     let lib_target = dep.lib_target.as_ref().expect("dependency had no lib target");
     let crate_root_from_src = paths.to_gn_abs_path(&lib_target.root).unwrap();
     let build_script_from_src = dep.build_script.as_ref().map(|p| paths.to_gn_abs_path(p).unwrap());
@@ -197,7 +203,7 @@
         extra_kv.extend(per_crate.extra_kv.iter().map(|(k, v)| (k.clone(), v.clone())));
     }
 
-    let mut rule = RuleConcrete {
+    let mut detail = CrateDetail {
         crate_type: "rlib".to_string(),
         crate_root: format!("//{crate_root_from_src}"),
         sources: details
@@ -236,13 +242,13 @@
         ..Default::default()
     };
 
-    rule.features = dep
+    detail.features = dep
         .dependency_kinds
         .get(&deps::DependencyKind::Normal)
         .map(|pki| pki.features.clone())
         .unwrap_or(vec![]);
-    rule.features.sort_unstable();
-    rule.features.dedup();
+    detail.features.sort_unstable();
+    detail.features.dedup();
 
     // Add only normal and build dependencies: we don't run unit tests.
     let dep_deps: Vec<&DepOfDep> = dep
@@ -259,11 +265,11 @@
     // Group the dependencies by condition, where the unconditional deps come
     // first. `group_deps` always returns at least one element, even if the
     // first set is empty.
-    rule.deps = group_deps(&dep_deps, |d| PackageId {
+    detail.deps = group_deps(&dep_deps, |d| PackageId {
         name: normalize_target_name(&d.package_name),
         epoch: None,
     });
-    rule.build_deps = group_deps(&build_deps, |d| PackageId {
+    detail.build_deps = group_deps(&build_deps, |d| PackageId {
         name: normalize_target_name(&d.package_name),
         epoch: None,
     });
@@ -271,24 +277,22 @@
     for dep in dep_deps {
         let target_name = normalize_target_name(&dep.package_name);
         if target_name != dep.use_name {
-            rule.aliased_deps.push((dep.use_name.clone(), format!(":{target_name}__rlib")));
+            detail.aliased_deps.push((dep.use_name.clone(), format!(":{target_name}__rlib")));
         }
     }
     // TODO: No support for aliased_build_deps in the `cargo_crate` GN template as
     // there's been no usage needed.
 
     // If there are still no deps after `extra_deps`, simply clear the list.
-    if rule.deps.len() == 1 && rule.deps[0].packages.len() == 0 {
-        rule.deps.clear();
+    if detail.deps.len() == 1 && detail.deps[0].packages.len() == 0 {
+        detail.deps.clear();
     }
 
-    (
-        normalize_target_name(&dep.package_name),
-        Rule::Concrete {
-            common: RuleCommon { testonly: false, public_visibility: true },
-            details: rule,
-        },
-    )
+    Rule {
+        name: normalize_target_name(&dep.package_name),
+        gn_visibility: GnVisibility { testonly: false, public: true },
+        detail: RuleDetail::Crate(detail),
+    }
 }
 
 /// Generate the `BuildFile` for `dep`, or return `None` if no rules would be
@@ -314,7 +318,7 @@
 
     // Template for all the rules in a build file. Several fields are
     // the same for all of a package's rules.
-    let mut rule_template = RuleConcrete {
+    let mut template = CrateDetail {
         edition: dep.edition.to_string(),
         cargo_pkg_version: dep.version.to_string(),
         cargo_pkg_authors,
@@ -333,8 +337,8 @@
 
     // Enumerate the dependencies of each kind for the package.
     for (gn_deps, cargo_deps) in [
-        (&mut rule_template.deps, &dep.dependencies),
-        (&mut rule_template.build_deps, &dep.build_dependencies),
+        (&mut template.deps, &dep.dependencies),
+        (&mut template.build_deps, &dep.build_dependencies),
     ] {
         let cargo_deps: Vec<_> = cargo_deps.iter().collect();
 
@@ -354,13 +358,13 @@
         }
     }
 
-    rule_template.aliased_deps.sort_unstable();
+    template.aliased_deps.sort_unstable();
 
-    let mut rules: Vec<(String, Rule)> = Vec::new();
+    let mut rules: Vec<Rule> = Vec::new();
 
     // Generate rules for each binary the package provides.
     for bin_target in &dep.bin_targets {
-        let mut bin_rule = rule_template.clone();
+        let mut bin_rule = template.clone();
         bin_rule.crate_type = "bin".to_string();
         bin_rule.crate_root = to_gn_path(bin_target.root.as_path());
         bin_rule.sources =
@@ -386,13 +390,11 @@
             }
         }
 
-        rules.push((
-            NormalizedName::from_crate_name(&bin_target.name).to_string(),
-            Rule::Concrete {
-                common: RuleCommon { testonly: false, public_visibility: true },
-                details: bin_rule,
-            },
-        ));
+        rules.push(Rule {
+            name: NormalizedName::from_crate_name(&bin_target.name).to_string(),
+            gn_visibility: GnVisibility { testonly: false, public: true },
+            detail: RuleDetail::Crate(bin_rule),
+        });
     }
 
     // Generate the rule for the main library target, if it exists.
@@ -413,7 +415,7 @@
             }
             .to_string();
 
-            let mut lib_details = rule_template.clone();
+            let mut lib_details = template.clone();
             lib_details.crate_name = Some(crate_id.normalized_name().to_string());
             lib_details.epoch = Some(Epoch::from_version(&crate_id.version));
             lib_details.crate_type = lib_target.lib_type.to_string();
@@ -427,29 +429,30 @@
             let testonly = dep_kind == deps::DependencyKind::Development;
             let visibility = metadata.visibility;
 
-            let lib_rule = Rule::Concrete {
-                common: RuleCommon {
+            rules.push(Rule {
+                name: lib_rule_name.clone(),
+                gn_visibility: GnVisibility {
                     testonly,
-                    public_visibility: match visibility {
+                    public: match visibility {
                         Visibility::Public => true,
                         Visibility::ThirdParty | Visibility::TestOnlyAndThirdParty => false,
                     },
                 },
-                details: lib_details,
-            };
-
-            rules.push((lib_rule_name.clone(), lib_rule));
+                detail: RuleDetail::Crate(lib_details),
+            });
 
             // A package may be available to first-party tests. In this case limit :lib's
             // visibility to third-party but provide a testonly alias visible
             // everywhere. The :lib target must still exist for third-party
             // transitive deps, which aren't testonly.
             if dep_kind == Normal && visibility == Visibility::TestOnlyAndThirdParty {
-                let test_support_rule = Rule::Group {
-                    common: RuleCommon { testonly: true, public_visibility: true },
-                    concrete_target: lib_rule_name,
-                };
-                rules.push(("test_support".to_string(), test_support_rule));
+                rules.push(Rule {
+                    name: "test_support".to_string(),
+                    gn_visibility: GnVisibility { testonly: true, public: true },
+                    detail: RuleDetail::TestonlyAlias(TestonlyAliasDetail {
+                        real_target: lib_rule_name,
+                    }),
+                })
             }
         }
     }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 02e06c6..8067f0e 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -7415,6 +7415,7 @@
       label="EMF_INVALID_OPEN_CHANNEL_TO_NATIVE_APP_FROM_NATIVE_HOST"/>
   <int value="31" label="EFH_NO_BACKGROUND_HOST_FOR_FRAME"/>
   <int value="32" label="LEGACY_IPC_MISMATCH"/>
+  <int value="33" label="ER_SW_INVALID_LAZY_BACKGROUND_PARAM"/>
 </enum>
 
 <enum name="BadMessageReasonGuestView">
diff --git a/tools/metrics/histograms/metadata/compose/enums.xml b/tools/metrics/histograms/metadata/compose/enums.xml
index 01a2c58..8a8a10a 100644
--- a/tools/metrics/histograms/metadata/compose/enums.xml
+++ b/tools/metrics/histograms/metadata/compose/enums.xml
@@ -42,6 +42,13 @@
   <int value="6" label="User permission is denied"/>
 </enum>
 
+<enum name="ComposeSessionCloseReasonType">
+  <int value="0" label="Accepted suggestion"/>
+  <int value="1" label="Close button"/>
+  <int value="2"
+      label="Session implicitly closed, often by web contents destruction"/>
+</enum>
+
 <enum name="ComposeShowStatus">
   <int value="0" label="Menu item displayed"/>
   <int value="1" label="Blocked for generic reason"/>
@@ -49,6 +56,8 @@
   <int value="3" label="Blocked for MSBB not enabled"/>
   <int value="4" label="Blocked for user not signed in"/>
   <int value="5" label="Blocked for user language not supported"/>
+  <int value="6"
+      label="Blocked for form element appearing in cross-origin subframe."/>
 </enum>
 
 </enums>
diff --git a/tools/metrics/histograms/metadata/compose/histograms.xml b/tools/metrics/histograms/metadata/compose/histograms.xml
index 0f23673ec..9aba7784 100644
--- a/tools/metrics/histograms/metadata/compose/histograms.xml
+++ b/tools/metrics/histograms/metadata/compose/histograms.xml
@@ -75,6 +75,17 @@
   </summary>
 </histogram>
 
+<histogram name="Compose.SessionCloseReason"
+    enum="ComposeSessionCloseReasonType" expires_after="2024-11-01">
+  <owner>petewil@chromium.org</owner>
+  <owner>chrome-compose-frontend@google.com</owner>
+  <summary>
+    When a session ends, record how we exited the session, whether by accepting
+    the input, canceling wiht the close button, or losing focus and not going
+    back to the session.
+  </summary>
+</histogram>
+
 </histograms>
 
 </histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml
index 3bd57f58..6ffdb813 100644
--- a/tools/metrics/histograms/metadata/extensions/histograms.xml
+++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -1288,12 +1288,16 @@
     API, and web view API events).
   </summary>
   <token key="BackgroundContextType">
-    <variant name="ExtensionEventPage2"
+    <variant name="ExtensionEventPage3"
         summary="event page. Emitted when extensions browser code receives
                  receives an ack from the renderer that it fired the event in
-                 the event page. Replaced previous version because values
-                 were inaccurate due to a bug with recording the dispatch
-                 start time 2023-08"/>
+                 the event page. It only counts events that ran in a event
+                 page background script, other listeners in the extension
+                 renderer that can receive the event are not counted.
+                 Replaced previous version because values were inaccurate due
+                 to a bug where we recorded this metric for all events for an
+                 extension, rather that just for those that ran in the lazy
+                 background page script 2023-10"/>
     <variant name="ExtensionServiceWorker2"
         summary="service worker. Emitted shortly after extensions browser
                  code receives the ack from the renderer that it fired the
diff --git a/tools/metrics/histograms/metadata/mobile/histograms.xml b/tools/metrics/histograms/metadata/mobile/histograms.xml
index 059da1ab0..79419afd 100644
--- a/tools/metrics/histograms/metadata/mobile/histograms.xml
+++ b/tools/metrics/histograms/metadata/mobile/histograms.xml
@@ -35,6 +35,8 @@
   <variant name="InfobarTypeAutofillAddressProfile"
       summary="Recorded for Autofill Address Infobar."/>
   <variant name="InfobarTypeConfirm" summary="Recorded for Confirm Messages."/>
+  <variant name="InfobarTypeParcelTracking"
+      summary="Recorded for Parcel Tracking Infobar."/>
   <variant name="InfobarTypePasswordSave"
       summary="Recorded for Save Password Infobar."/>
   <variant name="InfobarTypePasswordUpdate"
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml
index d31a752..fc12409b 100644
--- a/tools/metrics/histograms/metadata/sync/histograms.xml
+++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -732,7 +732,7 @@
 </histogram>
 
 <histogram name="Sync.Local.Enabled2" enum="BooleanEnabled"
-    expires_after="2023-12-17">
+    expires_after="2024-12-17">
   <owner>igorruvinov@chromium.org</owner>
   <owner>pastarmovj@chromium.org</owner>
   <component>Services&gt;Sync</component>
diff --git a/tools/metrics/histograms/metadata/web_apk/histograms.xml b/tools/metrics/histograms/metadata/web_apk/histograms.xml
index 5e8db68..6310086 100644
--- a/tools/metrics/histograms/metadata/web_apk/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_apk/histograms.xml
@@ -59,6 +59,13 @@
   </summary>
 </histogram>
 
+<histogram name="WebApk.Database.WriteResult" units="boolean"
+    expires_after="2024-06-01">
+  <owner>hartmanng@chromium.org</owner>
+  <owner>src/chrome/android/webapk/OWNERS</owner>
+  <summary>Records the write result (boolean) in WebApkDatabase.</summary>
+</histogram>
+
 <histogram name="WebApk.Install.AvailableSpace.Fail" units="MB"
     expires_after="2023-12-01">
   <owner>hartmanng@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 19b6afd3..5238b6bf 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@
             "full_remote_path": "perfetto-luci-artifacts/3f522a981c45dc5d735a5e5d775c70188adff93c/linux-arm64/trace_processor_shell"
         },
         "win": {
-            "hash": "1e0ed5a99e074792709e27a1f5fcd90e7a399fc0",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/ef4620d4c8285c95aeb2c0e80568a852c829a977/trace_processor_shell.exe"
+            "hash": "04ef2b842e7214f0adf2858a872dda7a0335c347",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/86ba297f4358f76eced618085b9aa669446a6c51/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "a6d798c6ea35705f2ab9ace2b224c32e376eb0ce",
@@ -14,7 +14,7 @@
         },
         "mac": {
             "hash": "f5fb18b0518c9b46cbe8753bdec4b42864b1fba2",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/ef4620d4c8285c95aeb2c0e80568a852c829a977/trace_processor_shell"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/86ba297f4358f76eced618085b9aa669446a6c51/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "cc287491e9ff9fe2c4866e5574eaea04134895a0",
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc
index 55eca71..8ca9e9c 100644
--- a/ui/message_center/views/notification_view.cc
+++ b/ui/message_center/views/notification_view.cc
@@ -118,6 +118,8 @@
 // as well as capitalizing the given label string. Used by chrome notifications.
 // Ash notifications create their own.
 class NotificationTextButton : public views::MdTextButton {
+  METADATA_HEADER(NotificationTextButton, views::MdTextButton)
+
  public:
   NotificationTextButton(PressedCallback callback, const std::u16string& label)
       : views::MdTextButton(std::move(callback), label) {
@@ -153,10 +155,14 @@
   absl::optional<SkColor> color_;
 };
 
+BEGIN_METADATA(NotificationTextButton)
+END_METADATA
+
 // InlineSettingsRadioButton ///////////////////////////////////////////////////
 
 class InlineSettingsRadioButton : public views::RadioButton {
   METADATA_HEADER(InlineSettingsRadioButton, views::RadioButton)
+
  public:
   explicit InlineSettingsRadioButton(const std::u16string& label_text)
       : views::RadioButton(label_text, 1 /* group */) {
diff --git a/ui/message_center/views/notification_view_base.h b/ui/message_center/views/notification_view_base.h
index 3fccf18d..c8f6221 100644
--- a/ui/message_center/views/notification_view_base.h
+++ b/ui/message_center/views/notification_view_base.h
@@ -43,6 +43,7 @@
 // line. This view is used for NOTIFICATION_TYPE_PROGRESS.
 class CompactTitleMessageView : public views::View {
   METADATA_HEADER(CompactTitleMessageView, views::View)
+
  public:
   CompactTitleMessageView();
   CompactTitleMessageView(const CompactTitleMessageView&) = delete;
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 5a747d5..9fa201a 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -875,8 +875,9 @@
   if (len_with_null - 1 == title.length() &&
       GetWindowText(hwnd(), base::WriteInto(&current_title, len_with_null),
                     len_with_null) &&
-      current_title == base::AsWStringPiece(title))
+      current_title == base::AsWStringView(title)) {
     return false;
+  }
   SetWindowText(hwnd(), base::as_wcstr(title));
   return true;
 }
diff --git a/v8 b/v8
index 6f7f7fc..d8629e1 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit 6f7f7fc9a15d3d026dfb83127d7696384a260453
+Subproject commit d8629e1b3fd3f577927bc834b67b7b67daddd471