diff --git a/DEPS b/DEPS
index 1476ea5..fb2dee3a 100644
--- a/DEPS
+++ b/DEPS
@@ -308,11 +308,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '56b616844ff7afddf73ae342ac4287a816603ca2',
+  'skia_revision': '770835703800e0017d21c39414c615004675913d',
   # 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': '670e12fa6ee88250bc5c7070ffcc7483159d94a4',
+  'v8_revision': 'd945cbe39f0a270cc44e56fc263c0953c575e366',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
@@ -359,7 +359,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '7bac4d146a86482c154bf878221ff321faccac4c',
+  'freetype_revision': '57617782464411201ce7bbc93b086c1b4d7d84a5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -423,11 +423,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '33ffb3786277319c85806c06fcf51a6fbbb21aee',
+  'dawn_revision': 'fc8f2b61a0e606040b3a5f88d16692b3c44b1970',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '99be906332f369aaecc3fed7bb1943018d7c213b',
+  'quiche_revision': '83a9e81296b36898025bce1110db9f9c4f23afd3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -499,7 +499,7 @@
 
   # If you change this, also update the libc++ revision in
   # //buildtools/deps_revisions.gni.
-  'libcxx_revision':       '69115fd1bdb6ffc918b5559eaef1d0caeb3a045a',
+  'libcxx_revision':       '53801f26327be0359ffd785d2c9b186067ac6ef6',
 
   # GN CIPD package version.
   'gn_version': 'git_revision:5fd939de8a66c915778c14a2788a857be858ef6c',
@@ -823,12 +823,12 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '0f214c7f87366bba55645490815654cb6f2f34ba',
+    'd9fbbb1a8ba25f6fe6d396882b1a8649fbeac966',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + 'd8878295ced9193396fc47c4c67d9569c6240234',
+    'url': Var('chromium_git') + '/website.git' + '@' + '2c6ad70aba273dc83f20250b635c11ac9770caaf',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -985,7 +985,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': '08q85xGGrxGuHNaub5h0MHnhU9ZoGRMx91li-R6P1DAC',
+          'version': 'm-I30LLs_nNvsNtlBBaiWNEZJLLhBTlJvpCS5bRLXmAC',
       },
     ],
     'condition': 'checkout_android',
@@ -1195,7 +1195,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6592c255249330478d24c29866cc4e5967a7a951',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9f668bbff99167ba797888c6d322dd309f338aee',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1846,7 +1846,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'f6d89c7267a638f77be43ba33754b6d3a1098f37',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'f8587da72b065606a1b5e2074f628f9cc1473604',
+    Var('webrtc_git') + '/src.git' + '@' + 'edd804816cd1e57374717e9e2bdd2c4237b6e692',
 
   # 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.
@@ -1980,7 +1980,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'rOsyTlz3bUmoCL3JLx5IjynrfEL0f1iiHNrHnqo1M1QC',
+        'version': 'nIO4GXjw47i534TNJWhe55B5QuuHFSgVy_dQt34-FbYC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4009,7 +4009,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        'e2a8fd4b81ae3adb0741c97e42aabe11f664bd8a',
+        'd6d14a40e59c5a580be24a0c0505f4791b26c9ba',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_content_browser_client_receiver_bindings.cc b/android_webview/browser/aw_content_browser_client_receiver_bindings.cc
index ed9a0b5e..191b6c6e 100644
--- a/android_webview/browser/aw_content_browser_client_receiver_bindings.cc
+++ b/android_webview/browser/aw_content_browser_client_receiver_bindings.cc
@@ -165,16 +165,11 @@
     RegisterAssociatedInterfaceBindersForRenderFrameHost(
         content::RenderFrameHost& render_frame_host,
         blink::AssociatedInterfaceRegistry& associated_registry) {
-  // TODO(lingqi): Swap the parameters so that lambda functions are not needed.
   associated_registry.AddInterface<autofill::mojom::AutofillDriver>(
       base::BindRepeating(
-          [](content::RenderFrameHost* render_frame_host,
-             mojo::PendingAssociatedReceiver<autofill::mojom::AutofillDriver>
-                 receiver) {
-            autofill::ContentAutofillDriverFactory::BindAutofillDriver(
-                std::move(receiver), render_frame_host);
-          },
+          &autofill::ContentAutofillDriverFactory::BindAutofillDriver,
           &render_frame_host));
+  // TODO(lingqi): Swap the parameters so that lambda functions are not needed.
   associated_registry.AddInterface<
       content_capture::mojom::ContentCaptureReceiver>(base::BindRepeating(
       [](content::RenderFrameHost* render_frame_host,
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
index b8d77f2d..f3e5ede 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -723,6 +723,16 @@
                         + "system pages as much as possible so that other applications can "
                         + "reuse the memory pages."),
         Flag.baseFeature(
+                BaseFeatures.PARTITION_ALLOC_SORT_ACTIVE_SLOT_SPANS,
+                "Sorts the active slot spans in PartitionRoot::PurgeMemory()."),
+        Flag.baseFeature(
+                BaseFeatures.PARTITION_ALLOC_SORT_SMALLER_SLOT_SPAN_FREE_LISTS,
+                "sort free lists for smaller slot spans in PartitionRoot::PurgeMemory()."),
+        Flag.baseFeature(
+                BaseFeatures.PARTITION_ALLOC_STRAIGHTEN_LARGER_SLOT_SPAN_FREE_LISTS,
+                "Straightens free lists for larger slot spans in PartitionRoot::PurgeMemory() -> "
+                        + "... -> PartitionPurgeSlotSpan()."),
+        Flag.baseFeature(
                 BlinkFeatures.FORM_CONTROLS_VERTICAL_WRITING_MODE_TEXT_SUPPORT,
                 "Enables support for CSS vertical writing mode on text-based form controls."),
         Flag.baseFeature(
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index aa2ea91b..2befa950 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -188,10 +188,6 @@
     // to the new mechanism in android_webview/browser/aw_field_trials.cc.
     base::ScopedAddFeatureFlags features(cl);
 
-    features.EnableIfNotSet(autofill::features::kAutofillExtractAllDatalists);
-    features.EnableIfNotSet(
-        autofill::features::kAutofillLegacyDatalistDropdown);
-
     if (cl->HasSwitch(switches::kWebViewLogJsConsoleMessages)) {
       features.EnableIfNotSet(::features::kLogJsConsoleMessages);
     }
diff --git a/android_webview/renderer/aw_render_frame_ext.cc b/android_webview/renderer/aw_render_frame_ext.cc
index 1f9014d5..289952ca 100644
--- a/android_webview/renderer/aw_render_frame_ext.cc
+++ b/android_webview/renderer/aw_render_frame_ext.cc
@@ -36,6 +36,11 @@
 
 namespace {
 
+using autofill::AutofillAgent;
+using UsesKeyboardAccessoryForSuggestions =
+    autofill::AutofillAgent::UsesKeyboardAccessoryForSuggestions;
+using ExtractAllDatalists = autofill::AutofillAgent::ExtractAllDatalists;
+
 const char kAddressPrefix[] = "geo:0,0?q=";
 const char kEmailPrefix[] = "mailto:";
 const char kPhoneNumberPrefix[] = "tel:";
@@ -148,8 +153,10 @@
   auto password_autofill_agent =
       std::make_unique<autofill::PasswordAutofillAgent>(render_frame,
                                                         &registry_);
-  new autofill::AutofillAgent(render_frame, std::move(password_autofill_agent),
-                              nullptr, &registry_);
+  new AutofillAgent(
+      render_frame,
+      {UsesKeyboardAccessoryForSuggestions(false), ExtractAllDatalists(true)},
+      std::move(password_autofill_agent), nullptr, &registry_);
   if (content_capture::features::IsContentCaptureEnabled())
     new content_capture::ContentCaptureSender(render_frame, &registry_);
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index ac9273ca..192a7e75 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -3420,7 +3420,6 @@
     "picker/picker_controller_unittest.cc",
     "picker/picker_insert_media_request_unittest.cc",
     "picker/picker_session_metrics_unittest.cc",
-    "picker/views/picker_category_view_unittest.cc",
     "picker/views/picker_contents_view_unittest.cc",
     "picker/views/picker_gif_view_unittest.cc",
     "picker/views/picker_search_field_view_unittest.cc",
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index b23f015..a951265 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -2700,6 +2700,12 @@
 // rootfs.
 BASE_FEATURE(kTimeOfDayDlc, "TimeOfDayDlc", base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Enable or disable listening to prefs for virtual keyboard policy in login
+// screen.
+BASE_FEATURE(kTouchVirtualKeyboardPolicyListenPrefsAtLogin,
+             "TouchVirtualKeyboardPolicyListenPrefsAtLogin",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 // Enables the TrafficCountersHandler class to auto-reset traffic counters
 // and shows Data Usage in the Celluar Settings UI.
 BASE_FEATURE(kTrafficCountersEnabled,
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index d94344e..fb568463 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -836,6 +836,8 @@
 COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kTimeOfDayWallpaperForcedAutoSchedule);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kTimeOfDayDlc);
+COMPONENT_EXPORT(ASH_CONSTANTS)
+BASE_DECLARE_FEATURE(kTouchVirtualKeyboardPolicyListenPrefsAtLogin);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kTrafficCountersEnabled);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kTrilinearFiltering);
 COMPONENT_EXPORT(ASH_CONSTANTS)
diff --git a/ash/picker/picker_controller.cc b/ash/picker/picker_controller.cc
index 789aa27..eb15430 100644
--- a/ash/picker/picker_controller.cc
+++ b/ash/picker/picker_controller.cc
@@ -128,6 +128,12 @@
       PickerSearchResults::Section(
           u"Matching expressions",
           {{PickerSearchResult(u"👍"), PickerSearchResult(u"😊")}}),
+      PickerSearchResults::Section(u"Matching links",
+                                   {{PickerSearchResult(u"www.foo.com"),
+                                     PickerSearchResult(u"crbug.com")}}),
+      PickerSearchResults::Section(u"Matching files",
+                                   {{PickerSearchResult(u"my file"),
+                                     PickerSearchResult(u"my other file")}}),
   }}));
 }
 
@@ -143,9 +149,8 @@
   }
 
   // This cancels the previous request if there was one.
-  // TODO: b/316936944 - Actually insert a real result.
   insert_media_request_ = std::make_unique<PickerInsertMediaRequest>(
-      input_method, u"test", kInsertMediaTimeout);
+      input_method, result.text(), kInsertMediaTimeout);
 }
 
 bool PickerController::ShouldPaint() {
diff --git a/ash/picker/picker_controller_unittest.cc b/ash/picker/picker_controller_unittest.cc
index fced6b5..e164c5f 100644
--- a/ash/picker/picker_controller_unittest.cc
+++ b/ash/picker/picker_controller_unittest.cc
@@ -4,11 +4,16 @@
 
 #include "ash/picker/picker_controller.h"
 
+#include "ash/picker/model/picker_search_results.h"
 #include "ash/public/cpp/picker/picker_client.h"
+#include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/test/test_ash_web_view_factory.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
+#include "ui/base/ime/fake_text_input_client.h"
+#include "ui/base/ime/input_method.h"
 #include "ui/views/test/widget_test.h"
 
 namespace ash {
@@ -103,5 +108,41 @@
   histogram.ExpectTotalCount("Ash.Picker.Session.InputReadyLatency", 1);
 }
 
+TEST_F(PickerControllerTest, InsertResultDoesNothingWhenWidgetIsClosed) {
+  PickerController controller;
+  TestPickerClient client(&controller);
+  auto* input_method =
+      Shell::GetPrimaryRootWindow()->GetHost()->GetInputMethod();
+
+  controller.InsertResultOnNextFocus(PickerSearchResult(u"abc"));
+  ui::FakeTextInputClient input_field(ui::TEXT_INPUT_TYPE_TEXT);
+  input_method->SetFocusedTextInputClient(&input_field);
+  absl::Cleanup focused_input_field_reset = [input_method] {
+    // Reset the input field since it will be destroyed before `input_method`.
+    input_method->SetFocusedTextInputClient(nullptr);
+  };
+
+  EXPECT_EQ(input_field.text(), u"");
+}
+
+TEST_F(PickerControllerTest, InsertResultInsertsIntoInputFieldAfterFocus) {
+  PickerController controller;
+  TestPickerClient client(&controller);
+  controller.ToggleWidget();
+  auto* input_method =
+      Shell::GetPrimaryRootWindow()->GetHost()->GetInputMethod();
+
+  controller.InsertResultOnNextFocus(PickerSearchResult(u"abc"));
+  controller.widget_for_testing()->CloseNow();
+  ui::FakeTextInputClient input_field(ui::TEXT_INPUT_TYPE_TEXT);
+  input_method->SetFocusedTextInputClient(&input_field);
+  absl::Cleanup focused_input_field_reset = [input_method] {
+    // Reset the input field since it will be destroyed before `input_method`.
+    input_method->SetFocusedTextInputClient(nullptr);
+  };
+
+  EXPECT_EQ(input_field.text(), u"abc");
+}
+
 }  // namespace
 }  // namespace ash
diff --git a/ash/picker/views/picker_category_view.cc b/ash/picker/views/picker_category_view.cc
index 08b3809..147bcfc 100644
--- a/ash/picker/views/picker_category_view.cc
+++ b/ash/picker/views/picker_category_view.cc
@@ -5,51 +5,29 @@
 #include "ash/picker/views/picker_category_view.h"
 
 #include <memory>
+#include <utility>
 
-#include "ash/picker/model/picker_category.h"
 #include "ash/picker/model/picker_search_results.h"
-#include "ash/picker/views/picker_item_view.h"
-#include "ash/picker/views/picker_section_view.h"
-#include "base/functional/bind.h"
-#include "base/functional/callback.h"
+#include "ash/picker/views/picker_search_results_view.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/views/layout/flex_layout.h"
 #include "ui/views/layout/layout_manager.h"
 
 namespace ash {
 
-PickerCategoryView::PickerCategoryView(SelectResultCallback callback)
-    : select_result_callback_(std::move(callback)) {
+PickerCategoryView::PickerCategoryView(
+    PickerSearchResultsView::SelectSearchResultCallback callback) {
   SetLayoutManager(std::make_unique<views::FlexLayout>())
       ->SetOrientation(views::LayoutOrientation::kVertical);
+
+  search_results_view_ = AddChildView(
+      std::make_unique<PickerSearchResultsView>(std::move(callback)));
 }
 
 PickerCategoryView::~PickerCategoryView() = default;
 
 void PickerCategoryView::SetResults(const PickerSearchResults& results) {
-  results_ = results;
-
-  section_views_.clear();
-  RemoveAllChildViews();
-  for (const auto& section : results_.sections()) {
-    auto* section_view =
-        AddChildView(std::make_unique<PickerSectionView>(section.heading()));
-    for (const auto& result : section.results()) {
-      // `base::Unretained` is safe here because this class owns the section
-      // view, which owns the item view.
-      section_view->AddItemView(std::make_unique<PickerItemView>(
-          base::BindOnce(&PickerCategoryView::SelectResult,
-                         base::Unretained(this), result),
-          result.text()));
-    }
-    section_views_.push_back(section_view);
-  }
-}
-
-void PickerCategoryView::SelectResult(const PickerSearchResult& result) {
-  if (!select_result_callback_.is_null()) {
-    std::move(select_result_callback_).Run(result);
-  }
+  search_results_view_->SetSearchResults(results);
 }
 
 BEGIN_METADATA(PickerCategoryView)
diff --git a/ash/picker/views/picker_category_view.h b/ash/picker/views/picker_category_view.h
index 33178c3..630ae40f 100644
--- a/ash/picker/views/picker_category_view.h
+++ b/ash/picker/views/picker_category_view.h
@@ -6,28 +6,21 @@
 #define ASH_PICKER_VIEWS_PICKER_CATEGORY_VIEW_H_
 
 #include "ash/ash_export.h"
-#include "ash/picker/model/picker_category.h"
-#include "ash/picker/model/picker_search_results.h"
-#include "base/containers/span.h"
-#include "base/functional/callback_forward.h"
+#include "ash/picker/views/picker_search_results_view.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/view.h"
 
 namespace ash {
 
-class PickerSearchResult;
-class PickerSectionView;
+class PickerSearchResults;
 
 // View to show Picker results for a specific category.
 class ASH_EXPORT PickerCategoryView : public views::View {
   METADATA_HEADER(PickerCategoryView, views::View)
 
  public:
-  // Indicates the user has selected a result.
-  using SelectResultCallback =
-      base::OnceCallback<void(const PickerSearchResult& result)>;
-
-  explicit PickerCategoryView(SelectResultCallback callback);
+  explicit PickerCategoryView(
+      PickerSearchResultsView::SelectSearchResultCallback callback);
   PickerCategoryView(const PickerCategoryView&) = delete;
   PickerCategoryView& operator=(const PickerCategoryView&) = delete;
   ~PickerCategoryView() override;
@@ -35,21 +28,10 @@
   // Replaces the current results with `results`.
   void SetResults(const PickerSearchResults& results);
 
-  base::span<const raw_ptr<PickerSectionView>> section_views_for_testing()
-      const {
-    return section_views_;
-  }
-
  private:
-  // Runs `select_result_callback_` on `result`. Note that only one result can
-  // be selected (and subsequently calling this method will do nothing).
-  void SelectResult(const PickerSearchResult& result);
-
-  SelectResultCallback select_result_callback_;
-  PickerSearchResults results_;
-
-  // The views for each section of results.
-  std::vector<raw_ptr<PickerSectionView>> section_views_;
+  // Default view for displaying category results.
+  // TODO: b/316936620 - Replace this with specific category pages.
+  raw_ptr<PickerSearchResultsView> search_results_view_ = nullptr;
 };
 
 }  // namespace ash
diff --git a/ash/picker/views/picker_category_view_unittest.cc b/ash/picker/views/picker_category_view_unittest.cc
deleted file mode 100644
index 7624d85f..0000000
--- a/ash/picker/views/picker_category_view_unittest.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2024 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/picker/views/picker_category_view.h"
-
-#include <memory>
-
-#include "ash/picker/model/picker_search_results.h"
-#include "ash/picker/views/picker_item_view.h"
-#include "ash/picker/views/picker_section_view.h"
-#include "ash/test/ash_test_base.h"
-#include "ash/test/view_drawn_waiter.h"
-#include "base/functional/callback_helpers.h"
-#include "base/test/test_future.h"
-#include "testing/gmock/include/gmock/gmock-matchers.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/widget/widget.h"
-
-namespace ash {
-namespace {
-
-using ::testing::AllOf;
-using ::testing::ElementsAre;
-using ::testing::Eq;
-using ::testing::IsEmpty;
-using ::testing::Not;
-using ::testing::Pointee;
-using ::testing::Property;
-using ::testing::SizeIs;
-
-using PickerCategoryViewTest = AshTestBase;
-
-auto MatchesResultSection(const PickerSearchResults::Section& section) {
-  return AllOf(
-      Property(&PickerSectionView::title_for_testing,
-               Property(&views::Label::GetText, Eq(section.heading()))),
-      Property(&PickerSectionView::item_views_for_testing,
-               SizeIs(section.results().size())));
-}
-
-TEST_F(PickerCategoryViewTest, CreatesResultsSections) {
-  PickerCategoryView view(base::DoNothing());
-  const PickerSearchResults kResults({{
-      PickerSearchResults::Section(u"Saved",
-                                   {{PickerSearchResult(u"Result A")}}),
-      PickerSearchResults::Section(
-          u"Recently used",
-          {{PickerSearchResult(u"Result B"), PickerSearchResult(u"Result C")}}),
-  }});
-  view.SetResults(kResults);
-
-  EXPECT_THAT(view.children(), SizeIs(kResults.sections().size()));
-  EXPECT_THAT(
-      view.section_views_for_testing(),
-      ElementsAre(Pointee(MatchesResultSection(kResults.sections()[0])),
-                  Pointee(MatchesResultSection(kResults.sections()[1]))));
-}
-
-TEST_F(PickerCategoryViewTest, LeftClickSelectsResult) {
-  std::unique_ptr<views::Widget> widget = CreateFramelessTestWidget();
-  widget->SetFullscreen(true);
-  base::test::TestFuture<const PickerSearchResult&> future;
-  auto* view = widget->SetContentsView(
-      std::make_unique<PickerCategoryView>(future.GetCallback()));
-  view->SetResults(PickerSearchResults({{
-      PickerSearchResults::Section(u"Recently used",
-                                   {{PickerSearchResult(u"result")}}),
-  }}));
-  ASSERT_THAT(view->section_views_for_testing(), Not(IsEmpty()));
-  ASSERT_THAT(view->section_views_for_testing()[0]->item_views_for_testing(),
-              Not(IsEmpty()));
-
-  PickerItemView* result_view =
-      view->section_views_for_testing()[0]->item_views_for_testing()[0];
-  ViewDrawnWaiter().Wait(result_view);
-  LeftClickOn(result_view);
-
-  EXPECT_THAT(future.Get(), Property(&PickerSearchResult::text, Eq(u"result")));
-}
-
-}  // namespace
-}  // namespace ash
diff --git a/ash/webui/common/resources/office_fallback/main.html b/ash/webui/common/resources/office_fallback/main.html
index ec027f7..ed1a51f 100644
--- a/ash/webui/common/resources/office_fallback/main.html
+++ b/ash/webui/common/resources/office_fallback/main.html
@@ -10,6 +10,8 @@
     <style>
       body {
         background-color: var(--cros-bg-color-elevation-3);
+        /** Use the same height as defined in C++*/
+        height: 100vh;
         margin: 0;
       }
     </style>
diff --git a/ash/webui/common/resources/office_fallback/office_fallback_dialog.html b/ash/webui/common/resources/office_fallback/office_fallback_dialog.html
index 7e843aa..6faf342b 100644
--- a/ash/webui/common/resources/office_fallback/office_fallback_dialog.html
+++ b/ash/webui/common/resources/office_fallback/office_fallback_dialog.html
@@ -1,37 +1,52 @@
 <style>
-  #title {
-    font-family: 'Roboto Medium';
-    font-size: 14px;
-    padding-bottom: 16px;
+  :host {
+    display: block;
+    /**<office-fallback> element takes the full height of the body*/
+    height: 100%;
   }
 
-  #body {
-    font-family: 'Roboto';
-    font-weight: 300;
+  #dialog {
+    padding: 32px 32px 28px 32px;
+    /**dialog takes the full height*/
+    height: -webkit-fill-available;
+    display: flex;
+    flex-direction: column;
+  }
+
+  #dialog:focus-visible {
+    outline: none;
+  }
+
+  #text {
+    flex: 1;
+  }
+
+  #title {
+    color: var(--cros-sys-on_surface);
+    font: var(--cros-display-7-font);
+  }
+
+  .normal-text {
+    color: var(--cros-sys-on_surface_variant);
+    font: var(--cros-body-1-font);
+    margin-block-start: 16px;
   }
 
   #button-container {
     display: flex;
-    padding-top: 32px;
+    margin-block-start: 32px;
   }
 
-  #content {
-    outline: none;
-    padding-bottom: 20px;
-    padding-inline-end: 24px;
-    padding-inline-start: 24px;
-    padding-top: 24px;
-  }
-
-  :host-context([theme='refresh23']) cr-button {
+  cr-button {
     --active-bg: transparent;
     --active-shadow: none;
     --active-shadow-action: none;
     --bg-action: var(--cros-sys-primary);
     --cr-button-height: 36px;
     --disabled-bg-action:
-        var(--cros-sys-disabled_container);
-    --disabled-bg: var(--cros-sys-disabled_container);;
+      var(--cros-sys-disabled_container);
+    --disabled-bg: var(--cros-sys-disabled_container);
+    ;
     --disabled-text-color: var(--cros-sys-disabled);
     /* Use the default bg color as hover color because we
         rely on hoverBackground layer below.  */
@@ -47,45 +62,42 @@
     box-shadow: none;
   }
 
-  :host-context([theme='refresh23']) cr-button.cancel-button {
+  cr-button.secondary-button {
     background-color: var(--cros-sys-primary_container);
   }
 
-  :host-context([theme='refresh23'])
-      cr-button.cancel-button:hover::part(hoverBackground) {
+  cr-button.secondary-button:hover::part(hoverBackground) {
     background-color: var(--cros-sys-hover_on_subtle);
     display: block;
   }
 
-  :host-context([theme='refresh23'])
-      cr-button.action-button:hover::part(hoverBackground) {
+  cr-button.action-button:hover::part(hoverBackground) {
     background-color: var(--cros-sys-hover_on_prominent);
     display: block;
   }
 
-  :host-context([theme='refresh23']):host-context(.focus-outline-visible)
-      cr-button:focus {
+  :host-context(.focus-outline-visible) cr-button:focus {
     outline: 2px solid var(--cros-sys-focus_ring);
     outline-offset: 2px;
   }
 </style>
 
-<div id="content" role="dialog" autofocus tabindex="-1" aria-labelledby="title" aria-describedby="body">
-  <div id="title">
-  </div>
-  <div id="body">
-    <div id="reason-message" style="margin-bottom: 13px;"></div>
-    <div id="instructions-message"></div>
+<div id="dialog" role="dialog" autofocus tabindex="-1" aria-labelledby="title" aria-describedby="body">
+  <div id="text">
+    <div id="title"></div>
+    <div id="reason-message" class="normal-text"></div>
+    <div id="instructions-message" class="normal-text"></div>
   </div>
   <div id="button-container">
-    <cr-button id="quick-office-button">
+    <cr-button id="quick-office-button" class="secondary-button">
       $i18n{officeFallbackOpenWithOfflineEditor}
     </cr-button>
-    <cr-button id="cancel-button" class="cancel-button" style="margin-left: auto;">
+    <cr-button id="cancel-button" class="secondary-button" style="margin-left: auto;">
       $i18n{officeFallbackCancel}
     </cr-button>
-    <cr-button id="try-again-button" class="action-button">
+    <!-- 8px gap between cancel and try again button -->
+    <cr-button id="try-again-button" class="action-button" style="margin-left: 8px;">
       $i18n{officeFallbackTryAgain}
     </cr-button>
   </div>
-</div>
+</div>
\ No newline at end of file
diff --git a/ash/webui/common/resources/office_fallback/office_fallback_dialog.ts b/ash/webui/common/resources/office_fallback/office_fallback_dialog.ts
index f12ac43b6..fb98f328 100644
--- a/ash/webui/common/resources/office_fallback/office_fallback_dialog.ts
+++ b/ash/webui/common/resources/office_fallback/office_fallback_dialog.ts
@@ -5,7 +5,6 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import './strings.m.js';
 
-import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
 import {ColorChangeUpdater} from 'chrome://resources/cr_components/color_change_listener/colors_css_updater.js';
 import {assert} from 'chrome://resources/js/assert.js';
 
@@ -14,9 +13,6 @@
 import {getTemplate} from './office_fallback_dialog.html.js';
 
 window.addEventListener('load', () => {
-  const jellyEnabled = loadTimeData.getBoolean('isJellyEnabled');
-  const theme = jellyEnabled ? 'refresh23' : 'legacy';
-  document.documentElement.setAttribute('theme', theme);
   ColorChangeUpdater.forDocument().start();
 });
 
diff --git a/build/config/siso/reproxy.star b/build/config/siso/reproxy.star
index 4aacae0..5cd3450b 100644
--- a/build/config/siso/reproxy.star
+++ b/build/config/siso/reproxy.star
@@ -80,7 +80,8 @@
         path.join(toolchainpath, "bin"),
         path.join(toolchainpath, "lib"),
         path.join(toolchainpath, "usr/bin"),
-        path.join(toolchainpath, "usr/lib64"),
+        # TODO: b/320189180 - Simple Chrome builds should use libraries under usr/lib64.
+        # But, Ninja/Reclient also don't use them unexpectedly.
     ])
     rwcfg["inputs"] = inputs
     rwcfg["preserve_symlinks"] = True
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni
index 5372e4cb..0f84441 100644
--- a/buildtools/deps_revisions.gni
+++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@
 declare_args() {
   # Used to cause full rebuilds on libc++ rolls. This should be kept in sync
   # with the libcxx_revision vars in //DEPS.
-  libcxx_revision = "69115fd1bdb6ffc918b5559eaef1d0caeb3a045a"
+  libcxx_revision = "53801f26327be0359ffd785d2c9b186067ac6ef6"
 }
diff --git a/chrome/VERSION b/chrome/VERSION
index 547d17a..67298c0 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=122
 MINOR=0
-BUILD=6249
+BUILD=6250
 PATCH=0
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionPromptRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionPromptRenderTest.java
index 1cca350c..40c90d6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionPromptRenderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionPromptRenderTest.java
@@ -24,17 +24,23 @@
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.LocationSettingsTestUtil;
 import org.chromium.components.permissions.PermissionsAndroidFeatureList;
+import org.chromium.content_public.common.ContentSwitches;
 import org.chromium.device.geolocation.LocationProviderOverrider;
 import org.chromium.device.geolocation.MockLocationProvider;
 import org.chromium.ui.test.util.NightModeTestUtils;
 import org.chromium.ui.test.util.RenderTestRule;
 
+import java.io.IOException;
 import java.util.List;
 import java.util.concurrent.TimeoutException;
 
 @RunWith(ParameterizedRunner.class)
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@CommandLineFlags.Add({
+    ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+    ContentSwitches.HOST_RESOLVER_RULES + "=MAP * 127.0.0.1",
+    "ignore-certificate-errors"
+})
 public class PermissionPromptRenderTest {
 
     @ParameterAnnotations.ClassParameter
@@ -59,6 +65,7 @@
     public PermissionPromptRenderTest(boolean nightModeEnabled) {
         mNightModeEnabled = nightModeEnabled;
         mRenderTestRule.setNightModeEnabled(nightModeEnabled);
+        mPermissionRule.getEmbeddedTestServerRule().setServerUsesHttps(true);
         mPermissionRule.getEmbeddedTestServerRule().setServerPort(TEST_PORT);
     }
 
@@ -73,6 +80,17 @@
         NightModeTestUtils.tearDownNightModeForBlankUiTestActivity();
     }
 
+    private void testPrompt(boolean isOneTime) throws TimeoutException, IOException {
+        mPermissionRule.runJavaScriptCodeWithUserGestureInCurrentTab(
+                "initiate_getCurrentPosition()");
+
+        mPermissionRule.waitForDialogShownState(true);
+
+        mRenderTestRule.render(
+                mPermissionRule.getActivity().findViewById(R.id.modal_dialog_view),
+                isOneTime ? "oneTimePrompt" : "regularPrompt");
+    }
+
     @Test
     @MediumTest
     @Feature({"Prompt", "RenderTest"})
@@ -82,6 +100,8 @@
         LocationProviderOverrider.setLocationProviderImpl(new MockLocationProvider());
 
         mPermissionRule.loadUrl(mPermissionRule.getURL(TEST_FILE));
+
+        testPrompt(/* isOneTime= */ false);
         mPermissionRule.runJavaScriptCodeWithUserGestureInCurrentTab(
                 "initiate_getCurrentPosition()");
 
@@ -92,6 +112,8 @@
                 "regularPrompt");
     }
 
+
+
     @Test
     @MediumTest
     @Feature({"Prompt", "RenderTest"})
@@ -99,15 +121,22 @@
     public void testGeolocationOneTimePrompt() throws Exception {
         LocationSettingsTestUtil.setSystemLocationSettingEnabled(true);
         LocationProviderOverrider.setLocationProviderImpl(new MockLocationProvider());
-
         mPermissionRule.setUpUrl(TEST_FILE);
-        mPermissionRule.runJavaScriptCodeWithUserGestureInCurrentTab(
-                "initiate_getCurrentPosition()");
+        testPrompt(/* isOneTime= */ true);
+    }
 
-        mPermissionRule.waitForDialogShownState(true);
+    @Test
+    @MediumTest
+    @Feature({"Prompt", "RenderTest"})
+    @Features.EnableFeatures(PermissionsAndroidFeatureList.ONE_TIME_PERMISSION)
+    public void testGeolocationOneTimePromptLongOriginWrapsToNextLineAndIsNotElided()
+            throws Exception {
+        LocationSettingsTestUtil.setSystemLocationSettingEnabled(true);
+        LocationProviderOverrider.setLocationProviderImpl(new MockLocationProvider());
 
-        mRenderTestRule.render(
-                mPermissionRule.getActivity().findViewById(R.id.modal_dialog_view),
-                "oneTimePrompt");
+        mPermissionRule.setupUrlWithHostName(
+                "unelided.long.wrapping.hostname.with.subdomains.com", TEST_FILE);
+
+        testPrompt(/* isOneTime= */ true);
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionTestRule.java
index 96b43d4..20e266f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionTestRule.java
@@ -153,8 +153,27 @@
                 () -> getInfoBarContainer().addAnimationListener(mListener));
     }
 
-    public void setUpUrl(final String url) {
-        loadUrl(getURL(url));
+    /**
+     * Navigates to a relative URL in relation to the embedded server host directly without going
+     * through the UrlBar. This bypasses the page preloading mechanism of the UrlBar.
+     *
+     * @param relativeUrl The relative URL for which an absolute URL will be computed and loaded in
+     *     the current tab.
+     */
+    public void setUpUrl(final String relativeUrl) {
+        loadUrl(getURL(relativeUrl));
+    }
+
+    /**
+     * Navigates to a relative URL in relation to the specified host directly without going through
+     * the UrlBar. This bypasses the page preloading mechanism of the UrlBar.
+     *
+     * @param relativeUrl The relative URL for which an absolute URL will be computed and loaded in
+     *     the current tab.
+     * @param hostName The host name which should be used.
+     */
+    public void setupUrlWithHostName(String hostName, String relativeUrl) {
+        loadUrl(getURLWithHostName(hostName, relativeUrl));
     }
 
     public String getURL(String url) {
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index e1e5e21..3b45b9a 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -831,6 +831,10 @@
     "metrics/variations/chrome_variations_service_client.h",
     "metrics/variations/google_groups_updater_service_factory.cc",
     "metrics/variations/google_groups_updater_service_factory.h",
+    "model_execution/model_execution_session.cc",
+    "model_execution/model_execution_session.h",
+    "model_execution/model_manager_impl.cc",
+    "model_execution/model_manager_impl.h",
     "native_window_notification_source.h",
     "navigation_predictor/anchor_element_preloader.cc",
     "navigation_predictor/anchor_element_preloader.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 24dadce9..9567ab6 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -11027,6 +11027,14 @@
     {kAssistantIphInternalName, flag_descriptions::kAssistantIphName,
      flag_descriptions::kAssistantIphDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(feature_engagement::kIPHLauncherSearchHelpUiFeature)},
+
+    {"ash-picker", flag_descriptions::kAshPickerName,
+     flag_descriptions::kAshPickerDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(ash::features::kPicker)},
+
+    {"ash-picker-feature-key", flag_descriptions::kAshPickerFeatureKeyName,
+     flag_descriptions::kAshPickerFeatureKeyDescription, kOsCrOS,
+     STRING_VALUE_TYPE(ash::switches::kPickerFeatureKey, "")},
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
     {"pwm-shadow-dom-support",
diff --git a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
index a806602..7ae6635 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/apps/app_service/app_service_proxy.h"
+
 #include <memory>
 #include <optional>
 #include <utility>
@@ -15,7 +17,6 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_future.h"
 #include "build/chromeos_buildflags.h"
-#include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/publishers/app_publisher.h"
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
@@ -247,8 +248,12 @@
 
 class AppServiceProxyTest : public testing::Test {
  public:
+  AppServiceProxyTest() : scoped_feature_list_(kAppServiceStorage) {}
+
   void SetUp() override {
-    scoped_feature_list_.InitAndEnableFeature(kAppServiceStorage);
+    profile_ = std::make_unique<TestingProfile>();
+    app_service_proxy_ = AppServiceProxyFactory::GetForProfile(profile_.get());
+    WaitForAppServiceProxyReady(proxy());
   }
 
  protected:
@@ -313,12 +318,18 @@
 #endif
   }
 
+  Profile* profile() { return profile_.get(); }
+
+  AppServiceProxy* proxy() { return app_service_proxy_; }
+
   int NumOuterFinishedCallbacks() { return num_outer_finished_callbacks_; }
 
   int num_outer_finished_callbacks_ = 0;
 
   content::BrowserTaskEnvironment task_environment_;
   base::test::ScopedFeatureList scoped_feature_list_;
+  std::unique_ptr<TestingProfile> profile_;
+  raw_ptr<AppServiceProxy> app_service_proxy_;
 };
 
 class AppServiceProxyIconTest : public AppServiceProxyTest {
@@ -340,13 +351,11 @@
   //
   // This tests an AppServiceProxy as a 'black box', which uses an
   // IconCache but also other IconLoader filters, such as an IconCoalescer.
-
-  AppServiceProxy proxy(nullptr);
   FakeIconLoader fake;
-  OverrideAppServiceProxyInnerIconLoader(&proxy, &fake);
+  OverrideAppServiceProxyInnerIconLoader(proxy(), &fake);
 
   // The next LoadIcon call should be a cache miss.
-  UniqueReleaser c0 = LoadIcon(&proxy, "cromulent");
+  UniqueReleaser c0 = LoadIcon(proxy(), "cromulent");
   EXPECT_EQ(1, fake.NumPendingCallbacks());
   EXPECT_EQ(0, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(0, NumOuterFinishedCallbacks());
@@ -358,7 +367,7 @@
   EXPECT_EQ(1, NumOuterFinishedCallbacks());
 
   // The next LoadIcon call should be a cache hit.
-  UniqueReleaser c1 = LoadIcon(&proxy, "cromulent");
+  UniqueReleaser c1 = LoadIcon(proxy(), "cromulent");
   EXPECT_EQ(0, fake.NumPendingCallbacks());
   EXPECT_EQ(1, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(2, NumOuterFinishedCallbacks());
@@ -368,7 +377,7 @@
   c1.reset();
 
   // The next LoadIcon call should be a cache miss.
-  UniqueReleaser c2 = LoadIcon(&proxy, "cromulent");
+  UniqueReleaser c2 = LoadIcon(proxy(), "cromulent");
   EXPECT_EQ(1, fake.NumPendingCallbacks());
   EXPECT_EQ(1, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(2, NumOuterFinishedCallbacks());
@@ -386,17 +395,14 @@
   //
   // This tests an AppServiceProxy as a 'black box', which uses an
   // IconCoalescer but also other IconLoader filters, such as an IconCache.
-
-  AppServiceProxy proxy(nullptr);
-
   FakeIconLoader fake;
-  OverrideAppServiceProxyInnerIconLoader(&proxy, &fake);
+  OverrideAppServiceProxyInnerIconLoader(proxy(), &fake);
 
   // Issue 4 LoadIcon requests, 2 after de-duplication.
-  UniqueReleaser a0 = LoadIcon(&proxy, "avocet");
-  UniqueReleaser a1 = LoadIcon(&proxy, "avocet");
-  UniqueReleaser b2 = LoadIcon(&proxy, "brolga");
-  UniqueReleaser a3 = LoadIcon(&proxy, "avocet");
+  UniqueReleaser a0 = LoadIcon(proxy(), "avocet");
+  UniqueReleaser a1 = LoadIcon(proxy(), "avocet");
+  UniqueReleaser b2 = LoadIcon(proxy(), "brolga");
+  UniqueReleaser a3 = LoadIcon(proxy(), "avocet");
   EXPECT_EQ(2, fake.NumPendingCallbacks());
   EXPECT_EQ(0, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(0, NumOuterFinishedCallbacks());
@@ -408,7 +414,7 @@
   EXPECT_EQ(4, NumOuterFinishedCallbacks());
 
   // Issue another request, that triggers neither IconCache nor IconCoalescer.
-  UniqueReleaser c4 = LoadIcon(&proxy, "curlew");
+  UniqueReleaser c4 = LoadIcon(proxy(), "curlew");
   EXPECT_EQ(1, fake.NumPendingCallbacks());
   EXPECT_EQ(2, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(4, NumOuterFinishedCallbacks());
@@ -421,7 +427,7 @@
   EXPECT_EQ(4, NumOuterFinishedCallbacks());
 
   // Issuing another "curlew" request should coalesce with the in-flight one.
-  UniqueReleaser c5 = LoadIcon(&proxy, "curlew");
+  UniqueReleaser c5 = LoadIcon(proxy(), "curlew");
   EXPECT_EQ(1, fake.NumPendingCallbacks());
   EXPECT_EQ(2, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(4, NumOuterFinishedCallbacks());
@@ -436,11 +442,9 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 class AppServiceProxyShortcutIconTest : public AppServiceProxyTest {
-  void SetUp() override {
-    scoped_feature_list_.InitWithFeatures(
-        {kAppServiceStorage, chromeos::features::kCrosWebAppShortcutUiUpdate},
-        {});
-  }
+ public:
+  AppServiceProxyShortcutIconTest()
+      : features_{chromeos::features::kCrosWebAppShortcutUiUpdate} {}
 
  protected:
   UniqueReleaser LoadShortcutIcon(AppServiceProxy* proxy,
@@ -470,6 +474,9 @@
       apps::IconLoader* icon_loader) {
     proxy->OverrideShortcutInnerIconLoaderForTesting(icon_loader);
   }
+
+ private:
+  base::test::ScopedFeatureList features_;
 };
 
 TEST_F(AppServiceProxyShortcutIconTest, IconCache) {
@@ -478,13 +485,11 @@
   //
   // This tests an AppServiceProxy as a 'black box', which uses an
   // IconCache but also other IconLoader filters, such as an IconCoalescer.
-
-  AppServiceProxy proxy(nullptr);
   FakeIconLoader fake;
-  OverrideAppServiceProxyShortcutInnerIconLoader(&proxy, &fake);
+  OverrideAppServiceProxyShortcutInnerIconLoader(proxy(), &fake);
 
   // The next LoadShortcutIcon call should be a cache miss.
-  UniqueReleaser c0 = LoadShortcutIcon(&proxy, "cromulent");
+  UniqueReleaser c0 = LoadShortcutIcon(proxy(), "cromulent");
   EXPECT_EQ(1, fake.NumPendingCallbacks());
   EXPECT_EQ(0, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(0, NumOuterFinishedCallbacks());
@@ -496,7 +501,7 @@
   EXPECT_EQ(1, NumOuterFinishedCallbacks());
 
   // The next LoadShortcutIcon call should be a cache hit.
-  UniqueReleaser c1 = LoadShortcutIcon(&proxy, "cromulent");
+  UniqueReleaser c1 = LoadShortcutIcon(proxy(), "cromulent");
   EXPECT_EQ(0, fake.NumPendingCallbacks());
   EXPECT_EQ(1, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(2, NumOuterFinishedCallbacks());
@@ -506,7 +511,7 @@
   c1.reset();
 
   // The next LoadShortcutIcon call should be a cache miss.
-  UniqueReleaser c2 = LoadShortcutIcon(&proxy, "cromulent");
+  UniqueReleaser c2 = LoadShortcutIcon(proxy(), "cromulent");
   EXPECT_EQ(1, fake.NumPendingCallbacks());
   EXPECT_EQ(1, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(2, NumOuterFinishedCallbacks());
@@ -524,17 +529,14 @@
   //
   // This tests an AppServiceProxy as a 'black box', which uses an
   // IconCoalescer but also other IconLoader filters, such as an IconCache.
-
-  AppServiceProxy proxy(nullptr);
-
   FakeIconLoader fake;
-  OverrideAppServiceProxyShortcutInnerIconLoader(&proxy, &fake);
+  OverrideAppServiceProxyShortcutInnerIconLoader(proxy(), &fake);
 
   // Issue 4 LoadShortcutIcon requests, 2 after de-duplication.
-  UniqueReleaser a0 = LoadShortcutIcon(&proxy, "avocet");
-  UniqueReleaser a1 = LoadShortcutIcon(&proxy, "avocet");
-  UniqueReleaser b2 = LoadShortcutIcon(&proxy, "brolga");
-  UniqueReleaser a3 = LoadShortcutIcon(&proxy, "avocet");
+  UniqueReleaser a0 = LoadShortcutIcon(proxy(), "avocet");
+  UniqueReleaser a1 = LoadShortcutIcon(proxy(), "avocet");
+  UniqueReleaser b2 = LoadShortcutIcon(proxy(), "brolga");
+  UniqueReleaser a3 = LoadShortcutIcon(proxy(), "avocet");
   EXPECT_EQ(2, fake.NumPendingCallbacks());
   EXPECT_EQ(0, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(0, NumOuterFinishedCallbacks());
@@ -546,7 +548,7 @@
   EXPECT_EQ(4, NumOuterFinishedCallbacks());
 
   // Issue another request, that triggers neither IconCache nor IconCoalescer.
-  UniqueReleaser c4 = LoadShortcutIcon(&proxy, "curlew");
+  UniqueReleaser c4 = LoadShortcutIcon(proxy(), "curlew");
   EXPECT_EQ(1, fake.NumPendingCallbacks());
   EXPECT_EQ(2, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(4, NumOuterFinishedCallbacks());
@@ -559,7 +561,7 @@
   EXPECT_EQ(4, NumOuterFinishedCallbacks());
 
   // Issuing another "curlew" request should coalesce with the in-flight one.
-  UniqueReleaser c5 = LoadShortcutIcon(&proxy, "curlew");
+  UniqueReleaser c5 = LoadShortcutIcon(proxy(), "curlew");
   EXPECT_EQ(1, fake.NumPendingCallbacks());
   EXPECT_EQ(2, fake.NumInnerFinishedCallbacks());
   EXPECT_EQ(4, NumOuterFinishedCallbacks());
@@ -573,20 +575,17 @@
 }
 
 TEST_F(AppServiceProxyShortcutIconTest, LoadShortcutIconWithBadge) {
-  TestingProfile profile;
-  AppServiceProxy* const proxy =
-      AppServiceProxyFactory::GetForProfile(&profile);
-
   FakeIconLoader fake_shortcut_loader;
   FakeIconLoader fake_app_loader;
-  OverrideAppServiceProxyShortcutInnerIconLoader(proxy, &fake_shortcut_loader);
-  OverrideAppServiceProxyInnerIconLoader(proxy, &fake_app_loader);
+  OverrideAppServiceProxyShortcutInnerIconLoader(proxy(),
+                                                 &fake_shortcut_loader);
+  OverrideAppServiceProxyInnerIconLoader(proxy(), &fake_app_loader);
 
   auto shortcut = std::make_unique<Shortcut>("host_app_id", "local_id");
   ShortcutId shortcut_id = shortcut->shortcut_id;
-  proxy->ShortcutRegistryCache()->UpdateShortcut(std::move(shortcut));
+  proxy()->ShortcutRegistryCache()->UpdateShortcut(std::move(shortcut));
 
-  UniqueReleaser c0 = LoadShortcutIconWithBadge(proxy, shortcut_id);
+  UniqueReleaser c0 = LoadShortcutIconWithBadge(proxy(), shortcut_id);
   EXPECT_EQ(1, fake_shortcut_loader.NumPendingCallbacks());
   EXPECT_EQ(0, fake_shortcut_loader.NumInnerFinishedCallbacks());
   EXPECT_EQ(0, NumOuterFinishedCallbacks());
@@ -665,25 +664,20 @@
 
 TEST_F(AppServiceProxyTest, ReinitializeClearsCache) {
   constexpr char kTestAppId[] = "pwa";
-  TestingProfile profile;
-  AppServiceProxy* const proxy =
-      AppServiceProxyFactory::GetForProfile(&profile);
-  WaitForAppServiceProxyReady(proxy);
-
   {
     std::vector<AppPtr> apps;
     AppPtr app = std::make_unique<App>(AppType::kWeb, kTestAppId);
     apps.push_back(std::move(app));
-    proxy->OnApps(std::move(apps), AppType::kWeb,
-                  /*should_notify_initialized=*/true);
+    proxy()->OnApps(std::move(apps), AppType::kWeb,
+                    /*should_notify_initialized=*/true);
   }
 
-  EXPECT_EQ(proxy->AppRegistryCache().GetAppType(kTestAppId), AppType::kWeb);
+  EXPECT_EQ(proxy()->AppRegistryCache().GetAppType(kTestAppId), AppType::kWeb);
 
-  proxy->ReinitializeForTesting(proxy->profile());
-  WaitForAppServiceProxyReady(proxy);
+  proxy()->ReinitializeForTesting(proxy()->profile());
+  WaitForAppServiceProxyReady(proxy());
 
-  EXPECT_EQ(proxy->AppRegistryCache().GetAppType(kTestAppId),
+  EXPECT_EQ(proxy()->AppRegistryCache().GetAppType(kTestAppId),
             AppType::kUnknown);
 }
 
@@ -691,24 +685,23 @@
 class AppServiceProxyPreferredAppsTest : public AppServiceProxyTest {
  public:
   void SetUp() override {
-    proxy_ = AppServiceProxyFactory::GetForProfile(&profile_);
+    AppServiceProxyTest::SetUp();
 
     // Wait for the PreferredAppsList to be initialized from disk before tests
     // start modifying it.
     base::RunLoop file_read_run_loop;
-    proxy_->ReinitializeForTesting(&profile_, file_read_run_loop.QuitClosure());
+    proxy()->ReinitializeForTesting(profile(),
+                                    file_read_run_loop.QuitClosure());
     file_read_run_loop.Run();
 
-    web_app::test::AwaitStartWebAppProviderAndSubsystems(&profile_);
+    web_app::test::AwaitStartWebAppProviderAndSubsystems(profile());
   }
 
-  AppServiceProxy* proxy() { return proxy_; }
-
   // Shortcut for adding apps to App Service without going through a real
   // Publisher.
   void OnApps(std::vector<AppPtr> apps, AppType type) {
-    proxy_->OnApps(std::move(apps), type,
-                   /*should_notify_initialized=*/false);
+    proxy()->OnApps(std::move(apps), type,
+                    /*should_notify_initialized=*/false);
   }
 
   PreferredAppsList& GetPreferredAppsList() {
@@ -718,10 +711,6 @@
   PreferredAppsImpl* PreferredAppsImpl() {
     return proxy()->preferred_apps_impl_.get();
   }
-
- private:
-  TestingProfile profile_;
-  raw_ptr<AppServiceProxy> proxy_;
 };
 
 TEST_F(AppServiceProxyPreferredAppsTest, UpdatedOnUninstall) {
@@ -1183,7 +1172,6 @@
 }
 
 TEST_F(AppServiceProxyTest, LaunchCallback) {
-  AppServiceProxy proxy(nullptr);
   bool called_1 = false;
   bool called_2 = false;
   auto instance_id_1 = base::UnguessableToken::Create();
@@ -1193,36 +1181,38 @@
   {
     LaunchResult result_1;
     result_1.instance_ids.push_back(instance_id_1);
-    proxy.OnLaunched(base::BindOnce(
-                         [](bool* called, apps::LaunchResult&& launch_result) {
-                           *called = true;
-                         },
-                         &called_1),
-                     std::move(result_1));
+    proxy()->OnLaunched(
+        base::BindOnce(
+            [](bool* called, apps::LaunchResult&& launch_result) {
+              *called = true;
+            },
+            &called_1),
+        std::move(result_1));
   }
-  EXPECT_EQ(proxy.callback_list_.size(), 1U);
+  EXPECT_EQ(proxy()->callback_list_.size(), 1U);
   EXPECT_FALSE(called_1);
 
   {
     LaunchResult result_2;
     result_2.instance_ids.push_back(instance_id_2);
-    proxy.OnLaunched(base::BindOnce(
-                         [](bool* called, apps::LaunchResult&& launch_result) {
-                           *called = true;
-                         },
-                         &called_2),
-                     std::move(result_2));
+    proxy()->OnLaunched(
+        base::BindOnce(
+            [](bool* called, apps::LaunchResult&& launch_result) {
+              *called = true;
+            },
+            &called_2),
+        std::move(result_2));
   }
-  EXPECT_EQ(proxy.callback_list_.size(), 2U);
+  EXPECT_EQ(proxy()->callback_list_.size(), 2U);
   EXPECT_FALSE(called_2);
 
   // Once the instance is created, the callback will be called.
   {
     auto delta =
         std::make_unique<apps::Instance>("abc", instance_id_1, nullptr);
-    proxy.InstanceRegistry().OnInstance(std::move(delta));
+    proxy()->InstanceRegistry().OnInstance(std::move(delta));
   }
-  EXPECT_EQ(proxy.callback_list_.size(), 1U);
+  EXPECT_EQ(proxy()->callback_list_.size(), 1U);
   EXPECT_TRUE(called_1);
   EXPECT_FALSE(called_2);
 
@@ -1230,14 +1220,15 @@
   called_1 = false;
   {
     LaunchResult result_3;
-    proxy.OnLaunched(base::BindOnce(
-                         [](bool* called, apps::LaunchResult&& launch_result) {
-                           *called = true;
-                         },
-                         &called_1),
-                     std::move(result_3));
+    proxy()->OnLaunched(
+        base::BindOnce(
+            [](bool* called, apps::LaunchResult&& launch_result) {
+              *called = true;
+            },
+            &called_1),
+        std::move(result_3));
   }
-  EXPECT_EQ(proxy.callback_list_.size(), 1U);
+  EXPECT_EQ(proxy()->callback_list_.size(), 1U);
   EXPECT_TRUE(called_1);
   EXPECT_FALSE(called_2);
 
@@ -1249,28 +1240,26 @@
     LaunchResult result_multi;
     result_multi.instance_ids.push_back(instance_id_3);
     result_multi.instance_ids.push_back(instance_id_4);
-    proxy.OnLaunched(base::BindOnce(
-                         [](bool* called, apps::LaunchResult&& launch_result) {
-                           *called = true;
-                         },
-                         &called_multi),
-                     std::move(result_multi));
+    proxy()->OnLaunched(
+        base::BindOnce(
+            [](bool* called, apps::LaunchResult&& launch_result) {
+              *called = true;
+            },
+            &called_multi),
+        std::move(result_multi));
   }
-  EXPECT_EQ(proxy.callback_list_.size(), 2U);
+  EXPECT_EQ(proxy()->callback_list_.size(), 2U);
   EXPECT_FALSE(called_multi);
-  proxy.InstanceRegistry().OnInstance(
+  proxy()->InstanceRegistry().OnInstance(
       std::make_unique<apps::Instance>("foo", instance_id_3, nullptr));
-  proxy.InstanceRegistry().OnInstance(
+  proxy()->InstanceRegistry().OnInstance(
       std::make_unique<apps::Instance>("bar", instance_id_4, nullptr));
-  EXPECT_EQ(proxy.callback_list_.size(), 1U);
+  EXPECT_EQ(proxy()->callback_list_.size(), 1U);
 
   EXPECT_TRUE(called_multi);
 }
 
 TEST_F(AppServiceProxyTest, GetAppsForIntentBestHandler) {
-  AppServiceProxy proxy(nullptr);
-  SetOnReadyForTesting(&proxy);
-
   const char kAppId1[] = "abcdefg";
   const GURL kTestUrl = GURL("https://www.example.com/");
 
@@ -1301,7 +1290,7 @@
   app->intent_filters.push_back(std::move(intent_filter2));
 
   apps.push_back(std::move(app));
-  proxy.OnApps(std::move(apps), AppType::kWeb, false);
+  proxy()->OnApps(std::move(apps), AppType::kWeb, false);
 
   std::vector<apps::IntentFilePtr> files;
   auto file = std::make_unique<apps::IntentFile>(GURL("abc.txt"));
@@ -1312,7 +1301,7 @@
       apps_util::kIntentActionView, std::move(files));
 
   std::vector<apps::IntentLaunchInfo> intent_launch_info =
-      proxy.GetAppsForIntent(intent, /*exclude_browsers=*/true);
+      proxy()->GetAppsForIntent(intent, /*exclude_browsers=*/true);
 
   // Check that we actually get back the 2nd filter, and not the excluded
   // scheme-only filter which should have been discarded.
@@ -1321,41 +1310,37 @@
 }
 
 TEST_F(AppServiceProxyTest, CreatePublisherAfterReadAppStorage) {
-  TestingProfile profile;
   constexpr char kTestAppId[] = "arc";
+  // Reinitialize App Service to re-read the App Storage file.
+  proxy()->ReinitializeForTesting(profile());
 
-  AppServiceProxy* const proxy =
-      AppServiceProxyFactory::GetForProfile(&profile);
-
-  FakeAppRegistryCacheObserver observer(&proxy->AppRegistryCache());
+  FakeAppRegistryCacheObserver observer(&proxy()->AppRegistryCache());
 
   // Add the OnApps task to the OnReady post task list.
-  proxy->OnReady()->Post(
+  proxy()->OnReady()->Post(
       FROM_HERE, base::BindLambdaForTesting([&]() {
         std::vector<AppPtr> apps;
         apps.push_back(std::make_unique<App>(AppType::kArc, kTestAppId));
-        proxy->OnApps(std::move(apps), AppType::kArc,
-                      /*should_notify_initialized=*/false);
+        proxy()->OnApps(std::move(apps), AppType::kArc,
+                        /*should_notify_initialized=*/false);
       }));
 
   // Verify no apps added to AppRegistryCache.
-  EXPECT_TRUE(proxy->AppRegistryCache().GetAllApps().empty());
+  EXPECT_TRUE(proxy()->AppRegistryCache().GetAllApps().empty());
 
   // Wait for reading AppStorage, then create publishers, and verify apps are
   // added to AppRegistryCache.
   std::set<std::string> app_ids;
   app_ids.insert(kTestAppId);
   observer.WaitForOnAppUpdate(app_ids);
-  EXPECT_FALSE(proxy->AppRegistryCache().GetAllApps().empty());
-  EXPECT_EQ(AppType::kArc, proxy->AppRegistryCache().GetAppType(kTestAppId));
+  EXPECT_FALSE(proxy()->AppRegistryCache().GetAllApps().empty());
+  EXPECT_EQ(AppType::kArc, proxy()->AppRegistryCache().GetAppType(kTestAppId));
 }
 
 class AppServiceProxyLaunchTest : public AppServiceProxyTest {
  public:
   void SetUp() override {
     AppServiceProxyTest::SetUp();
-    profile_ = std::make_unique<TestingProfile>();
-    proxy_ = AppServiceProxyFactory::GetForProfile(profile_.get());
     CreateAndInitShelfController();
   }
 
@@ -1365,8 +1350,8 @@
   void CreateAndInitShelfController() {
     model_ = std::make_unique<ash::ShelfModel>();
     shelf_controller_ =
-        std::make_unique<ChromeShelfController>(profile_.get(), model_.get());
-    shelf_controller_->SetProfileForTest(profile_.get());
+        std::make_unique<ChromeShelfController>(profile(), model_.get());
+    shelf_controller_->SetProfileForTest(profile());
     shelf_controller_->Init();
   }
 
@@ -1383,13 +1368,10 @@
   }
 
   ChromeShelfController* shelf_controller() { return shelf_controller_.get(); }
-  AppServiceProxy* proxy() { return proxy_; }
 
  public:
-  std::unique_ptr<TestingProfile> profile_;
   std::unique_ptr<ash::ShelfModel> model_;
   std::unique_ptr<ChromeShelfController> shelf_controller_;
-  raw_ptr<AppServiceProxy> proxy_;
 };
 
 // Verify the spinner can be closed when the app is uninstalled.
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index 73653fb..e5eaa98 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -4804,6 +4804,8 @@
     "policy/login/signin_profile_extensions_policy_test_base.h",
     "policy/remote_commands/crd/fake_start_crd_session_job_delegate.cc",
     "policy/remote_commands/crd/fake_start_crd_session_job_delegate.h",
+    "policy/remote_commands/device_command_fetch_support_packet_job_test_util.cc",
+    "policy/remote_commands/device_command_fetch_support_packet_job_test_util.h",
     "policy/reporting/metrics_reporting/cros_healthd_info_metric_sampler_test_utils.cc",
     "policy/reporting/metrics_reporting/cros_healthd_info_metric_sampler_test_utils.h",
     "policy/reporting/metrics_reporting/network/fake_network_diagnostics_util.cc",
@@ -4902,6 +4904,7 @@
     "//components/policy/proto",
     "//components/prefs",
     "//components/prefs:test_support",
+    "//components/reporting/storage:test_support",
     "//components/session_manager/core",
     "//components/sync/model",
     "//components/sync/protocol",
diff --git a/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.cc b/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.cc
index 34795fc..d6108f1 100644
--- a/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.cc
+++ b/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.cc
@@ -54,6 +54,11 @@
 
 namespace {
 
+bool* DestinationNoSpace() {
+  static bool destination_no_space = false;
+  return &destination_no_space;
+}
+
 // Starts the copy operation via FileSystemOperationRunner.
 storage::FileSystemOperationRunner::OperationID StartCopyOnIOThread(
     scoped_refptr<storage::FileSystemContext> file_system_context,
@@ -186,6 +191,12 @@
   return IsCrossFileSystem(profile, source_url, destination_url);
 }
 
+// static
+void CopyOrMoveIOTaskImpl::SetDestinationNoSpaceForTesting(
+    bool destination_no_space) {
+  *DestinationNoSpace() = destination_no_space;
+}
+
 void CopyOrMoveIOTaskImpl::Execute(IOTask::ProgressCallback progress_callback,
                                    IOTask::CompleteCallback complete_callback) {
   progress_callback_ = std::move(progress_callback);
@@ -403,7 +414,7 @@
     }
   }
 
-  if (required_bytes > free_space) {
+  if (required_bytes > free_space || *DestinationNoSpace()) {
     progress_->outputs.emplace_back(progress_->GetDestinationFolder(),
                                     base::File::FILE_ERROR_NO_SPACE);
     LOG(ERROR) << "Insufficient free space in destination";
diff --git a/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.h b/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.h
index f94009c..0b4e494 100644
--- a/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.h
+++ b/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.h
@@ -101,6 +101,9 @@
       const storage::FileSystemURL& source_url,
       const storage::FileSystemURL& destination_url);
 
+  // Helper function to generate FILE_ERROR_NO_SPACE errors in testing.
+  static void SetDestinationNoSpaceForTesting(bool destination_no_space);
+
  protected:
   // A helper for `GetHookDelegate`.
   bool ShouldSkipEncryptedFiles();
diff --git a/chrome/browser/ash/file_manager/copy_or_move_io_task_policy_impl.cc b/chrome/browser/ash/file_manager/copy_or_move_io_task_policy_impl.cc
index db183792..7c0fcff 100644
--- a/chrome/browser/ash/file_manager/copy_or_move_io_task_policy_impl.cc
+++ b/chrome/browser/ash/file_manager/copy_or_move_io_task_policy_impl.cc
@@ -95,14 +95,20 @@
     Profile* profile,
     scoped_refptr<storage::FileSystemContext> file_system_context,
     ProgressStatus status) {
-  DCHECK_EQ(settings.size(), status.sources.size());
-  DCHECK_EQ(settings.size(), status.outputs.size());
-  std::vector<storage::FileSystemURL> sources(settings.size());
-  std::vector<storage::FileSystemURL> outputs(settings.size());
-  for (size_t i = 0; i < settings.size(); ++i) {
+  // If there was an out-of-space error in the transfer, not all outputs might
+  // be populated as the transfer is aborted on out-of-space errors.
+  // So we truncate the settings, sources and outputs to only the first
+  // `num_good_files` entries.
+  const size_t num_good_files =
+      std::min({settings.size(), status.sources.size(), status.outputs.size()});
+
+  std::vector<storage::FileSystemURL> sources(num_good_files);
+  std::vector<storage::FileSystemURL> outputs(num_good_files);
+  for (size_t i = 0; i < num_good_files; ++i) {
     sources[i] = status.sources[i].url;
     outputs[i] = status.outputs[i].url;
   }
+  settings.resize(num_good_files);
 
   // Notify the Files app of completion of the copy/move.
   std::move(io_task_completion_callback).Run(std::move(status));
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 2badc1e..4ec6c5f7 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -3,8 +3,6 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ash/file_manager/file_manager_browsertest_base.h"
-#include "base/base_paths.h"
-#include "base/memory/raw_ptr.h"
 
 #include <stddef.h>
 
@@ -27,6 +25,7 @@
 #include "ash/style/dark_light_mode_controller_impl.h"
 #include "ash/webui/file_manager/url_constants.h"
 #include "ash/webui/system_apps/public/system_web_app_type.h"
+#include "base/base_paths.h"
 #include "base/containers/circular_deque.h"
 #include "base/containers/contains.h"
 #include "base/files/file_path.h"
@@ -37,6 +36,7 @@
 #include "base/json/json_value_converter.h"
 #include "base/json/json_writer.h"
 #include "base/json/values_util.h"
+#include "base/memory/raw_ptr.h"
 #include "base/no_destructor.h"
 #include "base/notreached.h"
 #include "base/path_service.h"
@@ -75,6 +75,7 @@
 #include "chrome/browser/ash/extensions/file_manager/event_router.h"
 #include "chrome/browser/ash/extensions/file_manager/event_router_factory.h"
 #include "chrome/browser/ash/file_manager/app_id.h"
+#include "chrome/browser/ash/file_manager/copy_or_move_io_task_impl.h"
 #include "chrome/browser/ash/file_manager/file_manager_test_util.h"
 #include "chrome/browser/ash/file_manager/file_tasks.h"
 #include "chrome/browser/ash/file_manager/file_tasks_notifier.h"
@@ -2646,6 +2647,8 @@
   if (error_url_.is_valid()) {
     storage::CopyOrMoveOperationDelegate::SetErrorUrlForTest(nullptr);
   }
+  file_manager::io_task::CopyOrMoveIOTaskImpl::SetDestinationNoSpaceForTesting(
+      false);
 }
 
 void FileManagerBrowserTestBase::TearDown() {
@@ -4018,6 +4021,12 @@
     return;
   }
 
+  if (name == "mockIOTaskDestinationNoSpace") {
+    file_manager::io_task::CopyOrMoveIOTaskImpl::
+        SetDestinationNoSpaceForTesting(true);
+    return;
+  }
+
   if (HandleGuestOsCommands(name, value, output)) {
     return;
   }
diff --git a/chrome/browser/ash/file_manager/file_manager_policy_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_policy_browsertest.cc
index 70e96d6..b5851a7 100644
--- a/chrome/browser/ash/file_manager/file_manager_policy_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_manager_policy_browsertest.cc
@@ -1234,6 +1234,10 @@
         FILE_TRANSFER_TEST_CASE("transferConnectorFromDriveToDownloadsFlat")
             .FileTransferConnectorReportOnlyMode()
             .NewDirectoryTree(),
+        FILE_TRANSFER_TEST_CASE("transferConnectorFromDriveToDownloadsFlatDesti"
+                                "nationNoSpaceForReportOnly")
+            .FileTransferConnectorReportOnlyMode()
+            .NewDirectoryTree(),
         FILE_TRANSFER_TEST_CASE("transferConnectorFromDriveToDownloadsMoveDeep")
             .NewDirectoryTree(),
         FILE_TRANSFER_TEST_CASE("transferConnectorFromDriveToDownloadsMoveDeep")
@@ -1293,6 +1297,9 @@
         FILE_TRANSFER_TEST_CASE("transferConnectorFromDriveToDownloadsFlat"),
         FILE_TRANSFER_TEST_CASE("transferConnectorFromDriveToDownloadsFlat")
             .FileTransferConnectorReportOnlyMode(),
+        FILE_TRANSFER_TEST_CASE("transferConnectorFromDriveToDownloadsFlatDesti"
+                                "nationNoSpaceForReportOnly")
+            .FileTransferConnectorReportOnlyMode(),
         FILE_TRANSFER_TEST_CASE(
             "transferConnectorFromDriveToDownloadsMoveDeep"),
         FILE_TRANSFER_TEST_CASE("transferConnectorFromDriveToDownloadsMoveDeep")
diff --git a/chrome/browser/ash/file_manager/office_file_tasks.cc b/chrome/browser/ash/file_manager/office_file_tasks.cc
index 9ea10b4d..ef4c88e7 100644
--- a/chrome/browser/ash/file_manager/office_file_tasks.cc
+++ b/chrome/browser/ash/file_manager/office_file_tasks.cc
@@ -317,6 +317,8 @@
           ash::cloud_upload::OfficeTaskResult::kCancelledAtFallback,
           std::move(cloud_open_metrics));
     }
+  } else {
+    LOG(ERROR) << "Empty user response";
   }
 }
 
diff --git a/chrome/browser/ash/file_system_provider/extension_provider.cc b/chrome/browser/ash/file_system_provider/extension_provider.cc
index cd4673b..f7d1dac 100644
--- a/chrome/browser/ash/file_system_provider/extension_provider.cc
+++ b/chrome/browser/ash/file_system_provider/extension_provider.cc
@@ -98,7 +98,9 @@
     Profile* profile,
     const ProvidedFileSystemInfo& file_system_info) {
   DCHECK(profile);
-  if (chromeos::features::IsFileSystemProviderContentCacheEnabled()) {
+  // Cache type is only set when `FileSystemProviderContentCache` feature flag
+  // is enabled and the provider is ODFS.
+  if (file_system_info.cache_type() != CacheType::NONE) {
     return std::make_unique<ThrottledFileSystem>(
         std::make_unique<CachedFileSystem>(
             std::make_unique<ProvidedFileSystem>(profile, file_system_info)));
diff --git a/chrome/browser/ash/file_system_provider/provided_file_system_info.cc b/chrome/browser/ash/file_system_provider/provided_file_system_info.cc
index 69e8e26c..0571da7 100644
--- a/chrome/browser/ash/file_system_provider/provided_file_system_info.cc
+++ b/chrome/browser/ash/file_system_provider/provided_file_system_info.cc
@@ -99,7 +99,8 @@
       supports_notify_tag_(false),
       configurable_(false),
       watchable_(false),
-      source_(extensions::SOURCE_FILE) {}
+      source_(extensions::SOURCE_FILE),
+      cache_type_(CacheType::NONE) {}
 
 ProvidedFileSystemInfo::ProvidedFileSystemInfo(
     const ProviderId& provider_id,
@@ -108,7 +109,8 @@
     bool configurable,
     bool watchable,
     extensions::FileSystemProviderSource source,
-    const IconSet& icon_set)
+    const IconSet& icon_set,
+    CacheType cache_type)
     : provider_id_(provider_id),
       file_system_id_(mount_options.file_system_id),
       display_name_(mount_options.display_name),
@@ -119,7 +121,8 @@
       configurable_(configurable),
       watchable_(watchable),
       source_(source),
-      icon_set_(icon_set) {
+      icon_set_(icon_set),
+      cache_type_(cache_type) {
   DCHECK_LE(0, mount_options.opened_files_limit);
 }
 
@@ -130,14 +133,16 @@
     bool configurable,
     bool watchable,
     extensions::FileSystemProviderSource source,
-    const IconSet& icon_set)
+    const IconSet& icon_set,
+    CacheType cache_type)
     : ProvidedFileSystemInfo(ProviderId::CreateFromExtensionId(extension_id),
                              mount_options,
                              mount_path,
                              configurable,
                              watchable,
                              source,
-                             icon_set) {}
+                             icon_set,
+                             cache_type) {}
 
 ProvidedFileSystemInfo::ProvidedFileSystemInfo(
     const ProvidedFileSystemInfo& other) = default;
diff --git a/chrome/browser/ash/file_system_provider/provided_file_system_info.h b/chrome/browser/ash/file_system_provider/provided_file_system_info.h
index 18544b5a..0ab204d 100644
--- a/chrome/browser/ash/file_system_provider/provided_file_system_info.h
+++ b/chrome/browser/ash/file_system_provider/provided_file_system_info.h
@@ -59,6 +59,12 @@
   ProviderType type_;
 };
 
+// The type of content cache that is used for the individual provider.
+// TODO(b/317137739): Move this value to
+// file_system_provider_capabilities_handler.h` once the
+// chrome.fileSystemProvider manifest exposes this value.
+enum class CacheType { LRU, NONE };
+
 // Contains information about the provided file system instance.
 class ProvidedFileSystemInfo {
  public:
@@ -70,7 +76,8 @@
                          bool configurable,
                          bool watchable,
                          extensions::FileSystemProviderSource source,
-                         const IconSet& icon_set);
+                         const IconSet& icon_set,
+                         CacheType cache_type = CacheType::NONE);
 
   // TODO(mtomasz): Remove this constructor. Callers should be using
   // provider id, not extension id.
@@ -80,7 +87,8 @@
                          bool configurable,
                          bool watchable,
                          extensions::FileSystemProviderSource source,
-                         const IconSet& icon_set);
+                         const IconSet& icon_set,
+                         CacheType cache_type = CacheType::NONE);
 
   ProvidedFileSystemInfo(const ProvidedFileSystemInfo& other);
 
@@ -97,6 +105,7 @@
   bool watchable() const { return watchable_; }
   extensions::FileSystemProviderSource source() const { return source_; }
   const IconSet& icon_set() const { return icon_set_; }
+  CacheType cache_type() const { return cache_type_; }
 
  private:
   // ID of the provider supplying this file system.
@@ -136,6 +145,9 @@
 
   // Icon set for the file system.
   IconSet icon_set_;
+
+  // The type of content cache that this file system leverages for eviction.
+  CacheType cache_type_;
 };
 
 }  // namespace ash::file_system_provider
diff --git a/chrome/browser/ash/file_system_provider/service.cc b/chrome/browser/ash/file_system_provider/service.cc
index 23063a0..68b68da0 100644
--- a/chrome/browser/ash/file_system_provider/service.cc
+++ b/chrome/browser/ash/file_system_provider/service.cc
@@ -20,6 +20,8 @@
 #include "chrome/browser/ash/file_system_provider/registry_interface.h"
 #include "chrome/browser/ash/file_system_provider/service_factory.h"
 #include "chrome/browser/ash/file_system_provider/throttled_file_system.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "extensions/browser/extension_registry.h"
@@ -119,6 +121,14 @@
       util::GetMountPath(profile_, provider_id, options.file_system_id);
   const std::string mount_point_name = mount_path.BaseName().AsUTF8Unsafe();
 
+  // The content cache is an experimentation on ODFS behind a feature flag, only
+  // pass it through if those conditions are met.
+  // TODO(b/317137739): This logic should be moved to a capability in the
+  // manifest.json.
+  const bool is_content_cache_enabled_and_odfs =
+      chromeos::features::IsFileSystemProviderContentCacheEnabled() &&
+      provider_id.GetExtensionId() == extension_misc::kODFSExtensionId;
+
   Capabilities capabilities = provider->GetCapabilities();
   // Store the file system descriptor. Use the mount point name as the file
   // system provider file system id.
@@ -133,7 +143,8 @@
   //   source = SOURCE_FILE
   ProvidedFileSystemInfo file_system_info(
       provider_id, options, mount_path, capabilities.configurable,
-      capabilities.watchable, capabilities.source, provider->GetIconSet());
+      capabilities.watchable, capabilities.source, provider->GetIconSet(),
+      is_content_cache_enabled_and_odfs ? CacheType::LRU : CacheType::NONE);
 
   // If already exists a file system provided by the same extension with this
   // id, then abort.
diff --git a/chrome/browser/ash/login/signin/offline_signin_limiter.h b/chrome/browser/ash/login/signin/offline_signin_limiter.h
index b42aca95..529c7fb6 100644
--- a/chrome/browser/ash/login/signin/offline_signin_limiter.h
+++ b/chrome/browser/ash/login/signin/offline_signin_limiter.h
@@ -32,6 +32,9 @@
                              public base::PowerSuspendObserver,
                              public session_manager::SessionManagerObserver {
  public:
+  // `profile` and `clock` must remain valid until Shutdown() is called. If
+  // `clock` is NULL, the shared base::DefaultClock instance will be used.
+  OfflineSigninLimiter(Profile* profile, const base::Clock* clock);
   OfflineSigninLimiter(const OfflineSigninLimiter&) = delete;
   OfflineSigninLimiter& operator=(const OfflineSigninLimiter&) = delete;
   ~OfflineSigninLimiter() override;  // public for testing purpose only.
@@ -54,10 +57,6 @@
   friend class OfflineSigninLimiterFactory;
   friend class OfflineSigninLimiterTest;
 
-  // `profile` and `clock` must remain valid until Shutdown() is called. If
-  // `clock` is NULL, the shared base::DefaultClock instance will be used.
-  OfflineSigninLimiter(Profile* profile, const base::Clock* clock);
-
   // Recalculates the amount of time remaining until online login should be
   // forced and sets the `offline_signin_limit_timer_` accordingly. If the limit
   // has expired already, sets the flag enforcing online login immediately.
diff --git a/chrome/browser/ash/login/signin/offline_signin_limiter_factory.cc b/chrome/browser/ash/login/signin/offline_signin_limiter_factory.cc
index e4fe63d5..ad55fe5 100644
--- a/chrome/browser/ash/login/signin/offline_signin_limiter_factory.cc
+++ b/chrome/browser/ash/login/signin/offline_signin_limiter_factory.cc
@@ -44,10 +44,11 @@
 
 OfflineSigninLimiterFactory::~OfflineSigninLimiterFactory() = default;
 
-KeyedService* OfflineSigninLimiterFactory::BuildServiceInstanceFor(
+std::unique_ptr<KeyedService>
+OfflineSigninLimiterFactory::BuildServiceInstanceForBrowserContext(
     content::BrowserContext* context) const {
-  return new OfflineSigninLimiter(static_cast<Profile*>(context),
-                                  clock_for_testing_);
+  return std::make_unique<OfflineSigninLimiter>(static_cast<Profile*>(context),
+                                                clock_for_testing_);
 }
 
 }  // namespace ash
diff --git a/chrome/browser/ash/login/signin/offline_signin_limiter_factory.h b/chrome/browser/ash/login/signin/offline_signin_limiter_factory.h
index 2ad72e3..5fe4208 100644
--- a/chrome/browser/ash/login/signin/offline_signin_limiter_factory.h
+++ b/chrome/browser/ash/login/signin/offline_signin_limiter_factory.h
@@ -41,7 +41,7 @@
   ~OfflineSigninLimiterFactory() override;
 
   // BrowserContextKeyedServiceFactory:
-  KeyedService* BuildServiceInstanceFor(
+  std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext(
       content::BrowserContext* context) const override;
 
   static base::Clock* clock_for_testing_;
diff --git a/chrome/browser/ash/phonehub/phone_hub_manager_factory.cc b/chrome/browser/ash/phonehub/phone_hub_manager_factory.cc
index c7e65aa..98dc0359 100644
--- a/chrome/browser/ash/phonehub/phone_hub_manager_factory.cc
+++ b/chrome/browser/ash/phonehub/phone_hub_manager_factory.cc
@@ -111,7 +111,8 @@
 
 PhoneHubManagerFactory::~PhoneHubManagerFactory() = default;
 
-KeyedService* PhoneHubManagerFactory::BuildServiceInstanceFor(
+std::unique_ptr<KeyedService>
+PhoneHubManagerFactory::BuildServiceInstanceForBrowserContext(
     content::BrowserContext* context) const {
   if (!features::IsPhoneHubEnabled()) {
     return nullptr;
@@ -149,7 +150,7 @@
     }
   }
 
-  PhoneHubManagerImpl* phone_hub_manager = new PhoneHubManagerImpl(
+  auto phone_hub_manager = std::make_unique<PhoneHubManagerImpl>(
       profile->GetPrefs(),
       device_sync::DeviceSyncClientFactory::GetForProfile(profile),
       multidevice_setup::MultiDeviceSetupClientFactory::GetForProfile(profile),
@@ -176,7 +177,7 @@
 
   // Provide |phone_hub_manager| to the system tray so that it can be used by
   // the UI.
-  SystemTray::Get()->SetPhoneHubManager(phone_hub_manager);
+  SystemTray::Get()->SetPhoneHubManager(phone_hub_manager.get());
 
   DCHECK(!g_context_for_service);
   g_context_for_service = context;
diff --git a/chrome/browser/ash/phonehub/phone_hub_manager_factory.h b/chrome/browser/ash/phonehub/phone_hub_manager_factory.h
index 55b54aa4..44dc515 100644
--- a/chrome/browser/ash/phonehub/phone_hub_manager_factory.h
+++ b/chrome/browser/ash/phonehub/phone_hub_manager_factory.h
@@ -33,7 +33,7 @@
   ~PhoneHubManagerFactory() override;
 
   // BrowserContextKeyedServiceFactory:
-  KeyedService* BuildServiceInstanceFor(
+  std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext(
       content::BrowserContext* context) const override;
   bool ServiceIsNULLWhileTesting() const override;
   bool ServiceIsCreatedWithBrowserContext() const override;
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job.cc
index 7ca4df5..e9aa6b2 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job.cc
@@ -16,6 +16,8 @@
 #include "base/check_deref.h"
 #include "base/check_is_test.h"
 #include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/functional/bind.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
@@ -27,6 +29,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/syslog_logging.h"
 #include "base/task/sequenced_task_runner.h"
+#include "base/task/thread_pool.h"
 #include "base/values.h"
 #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
 #include "chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.h"
@@ -61,6 +64,8 @@
 
 namespace {
 
+static const base::FilePath* g_target_directory_for_testing = nullptr;
+
 // The directory that the support packets will be stored.
 constexpr char kTargetDir[] = "/var/spool/support";
 constexpr char kFilenamePrefix[] = "admin-generated";
@@ -198,8 +203,15 @@
 const char kFetchSupportPacketFailureHistogramName[] =
     "Enterprise.DeviceRemoteCommand.FetchSupportPacket.Failure";
 
-DeviceCommandFetchSupportPacketJob::DeviceCommandFetchSupportPacketJob()
-    : target_dir_(kTargetDir) {}
+// static
+void DeviceCommandFetchSupportPacketJob::SetTargetDirForTesting(
+    const base::FilePath* target_dir) {
+  CHECK_IS_TEST();
+  g_target_directory_for_testing = target_dir;
+}
+
+DeviceCommandFetchSupportPacketJob::DeviceCommandFetchSupportPacketJob() =
+    default;
 
 DeviceCommandFetchSupportPacketJob::~DeviceCommandFetchSupportPacketJob() =
     default;
@@ -212,10 +224,12 @@
   return enterprise_management::RemoteCommand_Type_FETCH_SUPPORT_PACKET;
 }
 
-void DeviceCommandFetchSupportPacketJob::SetReportQueueForTesting(
-    std::unique_ptr<reporting::ReportQueue> report_queue) {
-  CHECK_IS_TEST();
-  report_queue_ = std::move(report_queue);
+const base::FilePath DeviceCommandFetchSupportPacketJob::GetTargetDir() {
+  if (g_target_directory_for_testing) {
+    CHECK_IS_TEST();
+    return *g_target_directory_for_testing;
+  }
+  return base::FilePath(kTargetDir);
 }
 
 bool DeviceCommandFetchSupportPacketJob::ParseCommandPayload(
@@ -310,6 +324,7 @@
                 notes_)));
     return;
   }
+
   StartJobExecution();
 }
 
@@ -368,7 +383,7 @@
   }
 
   base::FilePath target_file = GetFilepathToExport(
-      target_dir_, kFilenamePrefix, support_tool_handler_->GetCaseId(),
+      GetTargetDir(), kFilenamePrefix, support_tool_handler_->GetCaseId(),
       base::Time::Now());
 
   std::set<redaction::PIIType> pii_types =
@@ -407,15 +422,6 @@
 
   exported_path_ = exported_path;
 
-  // No need to create a `report_queue_` if it is already initialized. Since the
-  // DeviceCommandFetchSupportPacketJob instance will be created per command,
-  // `report_queue_` will only be already initialized for tests by
-  // `SetReportQueueForTesting()` function.
-  if (report_queue_) {
-    EnqueueEvent();
-    return;
-  }
-
   ::reporting::SourceInfo source_info;
   source_info.set_source(::reporting::SourceInfo::ASH);
   ::reporting::ReportQueueFactory::Create(
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job.h b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job.h
index ef0e417..4220c9c 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job.h
+++ b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job.h
@@ -9,6 +9,7 @@
 #include <set>
 #include <string>
 
+#include "base/check_is_test.h"
 #include "base/files/file_path.h"
 #include "base/functional/callback_forward.h"
 #include "base/memory/weak_ptr.h"
@@ -72,14 +73,12 @@
   // RemoteCommandJob:
   enterprise_management::RemoteCommand_Type GetType() const override;
 
-  // Convenience functions for testing. `/var/spool/support` path shouldn't be
-  // used in unit tests so it should be replaced.
-  base::FilePath GetExportedFilepathForTesting() { return exported_path_; }
-  void SetTargetDirForTesting(base::FilePath target_dir) {
-    target_dir_ = target_dir;
-  }
-  void SetReportQueueForTesting(
-      std::unique_ptr<reporting::ReportQueue> report_queue);
+  // Convenience function for testing. `/var/spool/support` path can't be
+  // used in unit/browser tests so it should be replaced by a temporary
+  // directory. The caller test is responsible for cleaning this path up after
+  // testing is done and calling `SetTargetDirForTesting(nullptr)` to reset the
+  // target dir.
+  static void SetTargetDirForTesting(const base::FilePath* target_dir);
 
  protected:
   // RemoteCommandJob:
@@ -87,6 +86,10 @@
   bool ParseCommandPayload(const std::string& command_payload) override;
 
  private:
+  // Returns /var/spool/support. A temporary directory that's set by
+  // `SetTargetDirForTesting()` will be used for testing.
+  const base::FilePath GetTargetDir();
+
   // Checks if the command should be enabled. Returns true if the
   // SystemLogEnabled policy is enabled.
   bool IsCommandEnabled() const;
@@ -118,10 +121,8 @@
 
   void OnEventEnqueued(reporting::Status status);
 
-  // The directory to export the generated support packet.
-  base::FilePath target_dir_;
   // The filepath of the exported support packet. It will be a file within
-  // `target_dir_`.
+  // GetTargetDir().
   base::FilePath exported_path_;
   // The details of requested support packet. Contains details like data
   // collectors, PII types, case ID etc.
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_browsertest.cc b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_browsertest.cc
new file mode 100644
index 0000000..1013220
--- /dev/null
+++ b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_browsertest.cc
@@ -0,0 +1,220 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job.h"
+
+#include <memory>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/json/json_writer.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/test_future.h"
+#include "base/test/values_test_util.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/values.h"
+#include "chrome/browser/ash/login/test/login_manager_mixin.h"
+#include "chrome/browser/ash/policy/core/device_policy_cros_browser_test.h"
+#include "chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_test_util.h"
+#include "chrome/browser/ash/policy/test_support/embedded_policy_test_server_mixin.h"
+#include "chrome/browser/ash/policy/test_support/remote_commands_service_mixin.h"
+#include "chrome/browser/policy/messaging_layer/proto/synced/log_upload_event.pb.h"
+#include "chrome/browser/policy/messaging_layer/public/report_client_test_util.h"
+#include "chrome/browser/support_tool/data_collection_module.pb.h"
+#include "chrome/browser/support_tool/support_tool_util.h"
+#include "chrome_device_policy.pb.h"
+#include "chromeos/ash/components/settings/cros_settings_names.h"
+#include "chromeos/ash/components/system/fake_statistics_provider.h"
+#include "components/policy/core/common/remote_commands/test_support/remote_command_builders.h"
+#include "components/policy/proto/device_management_backend.pb.h"
+#include "components/reporting/storage/test_storage_module.h"
+#include "content/public/browser/browser_main_parts.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace em = enterprise_management;
+
+using base::test::IsJson;
+using ::testing::_;
+using ::testing::WithArg;
+
+namespace policy {
+
+namespace {
+
+// Use a number larger than int32 to catch truncation errors.
+const int64_t kInitialCommandId = (1LL << 35) + 1;
+
+class DeviceCommandFetchSupportPacketBrowserTest
+    : public DevicePolicyCrosBrowserTest {
+ protected:
+  void CreatedBrowserMainParts(
+      content::BrowserMainParts* browser_main_parts) override {
+    DevicePolicyCrosBrowserTest::CreatedBrowserMainParts(browser_main_parts);
+    // Reporting test environment needs to be created before the browser
+    // creation is completed.
+    reporting_test_storage_ =
+        base::MakeRefCounted<reporting::test::TestStorageModule>();
+
+    reporting_test_enviroment_ =
+        reporting::ReportingClient::TestEnvironment::CreateWithStorageModule(
+            reporting_test_storage_);
+  }
+
+  void SetUpInProcessBrowserTestFixture() override {
+    DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
+
+    remote_commands_service_mixin_.SetCurrentIdForTesting(kInitialCommandId);
+
+    // Set serial number for testing.
+    statistics_provider_.SetMachineStatistic("serial_number", "000000");
+    ash::system::StatisticsProvider::SetTestProvider(&statistics_provider_);
+
+    {
+      base::ScopedAllowBlockingForTesting allow_blocking;
+      ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
+      target_dir_ = scoped_temp_dir_.GetPath();
+    }
+
+    DeviceCommandFetchSupportPacketJob::SetTargetDirForTesting(&target_dir_);
+  }
+
+  void TearDownInProcessBrowserTestFixture() override {
+    DevicePolicyCrosBrowserTest::TearDownInProcessBrowserTestFixture();
+    DeviceCommandFetchSupportPacketJob::SetTargetDirForTesting(nullptr);
+  }
+
+  int64_t WaitForCommandExecution(
+      const enterprise_management::RemoteCommand& command) {
+    int64_t command_id =
+        remote_commands_service_mixin_.AddPendingRemoteCommand(command);
+    remote_commands_service_mixin_.SendDeviceRemoteCommandsRequest();
+    remote_commands_service_mixin_.WaitForAcked(command_id);
+    return command_id;
+  }
+
+  enterprise_management::RemoteCommandResult WaitForCommandResult(
+      const enterprise_management::RemoteCommand& command) {
+    return remote_commands_service_mixin_.SendRemoteCommand(command);
+  }
+
+  void SetLogUploadEnabledPolicy(bool enabled) {
+    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+    proto.mutable_device_log_upload_settings()->set_system_log_upload_enabled(
+        enabled);
+    policy_helper()->RefreshPolicyAndWaitUntilDeviceSettingsUpdated(
+        {ash::kSystemLogUploadEnabled});
+    policy_test_server_mixin_.UpdateDevicePolicy(proto);
+  }
+
+  const base::HistogramTester& histogram_tester() { return histogram_tester_; }
+  scoped_refptr<reporting::test::TestStorageModule> reporting_storage() {
+    return reporting_test_storage_;
+  }
+  const base::FilePath& target_dir() { return target_dir_; }
+
+ private:
+  scoped_refptr<reporting::test::TestStorageModule> reporting_test_storage_;
+  std::unique_ptr<reporting::ReportingClient::TestEnvironment>
+      reporting_test_enviroment_;
+
+  ash::system::FakeStatisticsProvider statistics_provider_;
+  base::HistogramTester histogram_tester_;
+
+  base::ScopedTempDir scoped_temp_dir_;
+  base::FilePath target_dir_;
+
+  ash::LoginManagerMixin login_manager_mixin_{&mixin_host_, {}};
+  ash::EmbeddedPolicyTestServerMixin policy_test_server_mixin_{&mixin_host_};
+  RemoteCommandsServiceMixin remote_commands_service_mixin_{
+      mixin_host_, policy_test_server_mixin_};
+};
+
+}  // namespace
+
+// TODO: b/313072234 - Add tests for different session types. For now, we only
+// test on login screen (without any session).
+IN_PROC_BROWSER_TEST_F(DeviceCommandFetchSupportPacketBrowserTest, Success) {
+  SetLogUploadEnabledPolicy(true);
+  base::test::TestFuture<ash::reporting::LogUploadEvent>
+      log_upload_event_future;
+  test::CaptureUpcomingLogUploadEventOnReportingStorage(
+      reporting_storage(), log_upload_event_future.GetRepeatingCallback());
+  auto payload = base::WriteJson(test::GetFetchSupportPacketCommandPayloadDict(
+      GetAllAvailableDataCollectorsOnDevice()));
+  ASSERT_TRUE(payload.has_value());
+  int64_t command_id = WaitForCommandExecution(
+      RemoteCommandBuilder()
+          .SetType(em::RemoteCommand::FETCH_SUPPORT_PACKET)
+          .SetPayload(payload.value())
+          .Build());
+
+  ash::reporting::LogUploadEvent event = log_upload_event_future.Take();
+  EXPECT_TRUE(event.mutable_upload_settings()->has_origin_path());
+  base::FilePath exported_file(event.mutable_upload_settings()->origin_path());
+  // Ensure that the resulting `exported_file` exist under target directory.
+  EXPECT_EQ(exported_file.DirName(), target_dir());
+  EXPECT_TRUE(event.has_command_id());
+  EXPECT_EQ(event.command_id(), command_id);
+
+  std::string expected_upload_parameters = test::GetExpectedUploadParameters(
+      command_id, exported_file.BaseName().value());
+  EXPECT_EQ(expected_upload_parameters,
+            *event.mutable_upload_settings()->mutable_upload_parameters());
+
+  // The result payload should contain the success result code.
+  base::Value::Dict expected_payload;
+  expected_payload.Set("result",
+                       enterprise_management::FetchSupportPacketResultCode::
+                           FETCH_SUPPORT_PACKET_RESULT_SUCCESS);
+  EXPECT_THAT(event.command_result_payload(),
+              IsJson(std::move(expected_payload)));
+
+  // Check contents of the resulting file.
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking_for_test;
+    int64_t file_size;
+    ASSERT_TRUE(base::GetFileSize(exported_file, &file_size));
+    EXPECT_GT(file_size, 0);
+  }
+
+  histogram_tester().ExpectUniqueSample(
+      kFetchSupportPacketFailureHistogramName,
+      EnterpriseFetchSupportPacketFailureType::kNoFailure, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(DeviceCommandFetchSupportPacketBrowserTest,
+                       FailWhenLogUploadDisabled) {
+  SetLogUploadEnabledPolicy(false);
+  auto payload = base::WriteJson(test::GetFetchSupportPacketCommandPayloadDict(
+      GetAllAvailableDataCollectorsOnDevice()));
+  ASSERT_TRUE(payload.has_value());
+  enterprise_management::RemoteCommandResult result =
+      WaitForCommandResult(RemoteCommandBuilder()
+                               .SetType(em::RemoteCommand::FETCH_SUPPORT_PACKET)
+                               .SetPayload(payload.value())
+                               .Build());
+  EXPECT_EQ(result.result(),
+            enterprise_management::RemoteCommandResult_ResultType::
+                RemoteCommandResult_ResultType_RESULT_FAILURE);
+  // Expect result payload when the command fails because of not being
+  // supported on the device.
+  EXPECT_THAT(
+      result.payload(),
+      IsJson(base::Value::Dict().Set(
+          "result", enterprise_management::FetchSupportPacketResultCode::
+                        FAILURE_COMMAND_NOT_ENABLED)));
+
+  histogram_tester().ExpectUniqueSample(
+      kFetchSupportPacketFailureHistogramName,
+      EnterpriseFetchSupportPacketFailureType::
+          kFailedOnCommandEnabledForUserCheck,
+      1);
+}
+
+}  // namespace policy
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_test_util.cc b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_test_util.cc
new file mode 100644
index 0000000..f2e1df2
--- /dev/null
+++ b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_test_util.cc
@@ -0,0 +1,76 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_test_util.h"
+
+#include <algorithm>
+#include <memory>
+#include <vector>
+
+#include "base/functional/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/strings/stringprintf.h"
+#include "base/task/bind_post_task.h"
+#include "base/values.h"
+#include "chrome/browser/policy/messaging_layer/proto/synced/log_upload_event.pb.h"
+#include "chrome/browser/support_tool/data_collection_module.pb.h"
+#include "components/reporting/storage/test_storage_module.h"
+
+namespace policy::test {
+
+base::Value::Dict GetFetchSupportPacketCommandPayloadDict(
+    const std::vector<support_tool::DataCollectorType>& data_collectors) {
+  base::Value::Dict support_packet_details;
+  support_packet_details.Set("issueCaseId", "issue_case_id");
+  support_packet_details.Set("issueDescription", "issue description");
+  support_packet_details.Set("requesterMetadata", "obfuscated123");
+  base::Value::List data_collectors_list;
+  for (const auto& data_collector : data_collectors) {
+    data_collectors_list.Append(data_collector);
+  }
+  support_packet_details.Set("requestedDataCollectors",
+                             std::move(data_collectors_list));
+  support_packet_details.Set("requestedPiiTypes", base::Value::List());
+  return base::Value::Dict().Set("supportPacketDetails",
+                                 std::move(support_packet_details));
+}
+
+void CaptureUpcomingLogUploadEventOnReportingStorage(
+    scoped_refptr<reporting::test::TestStorageModule> reporting_storage,
+    base::RepeatingCallback<void(ash::reporting::LogUploadEvent)>
+        event_callback) {
+  // We bind `event_callback` to current task because `AddRecord()` is posted on
+  // ThreadPool and `event_callback` will be triggered from there.
+  event_callback = base::BindPostTaskToCurrentDefault(event_callback);
+  EXPECT_CALL(*reporting_storage,
+              AddRecord(testing::Eq(reporting::Priority::SLOW_BATCH),
+                        testing::ResultOf(
+                            [](const reporting::Record& record) {
+                              return record.destination();
+                            },
+                            testing::Eq(reporting::Destination::LOG_UPLOAD)),
+                        testing::_))
+      .WillOnce(
+          [event_callback](
+              reporting::Priority priority, reporting::Record record,
+              reporting::StorageModuleInterface::EnqueueCallback callback) {
+            EXPECT_TRUE(record.needs_local_unencrypted_copy());
+            ash::reporting::LogUploadEvent upcoming_event;
+            EXPECT_TRUE(upcoming_event.ParseFromArray(record.data().data(),
+                                                      record.data().size()));
+            std::move(event_callback).Run(std::move(upcoming_event));
+            std::move(callback).Run(reporting::Status::StatusOK());
+          });
+}
+
+std::string GetExpectedUploadParameters(int64_t command_id,
+                                        const std::string& exported_filepath) {
+  constexpr char kExpectedUploadParametersFormatter[] =
+      R"({"Command-ID":"%ld","File-Type":"support_file","Filename":"%s"}
+application/json)";
+  return base::StringPrintf(kExpectedUploadParametersFormatter, command_id,
+                            exported_filepath.c_str());
+}
+
+}  // namespace policy::test
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_test_util.h b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_test_util.h
new file mode 100644
index 0000000..9b0395b1
--- /dev/null
+++ b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_test_util.h
@@ -0,0 +1,53 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_POLICY_REMOTE_COMMANDS_DEVICE_COMMAND_FETCH_SUPPORT_PACKET_JOB_TEST_UTIL_H_
+#define CHROME_BROWSER_ASH_POLICY_REMOTE_COMMANDS_DEVICE_COMMAND_FETCH_SUPPORT_PACKET_JOB_TEST_UTIL_H_
+
+#include <vector>
+
+#include "base/functional/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/values.h"
+#include "chrome/browser/policy/messaging_layer/proto/synced/log_upload_event.pb.h"
+#include "chrome/browser/support_tool/data_collection_module.pb.h"
+#include "components/reporting/storage/test_storage_module.h"
+
+namespace policy::test {
+
+// Return a valid command payload with given data collectors requested.
+// The returned payload doesn't contain any PII request. The returned payload
+// will be as following.
+// {"supportPacketDetails":{
+//     "issueCaseId": "issue_case_id",
+//     "issueDescription": "issue description",
+//     "requestedDataCollectors": [<requested data collectors>],
+//     "requestedPiiTypes": [],
+//     "requesterMetadata": "obfuscated123"
+//   }
+// }
+base::Value::Dict GetFetchSupportPacketCommandPayloadDict(
+    const std::vector<support_tool::DataCollectorType>& data_collectors);
+
+// Captures the next uploaded LogUploadEvent on the `reporting_storage` and
+// returns it to `event_callback`. Sets an expectancy that a LogUploadEvent will
+// be enqueued to `reporting_storage` and fails the test if it does now.
+void CaptureUpcomingLogUploadEventOnReportingStorage(
+    scoped_refptr<reporting::test::TestStorageModule> reporting_storage,
+    base::RepeatingCallback<void(ash::reporting::LogUploadEvent)>
+        event_callback);
+
+// Returns the expected upload_parameters field of a LogUploadEvent for the
+// given values. The expected upload_paramaters will be in following format:
+//  {
+//     "Command-ID":"<command ID>",
+//     "File-Type":"support_file",
+//     "Filename":"<the filepath for the generated log file>"}
+// application/json
+std::string GetExpectedUploadParameters(int64_t command_id,
+                                        const std::string& exported_filepath);
+
+}  // namespace policy::test
+
+#endif  // CHROME_BROWSER_ASH_POLICY_REMOTE_COMMANDS_DEVICE_COMMAND_FETCH_SUPPORT_PACKET_JOB_TEST_UTIL_H_
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_unittest.cc
index c7231b6..8536443 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_unittest.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_unittest.cc
@@ -12,20 +12,24 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/json/json_writer.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_future.h"
 #include "base/test/values_test_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h"
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
+#include "chrome/browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_test_util.h"
 #include "chrome/browser/ash/policy/remote_commands/user_session_type_test_util.h"
 #include "chrome/browser/ash/settings/device_settings_test_helper.h"
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
 #include "chrome/browser/policy/messaging_layer/proto/synced/log_upload_event.pb.h"
+#include "chrome/browser/policy/messaging_layer/public/report_client_test_util.h"
 #include "chrome/browser/support_tool/data_collection_module.pb.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
@@ -35,12 +39,16 @@
 #include "chromeos/ash/components/system/statistics_provider.h"
 #include "components/feedback/redaction_tool/pii_types.h"
 #include "components/policy/proto/device_management_backend.pb.h"
-#include "components/reporting/client/mock_report_queue.h"
+#include "components/reporting/storage/storage_module_interface.h"
+#include "components/reporting/storage/test_storage_module.h"
 #include "components/reporting/util/status.h"
+#include "record.pb.h"
+#include "record_constants.pb.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::test::IsJson;
+using ::testing::_;
 using ::testing::WithArg;
 
 namespace policy {
@@ -73,36 +81,6 @@
 // The age of command in milliseconds.
 constexpr int64 kCommandAge = 60000;
 
-constexpr char kExpectedUploadParametersFormatter[] =
-    R"({"Command-ID":"%ld","File-Type":"support_file","Filename":"%s"}
-application/json)";
-
-// Return a valid command payload with at least one data collector requested.
-// The returned payload doesn't contain any PII request. The returned payload
-// will be as following.
-// {"supportPacketDetails":{
-//     "issueCaseId": "issue_case_id",
-//     "issueDescription": "issue description",
-//     "requestedDataCollectors":
-//     [support_tool::DataCollectorType::CHROMEOS_SYSTEM_LOGS(17)],
-//     "requestedPiiTypes": [],
-//     "requesterMetadata": "obfuscated123"
-//   }
-// }
-base::Value::Dict GetCommandPayloadDict() {
-  base::Value::Dict support_packet_details;
-  support_packet_details.Set("issueCaseId", "issue_case_id");
-  support_packet_details.Set("issueDescription", "issue description");
-  support_packet_details.Set("requesterMetadata", "obfuscated123");
-  support_packet_details.Set(
-      "requestedDataCollectors",
-      base::Value::List().Append(
-          support_tool::DataCollectorType::CHROMEOS_SYSTEM_LOGS));
-  support_packet_details.Set("requestedPiiTypes", base::Value::List());
-  return base::Value::Dict().Set("supportPacketDetails",
-                                 std::move(support_packet_details));
-}
-
 em::RemoteCommand GenerateCommandProto(std::string payload) {
   em::RemoteCommand command_proto;
   command_proto.set_type(em::RemoteCommand_Type_FETCH_SUPPORT_PACKET);
@@ -112,8 +90,6 @@
   return command_proto;
 }
 
-}  // namespace
-
 class DeviceCommandFetchSupportPacketTest : public ash::DeviceSettingsTestBase {
  public:
   DeviceCommandFetchSupportPacketTest()
@@ -128,7 +104,13 @@
   void SetUp() override {
     DeviceSettingsTestBase::SetUp();
     ASSERT_TRUE(profile_manager_.SetUp());
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+    reporting_test_storage_ =
+        base::MakeRefCounted<reporting::test::TestStorageModule>();
+    reporting_test_enviroment_ =
+        reporting::ReportingClient::TestEnvironment::CreateWithStorageModule(
+            reporting_test_storage_);
+
     ash::DebugDaemonClient::InitializeFake();
     // Set serial number for testing.
     statistics_provider_.SetMachineStatistic("serial_number", "000000");
@@ -138,18 +120,24 @@
     arc_kiosk_app_manager_ = std::make_unique<ash::ArcKioskAppManager>();
     web_kiosk_app_manager_ = std::make_unique<ash::WebKioskAppManager>();
     kiosk_chrome_app_manager_ = std::make_unique<ash::KioskChromeAppManager>();
+
+    {
+      base::ScopedAllowBlockingForTesting allow_blocking;
+      ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+      target_dir_ = temp_dir_.GetPath();
+    }
+
+    DeviceCommandFetchSupportPacketJob::SetTargetDirForTesting(&target_dir_);
   }
 
   void TearDown() override {
+    DeviceCommandFetchSupportPacketJob::SetTargetDirForTesting(nullptr);
+
     kiosk_chrome_app_manager_.reset();
     web_kiosk_app_manager_.reset();
     arc_kiosk_app_manager_.reset();
 
     ash::DebugDaemonClient::Shutdown();
-    if (!temp_dir_.IsValid()) {
-      return;
-    }
-    EXPECT_TRUE(temp_dir_.Delete());
     DeviceSettingsTestBase::TearDown();
   }
 
@@ -174,51 +162,48 @@
     ASSERT_TRUE(job_finished_future.Wait()) << "Job did not finish.";
   }
 
-  // TODO(b/313897897): We can directly use FakeReportQueue instead.
-  void CaptureUpcomingEventOnReportQueue(
-      DeviceCommandFetchSupportPacketJob& in_job,
-      ash::reporting::LogUploadEvent& upcoming_event) {
-    std::unique_ptr<reporting::MockReportQueueStrict> mock_report_queue =
-        std::make_unique<reporting::MockReportQueueStrict>();
-    EXPECT_CALL(*mock_report_queue.get(), AddRecord)
-        .WillOnce(testing::WithArgs<0, 2>(
-            [&upcoming_event](
-                std::string serialized_record,
-                reporting::ReportQueue::EnqueueCallback callback) {
-              // Parse the enqueued event from serialized record proto.
-              ASSERT_TRUE(upcoming_event.ParseFromString(serialized_record));
-              std::move(callback).Run(reporting::Status::StatusOK());
-            }));
-    in_job.SetReportQueueForTesting(std::move(mock_report_queue));
-  }
-
  protected:
   // App manager instances for testing kiosk sessions.
   std::unique_ptr<ash::ArcKioskAppManager> arc_kiosk_app_manager_;
   std::unique_ptr<ash::WebKioskAppManager> web_kiosk_app_manager_;
   std::unique_ptr<ash::KioskChromeAppManager> kiosk_chrome_app_manager_;
 
+  scoped_refptr<reporting::test::TestStorageModule> reporting_test_storage_;
+  std::unique_ptr<reporting::ReportingClient::TestEnvironment>
+      reporting_test_enviroment_;
+
   ash::system::FakeStatisticsProvider statistics_provider_;
   ash::ScopedCrosSettingsTestHelper cros_settings_helper_;
-  base::ScopedTempDir temp_dir_;
   base::HistogramTester histogram_tester_;
   TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal()};
+  base::FilePath target_dir_;
+  base::ScopedTempDir temp_dir_;
 };
 
+// Fixture for tests parameterized over the possible user session
+// types(`TestSessionType`) and PII policies.
+class DeviceCommandFetchSupportPacketTestParameterized
+    : public DeviceCommandFetchSupportPacketTest,
+      public ::testing::WithParamInterface<SessionInfo> {};
+
+}  // namespace
+
 TEST_F(DeviceCommandFetchSupportPacketTest,
        FailIfPayloadContainsEmptyDataCollectors) {
   DeviceCommandFetchSupportPacketJob job;
   // Wrong payload with empty data collectors list.
-  base::Value::Dict command_payload = GetCommandPayloadDict();
+  base::Value::Dict command_payload =
+      test::GetFetchSupportPacketCommandPayloadDict(
+          {support_tool::DataCollectorType::CHROMEOS_SYSTEM_LOGS});
   command_payload.SetByDottedPath(
       "supportPacketDetails.requestedDataCollectors", base::Value::List());
-  std::string wrong_payload;
-  ASSERT_TRUE(
-      base::JSONWriter::Write(std::move(command_payload), &wrong_payload));
+  auto wrong_payload = base::WriteJson(std::move(command_payload));
+  ASSERT_TRUE(wrong_payload.has_value());
 
   // Shouldn't be able to initialize with wrong payload.
   EXPECT_FALSE(job.Init(base::TimeTicks::Now(),
-                        GenerateCommandProto(wrong_payload), em::SignedData()));
+                        GenerateCommandProto(wrong_payload.value()),
+                        em::SignedData()));
   histogram_tester_.ExpectUniqueSample(
       kFetchSupportPacketFailureHistogramName,
       EnterpriseFetchSupportPacketFailureType::kFailedOnWrongCommandPayload, 1);
@@ -230,13 +215,11 @@
 
   DeviceCommandFetchSupportPacketJob job;
 
-  job.SetTargetDirForTesting(temp_dir_.GetPath());
+  auto payload = base::WriteJson(test::GetFetchSupportPacketCommandPayloadDict(
+      {support_tool::DataCollectorType::CHROMEOS_SYSTEM_LOGS}));
+  ASSERT_TRUE(payload.has_value());
 
-  std::string payload;
-  ASSERT_TRUE(
-      base::JSONWriter::Write(std::move(GetCommandPayloadDict()), &payload));
-
-  InitAndRunCommandJob(job, GenerateCommandProto(payload));
+  InitAndRunCommandJob(job, GenerateCommandProto(payload.value()));
 
   EXPECT_EQ(job.status(), RemoteCommandJob::FAILED);
   // Expect result payload when the command fails because of not being
@@ -253,12 +236,6 @@
                                        1);
 }
 
-// Fixture for tests parameterized over the possible user session
-// types(`TestSessionType`) and PII policies.
-class DeviceCommandFetchSupportPacketTestParameterized
-    : public DeviceCommandFetchSupportPacketTest,
-      public ::testing::WithParamInterface<SessionInfo> {};
-
 TEST_P(DeviceCommandFetchSupportPacketTestParameterized,
        SuccessfulCommandRequestWithoutPii) {
   const SessionInfo& session_info = GetParam();
@@ -267,31 +244,33 @@
 
   DeviceCommandFetchSupportPacketJob job;
 
-  job.SetTargetDirForTesting(temp_dir_.GetPath());
+  base::test::TestFuture<ash::reporting::LogUploadEvent>
+      log_upload_event_future;
+  test::CaptureUpcomingLogUploadEventOnReportingStorage(
+      reporting_test_storage_, log_upload_event_future.GetRepeatingCallback());
 
-  ash::reporting::LogUploadEvent enqueued_event;
-  CaptureUpcomingEventOnReportQueue(job, enqueued_event);
-
-  std::string payload;
-  ASSERT_TRUE(
-      base::JSONWriter::Write(std::move(GetCommandPayloadDict()), &payload));
-  InitAndRunCommandJob(job, GenerateCommandProto(payload));
+  auto payload = base::WriteJson(test::GetFetchSupportPacketCommandPayloadDict(
+      {support_tool::DataCollectorType::CHROMEOS_SYSTEM_LOGS}));
+  ASSERT_TRUE(payload.has_value());
+  InitAndRunCommandJob(job, GenerateCommandProto(payload.value()));
 
   EXPECT_EQ(job.status(), RemoteCommandJob::ACKED);
 
-  base::FilePath exported_file = job.GetExportedFilepathForTesting();
-
+  ash::reporting::LogUploadEvent enqueued_event =
+      log_upload_event_future.Take();
+  EXPECT_TRUE(enqueued_event.mutable_upload_settings()->has_origin_path());
+  base::FilePath exported_file(
+      enqueued_event.mutable_upload_settings()->origin_path());
+  // Ensure that the resulting `exported_file` exist under target directory.
+  EXPECT_EQ(exported_file.DirName(), target_dir_);
+  EXPECT_TRUE(enqueued_event.has_command_id());
+  EXPECT_EQ(enqueued_event.command_id(), kUniqueID);
   // Check the contents of LogUploadEvent that the job enqueued.
-  std::string expected_upload_parameters =
-      base::StringPrintf(kExpectedUploadParametersFormatter, kUniqueID,
-                         exported_file.BaseName().value().c_str());
+  std::string expected_upload_parameters = test::GetExpectedUploadParameters(
+      kUniqueID, exported_file.BaseName().value());
   EXPECT_EQ(
       expected_upload_parameters,
       *enqueued_event.mutable_upload_settings()->mutable_upload_parameters());
-  EXPECT_EQ(exported_file.value(),
-            *enqueued_event.mutable_upload_settings()->mutable_origin_path());
-  EXPECT_TRUE(enqueued_event.has_command_id());
-  EXPECT_EQ(enqueued_event.command_id(), kUniqueID);
   // The result payload should contain the success result code.
   EXPECT_THAT(
       enqueued_event.command_result_payload(),
@@ -299,9 +278,12 @@
           "result", enterprise_management::FetchSupportPacketResultCode::
                         FETCH_SUPPORT_PACKET_RESULT_SUCCESS)));
 
-  int64_t file_size;
-  ASSERT_TRUE(base::GetFileSize(exported_file, &file_size));
-  EXPECT_GT(file_size, 0);
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking_for_test;
+    int64_t file_size;
+    ASSERT_TRUE(base::GetFileSize(exported_file, &file_size));
+    EXPECT_GT(file_size, 0);
+  }
 
   histogram_tester_.ExpectUniqueSample(
       kFetchSupportPacketFailureHistogramName,
@@ -316,36 +298,40 @@
 
   DeviceCommandFetchSupportPacketJob job;
 
-  job.SetTargetDirForTesting(temp_dir_.GetPath());
-
-  ash::reporting::LogUploadEvent enqueued_event;
-  CaptureUpcomingEventOnReportQueue(job, enqueued_event);
+  base::test::TestFuture<ash::reporting::LogUploadEvent>
+      log_upload_event_future;
+  test::CaptureUpcomingLogUploadEventOnReportingStorage(
+      reporting_test_storage_, log_upload_event_future.GetRepeatingCallback());
 
   // Add a requested PII type to the command payload.
-  base::Value::Dict command_payload_dict = GetCommandPayloadDict();
+  base::Value::Dict command_payload_dict =
+      test::GetFetchSupportPacketCommandPayloadDict(
+          {support_tool::DataCollectorType::CHROMEOS_SYSTEM_LOGS});
   command_payload_dict.SetByDottedPath(
       "supportPacketDetails.requestedPiiTypes",
       base::Value::List().Append(support_tool::PiiType::EMAIL));
-  std::string payload;
-  ASSERT_TRUE(
-      base::JSONWriter::Write(std::move(command_payload_dict), &payload));
-  InitAndRunCommandJob(job, GenerateCommandProto(payload));
+  auto payload = base::WriteJson(std::move(command_payload_dict));
+  ASSERT_TRUE(payload.has_value());
+  InitAndRunCommandJob(job, GenerateCommandProto(payload.value()));
 
   EXPECT_EQ(job.status(), RemoteCommandJob::ACKED);
 
-  base::FilePath exported_file = job.GetExportedFilepathForTesting();
-
+  ash::reporting::LogUploadEvent enqueued_event =
+      log_upload_event_future.Take();
+  EXPECT_TRUE(enqueued_event.mutable_upload_settings()->has_origin_path());
+  base::FilePath exported_file(
+      enqueued_event.mutable_upload_settings()->origin_path());
+  // Ensure that the resulting `exported_file` exist under target directory.
+  EXPECT_EQ(exported_file.DirName(), target_dir_);
+  EXPECT_TRUE(enqueued_event.has_command_id());
+  EXPECT_EQ(enqueued_event.command_id(), kUniqueID);
   // Check the contents of LogUploadEvent that the job enqueued.
-  std::string expected_upload_parameters =
-      base::StringPrintf(kExpectedUploadParametersFormatter, kUniqueID,
-                         exported_file.BaseName().value().c_str());
+  std::string expected_upload_parameters = test::GetExpectedUploadParameters(
+      kUniqueID, exported_file.BaseName().value());
   EXPECT_EQ(
       expected_upload_parameters,
       *enqueued_event.mutable_upload_settings()->mutable_upload_parameters());
-  EXPECT_EQ(exported_file.value(),
-            *enqueued_event.mutable_upload_settings()->mutable_origin_path());
-  EXPECT_TRUE(enqueued_event.has_command_id());
-  EXPECT_EQ(enqueued_event.command_id(), kUniqueID);
+
   // The result payload should contain the success result code.
   base::Value::Dict expected_payload;
   expected_payload.Set("result",
@@ -362,9 +348,12 @@
   EXPECT_THAT(enqueued_event.command_result_payload(),
               IsJson(std::move(expected_payload)));
 
-  int64_t file_size;
-  ASSERT_TRUE(base::GetFileSize(exported_file, &file_size));
-  EXPECT_GT(file_size, 0);
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking_for_test;
+    int64_t file_size;
+    ASSERT_TRUE(base::GetFileSize(exported_file, &file_size));
+    EXPECT_GT(file_size, 0);
+  }
 
   histogram_tester_.ExpectUniqueSample(
       kFetchSupportPacketFailureHistogramName,
diff --git a/chrome/browser/ash/release_notes/release_notes_storage.cc b/chrome/browser/ash/release_notes/release_notes_storage.cc
index 16171828..9a633f2 100644
--- a/chrome/browser/ash/release_notes/release_notes_storage.cc
+++ b/chrome/browser/ash/release_notes/release_notes_storage.cc
@@ -28,7 +28,7 @@
 // This stores the latest milestone with new Release Notes content. If the last
 // milestone the user has seen the notification is before this, a new
 // notification will be shown.
-constexpr int kLastChromeVersionWithReleaseNotes = 119;
+constexpr int kLastChromeVersionWithReleaseNotes = 122;
 constexpr int kTimesToShowSuggestionChip = 3;
 
 int GetMilestone() {
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index badb2fcb..2ab4e7b 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/dom_distiller/dom_distiller_service_factory.h"
 #include "chrome/browser/history_clusters/history_clusters_service_factory.h"
 #include "chrome/browser/media/media_engagement_score_details.mojom.h"
+#include "chrome/browser/model_execution/model_manager_impl.h"
 #include "chrome/browser/navigation_predictor/navigation_predictor.h"
 #include "chrome/browser/optimization_guide/optimization_guide_internals_ui.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
@@ -1035,6 +1036,11 @@
   map->Add<blink::mojom::WebPrintingService>(
       base::BindRepeating(&printing::CreateWebPrintingServiceForFrame));
 #endif
+
+  if (base::FeatureList::IsEnabled(blink::features::kEnableModelExecutionAPI)) {
+    map->Add<blink::mojom::ModelManager>(
+        base::BindRepeating(&ModelManagerImpl::Create));
+  }
 }
 
 void PopulateChromeWebUIFrameBinders(
diff --git a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc
index b016e37..f5118235 100644
--- a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc
+++ b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc
@@ -412,12 +412,7 @@
 
   associated_registry.AddInterface<autofill::mojom::AutofillDriver>(
       base::BindRepeating(
-          [](content::RenderFrameHost* render_frame_host,
-             mojo::PendingAssociatedReceiver<autofill::mojom::AutofillDriver>
-                 receiver) {
-            autofill::ContentAutofillDriverFactory::BindAutofillDriver(
-                std::move(receiver), render_frame_host);
-          },
+          &autofill::ContentAutofillDriverFactory::BindAutofillDriver,
           &render_frame_host));
   associated_registry.AddInterface<autofill::mojom::PasswordGenerationDriver>(
       base::BindRepeating(
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 59224f9..396eae0 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -445,6 +445,16 @@
     "expiry_milestone": 110
   },
   {
+    "name": "ash-picker",
+    "owners": [ "shend@chromium.org", "e14s-eng@google.com" ],
+    "expiry_milestone": 131
+  },
+  {
+    "name": "ash-picker-feature-key",
+    "owners": [ "shend@chromium.org", "e14s-eng@google.com" ],
+    "expiry_milestone": 131
+  },
+  {
     "name": "ash-snap-groups",
     "owners": [ "michelefan@chromium.org", "sophiewen@chromium.org", "xdai@chromium.org" ],
     "expiry_milestone": 129
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 17bcb96..dd9e5d8 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -5604,6 +5604,13 @@
     "Enable unified desktop mode which allows a window to span multiple "
     "displays.";
 
+const char kAshPickerName[] = "Picker feature";
+const char kAshPickerDescription[] = "Enable new Picker feature on ChromeOS.";
+
+const char kAshPickerFeatureKeyName[] = "Feature key for Picker feature";
+const char kAshPickerFeatureKeyDescription[] =
+    "Feature key to use the new Picker feature on ChromeOS.";
+
 const char kAsynchronousScannerDiscoveryName[] =
     "Asynchronous scanner discovery";
 const char kAsynchronousScannerDiscoveryDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 7883258..91787037 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -3231,6 +3231,12 @@
 extern const char kAshEnableUnifiedDesktopName[];
 extern const char kAshEnableUnifiedDesktopDescription[];
 
+extern const char kAshPickerName[];
+extern const char kAshPickerDescription[];
+
+extern const char kAshPickerFeatureKeyName[];
+extern const char kAshPickerFeatureKeyDescription[];
+
 extern const char kAsynchronousScannerDiscoveryName[];
 extern const char kAsynchronousScannerDiscoveryDescription[];
 
diff --git a/chrome/browser/model_execution/OWNERS b/chrome/browser/model_execution/OWNERS
new file mode 100644
index 0000000..3e62e11f
--- /dev/null
+++ b/chrome/browser/model_execution/OWNERS
@@ -0,0 +1,4 @@
+fergal@chromium.org
+leimy@chromium.org
+cduvall@chromium.org
+sophiechang@chromium.org
diff --git a/chrome/browser/model_execution/model_execution_session.cc b/chrome/browser/model_execution/model_execution_session.cc
new file mode 100644
index 0000000..bfb8a425
--- /dev/null
+++ b/chrome/browser/model_execution/model_execution_session.cc
@@ -0,0 +1,66 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/model_execution/model_execution_session.h"
+
+#include <optional>
+
+#include "base/functional/bind.h"
+#include "components/optimization_guide/core/optimization_guide_util.h"
+#include "components/optimization_guide/proto/common_types.pb.h"
+#include "components/optimization_guide/proto/string_value.pb.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
+
+ModelExecutionSession::ModelExecutionSession(
+    std::unique_ptr<optimization_guide::OptimizationGuideModelExecutor::Session>
+        session)
+    : session_(std::move(session)) {}
+
+ModelExecutionSession::~ModelExecutionSession() = default;
+
+void ModelExecutionSession::BindReceiver(
+    mojo::PendingReceiver<blink::mojom::ModelGenericSession> receiver) {
+  receiver_.Bind(std::move(receiver));
+}
+
+void ModelExecutionSession::ModelExecutionCallback(
+    mojo::RemoteSetElementId responder_id,
+    optimization_guide::OptimizationGuideModelStreamingExecutionResult result,
+    std::unique_ptr<optimization_guide::ModelQualityLogEntry> log_entry) {
+  blink::mojom::ModelStreamingResponder* responder =
+      responder_set_.Get(responder_id);
+  if (!responder) {
+    return;
+  }
+
+  if (!result.has_value()) {
+    responder->OnResponse(blink::mojom::ModelStreamingResponseStatus::kError,
+                          std::nullopt);
+    return;
+  }
+
+  auto response = optimization_guide::ParsedAnyMetadata<
+      optimization_guide::proto::StringValue>(result->response);
+  if (response->has_value()) {
+    responder->OnResponse(blink::mojom::ModelStreamingResponseStatus::kOngoing,
+                          response->value());
+  }
+  if (result->is_complete) {
+    responder->OnResponse(blink::mojom::ModelStreamingResponseStatus::kComplete,
+                          std::nullopt);
+  }
+}
+
+void ModelExecutionSession::Execute(
+    const std::string& input,
+    mojo::PendingRemote<blink::mojom::ModelStreamingResponder> responder) {
+  mojo::RemoteSetElementId responder_id =
+      responder_set_.Add(std::move(responder));
+  optimization_guide::proto::StringValue request;
+  request.set_value(input);
+  session_->ExecuteModel(
+      request,
+      base::BindRepeating(&ModelExecutionSession::ModelExecutionCallback,
+                          weak_ptr_factory_.GetWeakPtr(), responder_id));
+}
diff --git a/chrome/browser/model_execution/model_execution_session.h b/chrome/browser/model_execution/model_execution_session.h
new file mode 100644
index 0000000..61c100ac
--- /dev/null
+++ b/chrome/browser/model_execution/model_execution_session.h
@@ -0,0 +1,51 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MODEL_EXECUTION_MODEL_EXECUTION_SESSION_H_
+#define CHROME_BROWSER_MODEL_EXECUTION_MODEL_EXECUTION_SESSION_H_
+
+#include "base/memory/weak_ptr.h"
+#include "components/optimization_guide/core/optimization_guide_model_executor.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
+#include "third_party/blink/public/mojom/model_execution/model_session.mojom.h"
+
+// The implementation of `blink::mojom::ModelGenericSession`, which exposes the
+// single stream-based `Execute()` API for model execution.
+class ModelExecutionSession : public blink::mojom::ModelGenericSession {
+ public:
+  explicit ModelExecutionSession(
+      std::unique_ptr<
+          optimization_guide::OptimizationGuideModelExecutor::Session> session);
+  ModelExecutionSession(const ModelExecutionSession&) = delete;
+  ModelExecutionSession& operator=(const ModelExecutionSession&) = delete;
+
+  ~ModelExecutionSession() override;
+
+  void BindReceiver(
+      mojo::PendingReceiver<blink::mojom::ModelGenericSession> receiver);
+
+  // `blink::mojom::ModelGenericSession` implementation.
+  void Execute(const std::string& input,
+               mojo::PendingRemote<blink::mojom::ModelStreamingResponder>
+                   responder) override;
+
+ private:
+  void ModelExecutionCallback(
+      mojo::RemoteSetElementId responder_id,
+      optimization_guide::OptimizationGuideModelStreamingExecutionResult result,
+      std::unique_ptr<optimization_guide::ModelQualityLogEntry> log_entry);
+
+  // The underlying session provided by optimization guide component.
+  std::unique_ptr<optimization_guide::OptimizationGuideModelExecutor::Session>
+      session_;
+  mojo::Receiver<blink::mojom::ModelGenericSession> receiver_{this};
+  // The `RemoteSet` storing all the responders, each of them corresponds to one
+  // `Execute()` call.
+  mojo::RemoteSet<blink::mojom::ModelStreamingResponder> responder_set_;
+
+  base::WeakPtrFactory<ModelExecutionSession> weak_ptr_factory_{this};
+};
+
+#endif  // CHROME_BROWSER_MODEL_EXECUTION_MODEL_EXECUTION_SESSION_H_
diff --git a/chrome/browser/model_execution/model_manager_impl.cc b/chrome/browser/model_execution/model_manager_impl.cc
new file mode 100644
index 0000000..4810da4
--- /dev/null
+++ b/chrome/browser/model_execution/model_manager_impl.cc
@@ -0,0 +1,83 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/model_execution/model_manager_impl.h"
+
+#include "chrome/browser/model_execution/model_execution_session.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/common/content_client.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+
+DOCUMENT_USER_DATA_KEY_IMPL(ModelManagerImpl);
+
+ModelManagerImpl::ModelManagerImpl(content::RenderFrameHost* rfh)
+    : DocumentUserData<ModelManagerImpl>(rfh) {
+  browser_context_ = rfh->GetBrowserContext()->GetWeakPtr();
+}
+
+ModelManagerImpl::~ModelManagerImpl() = default;
+
+// static
+void ModelManagerImpl::Create(
+    content::RenderFrameHost* render_frame_host,
+    mojo::PendingReceiver<blink::mojom::ModelManager> receiver) {
+  ModelManagerImpl* model_manager =
+      ModelManagerImpl::GetOrCreateForCurrentDocument(render_frame_host);
+  model_manager->receiver_.Bind(std::move(receiver));
+}
+
+void ModelManagerImpl::CanCreateGenericSession(
+    CanCreateGenericSessionCallback callback) {
+  // TODO(leimy): add the checks after optimization guide component provide more
+  // method to determine if a session could be started.
+  content::BrowserContext* browser_context = browser_context_.get();
+  std::move(callback).Run(
+      /*can_create=*/browser_context &&
+      !!OptimizationGuideKeyedServiceFactory::GetForProfile(
+          Profile::FromBrowserContext(browser_context)));
+}
+
+void ModelManagerImpl::CreateGenericSession(
+    mojo::PendingReceiver<blink::mojom::ModelGenericSession> receiver,
+    CreateGenericSessionCallback callback) {
+  content::BrowserContext* browser_context = browser_context_.get();
+  if (!browser_context) {
+    receiver_.ReportBadMessage(
+        "Caller should ensure `CanStartModelExecutionSession()` "
+        "returns true before calling this method.");
+    std::move(callback).Run(/*success=*/false);
+    return;
+  }
+
+  OptimizationGuideKeyedService* service =
+      OptimizationGuideKeyedServiceFactory::GetForProfile(
+          Profile::FromBrowserContext(browser_context));
+  if (!service) {
+    receiver_.ReportBadMessage(
+        "Caller should ensure `CanStartModelExecutionSession()` "
+        "returns true before calling this method.");
+    std::move(callback).Run(/*success=*/false);
+    return;
+  }
+
+  std::unique_ptr<optimization_guide::OptimizationGuideModelExecutor::Session>
+      session = service->StartSession(
+          optimization_guide::proto::ModelExecutionFeature::
+              MODEL_EXECUTION_FEATURE_TEST);
+  // TODO(leimy): after this check is done by optimization guide and we can
+  // return that from `CanStartModelExecutionSession()`, we should replace this
+  // block by a CHECK, and stop returning any boolean value from this method.
+  if (!session) {
+    std::move(callback).Run(/*success=*/false);
+    return;
+  }
+  mojo::MakeSelfOwnedReceiver(
+      std::make_unique<ModelExecutionSession>(std::move(session)),
+      std::move(receiver));
+  std::move(callback).Run(/*success=*/true);
+}
diff --git a/chrome/browser/model_execution/model_manager_impl.h b/chrome/browser/model_execution/model_manager_impl.h
new file mode 100644
index 0000000..2a62f8d
--- /dev/null
+++ b/chrome/browser/model_execution/model_manager_impl.h
@@ -0,0 +1,49 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MODEL_EXECUTION_MODEL_MANAGER_IMPL_H_
+#define CHROME_BROWSER_MODEL_EXECUTION_MODEL_MANAGER_IMPL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/document_user_data.h"
+#include "content/public/browser/render_frame_host.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "third_party/blink/public/mojom/model_execution/model_manager.mojom.h"
+
+// The browser-side implementation of `blink::mojom::ModelManager`, it should be
+// destroyed together with the associated RFH or when the RFH is used for a
+// cross-document navigation.
+class ModelManagerImpl : public content::DocumentUserData<ModelManagerImpl>,
+                         public blink::mojom::ModelManager {
+ public:
+  ModelManagerImpl(const ModelManagerImpl&) = delete;
+  ModelManagerImpl& operator=(const ModelManagerImpl&) = delete;
+
+  ~ModelManagerImpl() override;
+
+  static void Create(
+      content::RenderFrameHost* render_frame_host,
+      mojo::PendingReceiver<blink::mojom::ModelManager> receiver);
+
+ private:
+  friend class DocumentUserData<ModelManagerImpl>;
+  DOCUMENT_USER_DATA_KEY_DECL();
+
+  explicit ModelManagerImpl(content::RenderFrameHost* rfh);
+
+  // `blink::mojom::ModelManager` implementation.
+  void CanCreateGenericSession(
+      CanCreateGenericSessionCallback callback) override;
+
+  void CreateGenericSession(
+      mojo::PendingReceiver<::blink::mojom::ModelGenericSession> receiver,
+      CreateGenericSessionCallback callback) override;
+
+  base::WeakPtr<content::BrowserContext> browser_context_;
+  mojo::Receiver<blink::mojom::ModelManager> receiver_{this};
+};
+
+#endif  // CHROME_BROWSER_MODEL_EXECUTION_MODEL_MANAGER_IMPL_H_
diff --git a/chrome/browser/net/chrome_shared_dictionary_browsertest.cc b/chrome/browser/net/chrome_shared_dictionary_browsertest.cc
index 7d1857f..ac05ab4 100644
--- a/chrome/browser/net/chrome_shared_dictionary_browsertest.cc
+++ b/chrome/browser/net/chrome_shared_dictionary_browsertest.cc
@@ -23,6 +23,7 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/shared_dictionary_encoding_names.h"
 #include "services/network/public/mojom/shared_dictionary_access_observer.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -153,14 +154,23 @@
 // `ChromeSharedDictionaryBrowserTest` is required to test Chrome
 // specific code such as Site Settings.
 // See `SharedDictionaryBrowserTest` for content's version of tests.
-class ChromeSharedDictionaryBrowserTest : public InProcessBrowserTest {
+class ChromeSharedDictionaryBrowserTest
+    : public InProcessBrowserTest,
+      public ::testing::WithParamInterface<
+          network::features::CompressionDictionaryTransportBackendVersion> {
  public:
   ChromeSharedDictionaryBrowserTest() {
-    scoped_feature_list_.InitWithFeatures(
+    scoped_feature_list_.InitWithFeaturesAndParameters(
         /*enabled_features=*/
-        {network::features::kCompressionDictionaryTransportBackend,
-         network::features::kCompressionDictionaryTransport,
-         network::features::kSharedZstd},
+        {base::test::FeatureRefAndParams(
+             network::features::kCompressionDictionaryTransportBackend,
+             {{network::features::kCompressionDictionaryTransportBackendVersion
+                   .name,
+               network::features::kCompressionDictionaryTransportBackendVersion
+                   .GetName(GetVersion())}}),
+         base::test::FeatureRefAndParams(
+             network::features::kCompressionDictionaryTransport, {}),
+         base::test::FeatureRefAndParams(network::features::kSharedZstd, {})},
         /*disabled_features=*/{});
 
     embedded_test_server()->RegisterRequestHandler(
@@ -181,6 +191,9 @@
       const ChromeSharedDictionaryBrowserTest&) = delete;
 
  protected:
+  network::features::CompressionDictionaryTransportBackendVersion GetVersion() {
+    return GetParam();
+  }
   net::EmbeddedTestServer* cross_origin_server() {
     return cross_origin_server_.get();
   }
@@ -332,13 +345,15 @@
     } else if (request.relative_url == "/path/brotli_compressed") {
       CHECK(GetSecAvailableDictionary(request.headers));
       response->set_content_type("text/html");
-      response->AddCustomHeader("content-encoding", "sbr");
+      response->AddCustomHeader("content-encoding",
+                                network::GetSharedBrotliContentEncodingName());
       response->set_content(kBrotliCompressedDataString);
       return response;
     } else if (request.relative_url == "/path/zstd_compressed") {
       CHECK(GetSecAvailableDictionary(request.headers));
       response->set_content_type("text/html");
-      response->AddCustomHeader("content-encoding", "zstd-d");
+      response->AddCustomHeader("content-encoding",
+                                network::GetSharedZstdContentEncodingName());
       response->set_content(kZstdCompressedDataString);
       return response;
     }
@@ -348,7 +363,26 @@
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest, BlockWriting) {
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    ChromeSharedDictionaryBrowserTest,
+    testing::Values(
+        network::features::CompressionDictionaryTransportBackendVersion::kV1,
+        network::features::CompressionDictionaryTransportBackendVersion::kV2),
+    [](const testing::TestParamInfo<
+        network::features::CompressionDictionaryTransportBackendVersion>&
+           info) {
+      switch (info.param) {
+        case network::features::CompressionDictionaryTransportBackendVersion::
+            kV1:
+          return "V1";
+        case network::features::CompressionDictionaryTransportBackendVersion::
+            kV2:
+          return "V2";
+      }
+    });
+
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest, BlockWriting) {
   content_settings::CookieSettings* settings =
       CookieSettingsFactory::GetForProfile(browser()->profile()).get();
   settings->SetCookieSetting(embedded_test_server()->GetURL("/"),
@@ -359,7 +393,7 @@
   EXPECT_FALSE(TryRegisterDictionary(*embedded_test_server()));
 }
 
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest,
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest,
                        BlockWritingCrossOrigin) {
   content_settings::CookieSettings* settings =
       CookieSettingsFactory::GetForProfile(browser()->profile()).get();
@@ -371,7 +405,7 @@
   EXPECT_FALSE(TryRegisterDictionary(*cross_origin_server()));
 }
 
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest, BlockReading) {
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest, BlockReading) {
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/title1.html")));
   EXPECT_TRUE(TryRegisterDictionary(*embedded_test_server()));
@@ -388,7 +422,7 @@
       CheckDictionaryHeader(*embedded_test_server(), /*expect_blocked=*/true));
 }
 
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest,
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest,
                        BlockReadingCrossOrigin) {
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/title1.html")));
@@ -406,7 +440,7 @@
       CheckDictionaryHeader(*cross_origin_server(), /*expect_blocked=*/true));
 }
 
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest,
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest,
                        BlockReadingWhileNavigation) {
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/title1.html")));
@@ -427,7 +461,7 @@
       /*expect_blocked=*/true));
 }
 
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest,
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest,
                        BlockReadingWhileIframeNavigation) {
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/title1.html")));
@@ -448,7 +482,7 @@
       /*expect_blocked=*/true));
 }
 
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest,
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest,
                        UseCounterMainFrameNavigation) {
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/title1.html")));
@@ -482,7 +516,7 @@
       /*expected_used_for_subresource_count=*/0);
 }
 
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest,
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest,
                        UseCounterSubFrameNavigation) {
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/title1.html")));
@@ -527,7 +561,7 @@
       /*expected_used_for_subresource_count=*/0);
 }
 
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest,
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest,
                        UseCounterSubresource) {
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/title1.html")));
@@ -566,7 +600,7 @@
       /*expected_used_for_subresource_count=*/1);
 }
 
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest,
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest,
                        UseCounterZstdMainFrameNavigation) {
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/title1.html")));
@@ -600,7 +634,7 @@
       /*expected_used_for_subresource_count=*/0);
 }
 
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest,
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest,
                        UseCounterZstdSubresource) {
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/title1.html")));
@@ -645,7 +679,7 @@
 #else
 #define MAYBE_SiteDataCount SiteDataCount
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-IN_PROC_BROWSER_TEST_F(ChromeSharedDictionaryBrowserTest, MAYBE_SiteDataCount) {
+IN_PROC_BROWSER_TEST_P(ChromeSharedDictionaryBrowserTest, MAYBE_SiteDataCount) {
   base::Time time1 = base::Time::Now();
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/title1.html")));
diff --git a/chrome/browser/page_load_metrics/integration_tests/data/mouseover.html b/chrome/browser/page_load_metrics/integration_tests/data/mouseover.html
index 5bcd59bd..dade57643 100644
--- a/chrome/browser/page_load_metrics/integration_tests/data/mouseover.html
+++ b/chrome/browser/page_load_metrics/integration_tests/data/mouseover.html
@@ -27,9 +27,6 @@
   }
 };
 
-// Turn off BFCache to see if it helps with BFCache bot flakes.
-window.addEventListener("unload", () => { console.log("Turn off BFCache"); });
-
 const registerMouseover = background => {
   const func = background ? loadBackgroundImage : loadImage;
   image.addEventListener("mouseover", func("100x50"));
diff --git a/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc b/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc
index bbad8f0..8446620 100644
--- a/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc
+++ b/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc
@@ -23,6 +23,7 @@
 #include "components/paint_preview/buildflags/buildflags.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/test/back_forward_cache_util.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/hit_test_region_observer.h"
@@ -420,8 +421,14 @@
                       int x2,
                       int y2,
                       bool expected) {
-    // Install a ScopedRunLoopTimeout override to distinguish the timeout from
-    // MouseoverLCPTest vs browser_test_base.
+    // Turn off BFCache to see if it helps with BFCache bot flakes. See
+    // https://crbug.com/1288027
+    content::DisableBackForwardCacheForTesting(
+        web_contents(), content::BackForwardCache::DisableForTestingReason::
+                            TEST_REQUIRES_NO_CACHING);
+
+    // Install a ScopedRunLoopTimeout override to distinguish the timeout
+    // from MouseoverLCPTest vs browser_test_base.
     base::test::ScopedRunLoopTimeout run_loop_timeout(FROM_HERE, absl::nullopt,
                                                       base::NullCallback());
     auto waiter =
diff --git a/chrome/browser/page_load_metrics/observers/prerender_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/prerender_page_load_metrics_observer_browsertest.cc
index 2debedf..aa95a914 100644
--- a/chrome/browser/page_load_metrics/observers/prerender_page_load_metrics_observer_browsertest.cc
+++ b/chrome/browser/page_load_metrics/observers/prerender_page_load_metrics_observer_browsertest.cc
@@ -79,9 +79,6 @@
     histogram_tester().ExpectBucketCount(
         internal::kPageLoadPrerenderObserverEvent,
         internal::PageLoadPrerenderObserverEvent::kOnFirstPaintInPage, 1);
-    histogram_tester().ExpectBucketCount(
-        "PageLoad.Internal.Prerender2.ForegroundCheckResult.FirstPaint",
-        internal::PageLoadPrerenderForegroundCheckResult::kPassed, 1);
 
     // FirstPaint should be recorded in the prerender PageLoad, not in the
     // regular PageLoad.
@@ -101,10 +98,6 @@
         internal::kPageLoadPrerenderObserverEvent,
         internal::PageLoadPrerenderObserverEvent::kOnFirstContentfulPaintInPage,
         1);
-    histogram_tester().ExpectBucketCount(
-        "PageLoad.Internal.Prerender2.ForegroundCheckResult."
-        "FirstContentfulPaint",
-        internal::PageLoadPrerenderForegroundCheckResult::kPassed, 1);
 
     // FirstContentfulPaint should be recorded in the prerender PageLoad, not in
     // the regular PageLoad.
@@ -124,9 +117,6 @@
     histogram_tester().ExpectBucketCount(
         internal::kPageLoadPrerenderObserverEvent,
         internal::PageLoadPrerenderObserverEvent::kOnFirstInputInPage, 1);
-    histogram_tester().ExpectBucketCount(
-        "PageLoad.Internal.Prerender2.ForegroundCheckResult.FirstInputDelay",
-        internal::PageLoadPrerenderForegroundCheckResult::kPassed, 1);
 
     // FirstInputDelay should be recorded in the prerender PageLoad, not in the
     // regular PageLoad.
@@ -149,10 +139,6 @@
         internal::kPageLoadPrerenderObserverEvent,
         internal::PageLoadPrerenderObserverEvent::kRecordSessionEndHistograms,
         1);
-    histogram_tester().ExpectBucketCount(
-        "PageLoad.Internal.Prerender2.ForegroundCheckResult."
-        "LargestContentfulPaint",
-        internal::PageLoadPrerenderForegroundCheckResult::kPassed, 1);
 
     // LargestContentfulPaint should be recorded in the prerender PageLoad, not
     // in the regular PageLoad.
@@ -901,10 +887,6 @@
   histogram_tester().ExpectBucketCount(
       internal::kPageLoadPrerenderObserverEvent,
       internal::PageLoadPrerenderObserverEvent::kRecordSessionEndHistograms, 2);
-  histogram_tester().ExpectBucketCount(
-      "PageLoad.Internal.Prerender2.ForegroundCheckResult."
-      "LargestContentfulPaint",
-      internal::PageLoadPrerenderForegroundCheckResult::kPassed, 1);
 
   // LargestContentfulPaint should be recorded in the prerender PageLoad, not
   // in the regular PageLoad.
diff --git a/chrome/browser/policy/test/accessibility_policy_browsertest.cc b/chrome/browser/policy/test/accessibility_policy_browsertest.cc
index bc3bcf8b..711bc82 100644
--- a/chrome/browser/policy/test/accessibility_policy_browsertest.cc
+++ b/chrome/browser/policy/test/accessibility_policy_browsertest.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
 #include "chrome/browser/ash/accessibility/magnification_manager.h"
@@ -215,7 +217,29 @@
   EXPECT_FALSE(accessibility_manager->IsStickyKeysEnabled());
 }
 
-IN_PROC_BROWSER_TEST_F(AccessibilityPolicyTest, VirtualKeyboardEnabled) {
+// TODO(b/307433336): Remove this once the flag is enabled by default.
+// TODO(b/307433336): Move these tests to a separate file since these are not
+// accessibility related.
+class AccessibilityPolicyTouchVirtualKeyboardEnabledTest
+    : public AccessibilityPolicyTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  AccessibilityPolicyTouchVirtualKeyboardEnabledTest() {
+    feature_list_.InitWithFeatureState(
+        ash::features::kTouchVirtualKeyboardPolicyListenPrefsAtLogin,
+        GetParam());
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(,
+                         AccessibilityPolicyTouchVirtualKeyboardEnabledTest,
+                         ::testing::Values(true, false));
+
+IN_PROC_BROWSER_TEST_P(AccessibilityPolicyTouchVirtualKeyboardEnabledTest,
+                       TouchVirtualKeyboardEnabledDefault) {
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
   ASSERT_TRUE(keyboard_client);
 
@@ -227,6 +251,12 @@
   EXPECT_TRUE(keyboard_client->is_keyboard_enabled());
   ClearEnableFlag(keyboard::KeyboardEnableFlag::kTouchEnabled);
   EXPECT_FALSE(keyboard_client->is_keyboard_enabled());
+}
+
+IN_PROC_BROWSER_TEST_P(AccessibilityPolicyTouchVirtualKeyboardEnabledTest,
+                       TouchVirtualKeyboardEnabledTrueEnablesVirtualKeyboard) {
+  auto* keyboard_client = ChromeKeyboardControllerClient::Get();
+  ASSERT_TRUE(keyboard_client);
 
   // Verify enabling the policy takes effect immediately and that that user
   // cannot disable the keyboard..
@@ -238,9 +268,17 @@
   EXPECT_TRUE(keyboard_client->is_keyboard_enabled());
   ClearEnableFlag(keyboard::KeyboardEnableFlag::kTouchEnabled);
   EXPECT_TRUE(keyboard_client->is_keyboard_enabled());
+}
+
+IN_PROC_BROWSER_TEST_P(
+    AccessibilityPolicyTouchVirtualKeyboardEnabledTest,
+    TouchVirtualKeyboardEnabledFalseDisablesVirtualKeyboard) {
+  auto* keyboard_client = ChromeKeyboardControllerClient::Get();
+  ASSERT_TRUE(keyboard_client);
 
   // Verify that disabling the policy takes effect immediately and that the user
   // cannot enable the keyboard.
+  PolicyMap policies;
   policies.Set(key::kTouchVirtualKeyboardEnabled, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(false),
                nullptr);
diff --git a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc
index ce7e58b78..2dac4fc9 100644
--- a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc
@@ -598,7 +598,7 @@
   for (auto& candidate : base::Reversed(candidates)) {
     MEMORY_LOG(ERROR) << "Target memory to free: "
                       << target_memory_to_free.target_kb << " KB";
-    if (target_memory_to_free.target_kb <= 0) {
+    if (target_memory_to_free.target_kb == 0) {
       break;
     }
 
@@ -608,7 +608,10 @@
     unnecessary_discard_monitor_.OnDiscard(freed_memory_kb,
                                            base::TimeTicks::Now());
 
-    target_memory_to_free.target_kb -= freed_memory_kb;
+    // Prevent underflow by capping the memory freed.
+    target_memory_to_free.target_kb -=
+        std::min(static_cast<uint64_t>(freed_memory_kb),
+                 target_memory_to_free.target_kb);
 
     if (freed_memory_kb > 0 && !first_kill_time) {
       first_kill_time = base::TimeTicks::Now();
diff --git a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h
index 18e215c..db62dc7 100644
--- a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h
+++ b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h
@@ -135,6 +135,8 @@
   FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, SetOomScoreAdj);
   FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, TestDiscardedTabsAreSkipped);
   FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, ReportProcesses);
+  FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest,
+                           TestTargetMemoryToFreeIsRespected);
 
   using OptionalArcProcessList = arc::ArcProcessService::OptionalArcProcessList;
 
diff --git a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc
index ab65d42..ca03493 100644
--- a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc
@@ -518,4 +518,33 @@
   EXPECT_EQ(processes[5].is_focused, true);
 }
 
+TEST_F(TabManagerDelegateTest, TestTargetMemoryToFreeIsRespected) {
+  // Not owned.
+  MockMemoryStat* memory_stat = new MockMemoryStat();
+
+  // Instantiate the mock instance.
+  MockTabManagerDelegate tab_manager_delegate(memory_stat);
+
+  TestLifecycleUnit tab1(base::TimeTicks() + base::Seconds(3), 10);
+  tab1.SetEstimatedMemoryFreedOnDiscardKB(60);
+  tab_manager_delegate.AddLifecycleUnit(&tab1);
+  TestLifecycleUnit tab2(base::TimeTicks() + base::Seconds(1), 11);
+  tab2.SetEstimatedMemoryFreedOnDiscardKB(60);
+  tab_manager_delegate.AddLifecycleUnit(&tab2);
+  TestLifecycleUnit tab3(base::TimeTicks() + base::Seconds(5), 12);
+  tab3.SetEstimatedMemoryFreedOnDiscardKB(60);
+  tab_manager_delegate.AddLifecycleUnit(&tab3);
+
+  // With target memory to free at 100, only two of the tabs should be killed.
+  memory_stat->SetTargetMemoryToFreeKB(100);
+
+  tab_manager_delegate.LowMemoryKillImpl(
+      base::TimeTicks::Now(), ::mojom::LifecycleUnitDiscardReason::EXTERNAL,
+      TabManager::TabDiscardDoneCB(base::DoNothing()), absl::nullopt);
+
+  auto killed_tabs = tab_manager_delegate.GetKilledTabs();
+
+  ASSERT_EQ(2U, killed_tabs.size());
+}
+
 }  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/test_lifecycle_unit.cc b/chrome/browser/resource_coordinator/test_lifecycle_unit.cc
index e83b7fa..653428c7 100644
--- a/chrome/browser/resource_coordinator/test_lifecycle_unit.cc
+++ b/chrome/browser/resource_coordinator/test_lifecycle_unit.cc
@@ -62,7 +62,7 @@
 }
 
 int TestLifecycleUnit::GetEstimatedMemoryFreedOnDiscardKB() const {
-  return 0;
+  return estimated_memory_freed_kb_;
 }
 
 bool TestLifecycleUnit::CanDiscard(mojom::LifecycleUnitDiscardReason reason,
diff --git a/chrome/browser/resource_coordinator/test_lifecycle_unit.h b/chrome/browser/resource_coordinator/test_lifecycle_unit.h
index c0e8980..94d367ec 100644
--- a/chrome/browser/resource_coordinator/test_lifecycle_unit.h
+++ b/chrome/browser/resource_coordinator/test_lifecycle_unit.h
@@ -41,6 +41,10 @@
     failure_reason_ = failure_reason;
   }
 
+  void SetEstimatedMemoryFreedOnDiscardKB(int estimated_memory_freed_kb) {
+    estimated_memory_freed_kb_ = estimated_memory_freed_kb;
+  }
+
   // LifecycleUnit:
   TabLifecycleUnitExternal* AsTabLifecycleUnitExternal() override;
   std::u16string GetTitle() const override;
@@ -64,6 +68,7 @@
   LifecycleUnit::SortKey sort_key_;
   bool can_discard_ = true;
   std::optional<DecisionFailureReason> failure_reason_;
+  int estimated_memory_freed_kb_ = 0;
 };
 
 // Helper funtions for testing CanDiscard policy.
diff --git a/chrome/browser/resources/password_manager/sharing/share_password_confirmation_dialog.html b/chrome/browser/resources/password_manager/sharing/share_password_confirmation_dialog.html
index 8d41a40..fbe0900 100644
--- a/chrome/browser/resources/password_manager/sharing/share_password_confirmation_dialog.html
+++ b/chrome/browser/resources/password_manager/sharing/share_password_confirmation_dialog.html
@@ -22,7 +22,6 @@
   #progress,
   #favicon {
     position: absolute;
-    animation-fill-mode: forwards;
   }
 
   #senderAvatar,
@@ -31,9 +30,7 @@
     right: 50%;
     transform: translate(50%, -50%);
 
-    animation-delay: 0.35s;
-    animation-duration: 4.65s;
-    animation-timing-function: cubic-bezier(0.7, 0, 0.45, 1.45);
+    transition: right 500ms cubic-bezier(0.7, 0, 0.45, 1.45);
   }
 
   #senderAvatar {
@@ -42,36 +39,10 @@
     width: var(--avatar-size_);
 
     z-index: 1;
-    animation-name: slideLeft;
-  }
-
-  @keyframes slideLeft {
-    100% {
-      right: calc(50% + var(--avatar-radius) - 4px);
-      z-index: 2;
-    }
-
-    10%,
-    90% {
-      right: calc(50% + 78px);
-    }
   }
 
   #recipientAvatar {
     z-index: 2;
-    animation-name: slideRight;
-  }
-
-  @keyframes slideRight {
-    100% {
-      z-index: 1;
-      right: calc(50% - var(--avatar-radius) + 4px);
-    }
-
-    10%,
-    90% {
-      right: calc(50% - 78px);
-    }
   }
 
   #lock {
@@ -86,23 +57,7 @@
     opacity: 0;
     transform: translate(50%, -50%) scale(0.5);
 
-    animation-delay: 0.8s;
-    animation-duration: 4s;
-    animation-timing-function: ease-in;
-    animation-name: lockOpacity;
-  }
-
-  @keyframes lockOpacity {
-    100% {
-      opacity: 0;
-      transform: translate(50%, -50%) scale(0);
-    }
-
-    3%,
-    95% {
-      opacity: 1;
-      transform: translate(50%, -50%) scale(1);
-    }
+    transition: opacity 0.15s ease-in 500ms, transform 0.15s ease-in 500ms;
   }
 
   #favicon {
@@ -119,18 +74,7 @@
     opacity: 0;
     transform: translate(50%, 0) scale(0);
 
-    animation-delay: 5s;
-    animation-duration: 0.15s;
-    animation-timing-function: ease-in;
-    animation-fill-mode: forwards;
-    animation-name: faviconOpacity;
-  }
-
-  @keyframes faviconOpacity {
-    100% {
-      opacity: 1;
-      transform: translate(50%, 0) scale(1);
-    }
+    transition: opacity 0.15s ease-in 500ms, transform 0.15s ease-in 500ms;
   }
 
   #progress {
@@ -142,22 +86,68 @@
 
     width: 0;
 
-    animation-delay: 1s;
-    animation-duration: 3.5s;
-    animation-timing-function: linear;
-    animation-name: progressWidth;
+    transition: all 4.1s linear 500ms, opacity 0.15s ease-in 500ms;
   }
 
-  @keyframes progressWidth {
-    100% {
-      width: 95px;
-      opacity: 0;
-    }
+  .loading #senderAvatar {
+    right: calc(50% + 78px);
+  }
 
-    1%,
-    99% {
-      opacity: 1;
-    }
+  .loading #recipientAvatar {
+    right: calc(50% - 78px);
+  }
+
+  .loading #progress {
+    opacity: 1;
+    width: 95px;
+  }
+
+  .loading #lock {
+    opacity: 1;
+    transform: translate(50%, -50%) scale(1);
+  }
+
+  [success] #senderAvatar {
+    right: calc(50% + var(--avatar-radius) - 4px);
+    z-index: 2;
+  }
+
+  [success] #recipientAvatar {
+    z-index: 1;
+    right: calc(50% - var(--avatar-radius) + 4px);
+  }
+
+  [success] #lock,
+  [success] #progress {
+    opacity: 0;
+    transition-delay: 0s;
+  }
+
+  [success] #favicon {
+    opacity: 1;
+    transform: translate(50%, 0) scale(1);
+  }
+
+  [canceled] #progress{
+    opacity: 0;
+    transition: none;
+  }
+
+  [canceled] #senderAvatar {
+    z-index: 2;
+  }
+
+  [canceled] #recipientAvatar {
+    z-index: 1;
+  }
+
+  [canceled] #lock,
+  [canceled] #senderAvatar,
+  [canceled] #recipientAvatar {
+    transition-property: transform, opacity, right;
+    transition-timing-function: cubic-bezier(0.7, -0.45, 0.45, 1);
+    transition-duration: 500ms;
+    transition-delay: 0s;
   }
 
   #description {
@@ -174,20 +164,6 @@
     color: var(--cr-secondary-text-color);
   }
 
-  [canceled] > #recipientAvatar,
-  [canceled] > #lock,
-  [canceled] > #progress,
-  [canceled] > #favicon {
-    display: none;
-  }
-
-  [canceled] > #senderAvatar {
-    top: 50%;
-    right: 50%;
-    transform: translate(50%, -50%);
-    animation: none;
-  }
-
   @media (prefers-color-scheme: dark) {
     /* Backgroud has to be non-transperent, and match one from cr-dialog. */
     #lock {
@@ -217,8 +193,9 @@
     </share-password-dialog-header>
   </div>
   <div slot="body">
-    <div class="animation-container"
-        canceled$="[[isStage_(dialogStageEnum_.CANCELED, dialogStage_)]]">
+    <div class="animation-container" id="animation"
+        canceled$="[[isStage_(dialogStageEnum_.CANCELED, dialogStage_)]]"
+        success$="[[isStage_(dialogStageEnum_.SUCCESS, dialogStage_)]]">
       <img id="senderAvatar" src="[[avatarImage]]" draggable="false" alt="">
       <share-password-group-avatar members="[[recipients]]"
           id="recipientAvatar">
diff --git a/chrome/browser/resources/password_manager/sharing/share_password_confirmation_dialog.ts b/chrome/browser/resources/password_manager/sharing/share_password_confirmation_dialog.ts
index 5dea5b0..0d285fd9 100644
--- a/chrome/browser/resources/password_manager/sharing/share_password_confirmation_dialog.ts
+++ b/chrome/browser/resources/password_manager/sharing/share_password_confirmation_dialog.ts
@@ -24,6 +24,7 @@
 
 export interface SharePasswordConfirmationDialogElement {
   $: {
+    animation: HTMLElement,
     header: HTMLElement,
     cancel: HTMLElement,
     done: HTMLElement,
@@ -93,6 +94,11 @@
   override ready() {
     super.ready();
 
+    // Start the animation after all elements have been loaded.
+    setTimeout(() => {
+      this.$.animation.classList.add('loading');
+    }, 0);
+
     // The user has 5 seconds to cancel the share action while loading/sharing
     // animation is in progress.
     setTimeout(() => {
@@ -191,6 +197,7 @@
     recordPasswordSharingInteraction(
         PasswordSharingActions.CONFIRMATION_DIALOG_SHARING_CANCELED);
     this.dialogStage_ = ConfirmationDialogStage.CANCELED;
+    this.$.animation.classList.remove('loading');
   }
 }
 
diff --git a/chrome/browser/resources/search_engine_choice/app.html b/chrome/browser/resources/search_engine_choice/app.html
index 7bcb3e3..e7aad7c 100644
--- a/chrome/browser/resources/search_engine_choice/app.html
+++ b/chrome/browser/resources/search_engine_choice/app.html
@@ -85,7 +85,7 @@
     background-color: var(--background-color);
     border-radius: calc(var(--omnibox-height) / 2);
     bottom: var(--search-engine-omnibox-bottom-value);
-    box-shadow: 0px 4px 16px 0px var(--search-engine-omnibox-shadow-color);
+    box-shadow: 0 4px 16px 0 var(--search-engine-omnibox-shadow-color);
     display: flex;
     flex-direction: row;
     gap: 8px;
@@ -253,7 +253,8 @@
 
   cr-expand-button {
     --cr-expand-button-size: 24px;
-    --cr-section-vertical-padding: 0px;
+    --cr-icon-button-margin-start: 0;
+    --cr-section-vertical-padding: 0;
     margin-inline-start: auto;
   }
 
@@ -416,11 +417,11 @@
 <img class="tangible-sync-style-right-banner" alt="">
 <div class="content-container tangible-sync-style">
   <img class="product-logo" src="images/product-logo.svg"
-      alt="$i18n{productLogoAltText}">
+      alt="$i18n{productLogoAltText}" aria-hidden="true">
   <h1 class="title">$i18n{title}</h1>
   <div class="omniboxes">
     <div id="dummyOmnibox">
-      <iron-icon icon="cr:search"></iron-icon>
+      <iron-icon icon="cr:search" aria-hidden="true"></iron-icon>
       <div class="hint-placeholder"></div>
     </div>
     <div id="searchEngineOmnibox">
@@ -437,18 +438,19 @@
     </a>
   </p>
   <cr-radio-group id="choiceList" class="custom-scrollbar"
-      selected="{{selectedChoice_}}" role="list" tabindex="0">
+      selected="{{selectedChoice_}}" role="list">
     <template is="dom-repeat" items="[[choiceList_]]">
-        <cr-radio-button role="listitem" class="label-first"
+        <cr-radio-button aria-label$="[[item.name]]" role="listitem"
+            class="label-first"
             name="[[item.prepopulateId]]">
           <div class="choice">
             <div class="choice-icon"
                 style$="background-image: [[item.iconPath]];"></div>
             <div class="choice-text">
               <div class="choice-title">
-                [[item.name]]
+                <span aria-hidden="true">[[item.name]]</span>
                 <cr-expand-button expanded="{{item.showMarketingSnippet}}"
-                    no-hover>
+                    no-hover role="button" aria-label="$i18n{chevronA11yLabel}">
                 </cr-expand-button>
                 <div class="vertical-separator"></div>
               </div>
diff --git a/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc b/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc
index f6d0ed1e..cc2a896a 100644
--- a/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc
+++ b/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc
@@ -306,6 +306,17 @@
   kListenToThisPageEnabled = 100248,
   kIpProtectionEnabled = 100249,
   kAccessibilityReadAnythingLinksEnabled = 100250,
+  kProfileContentSettingsPartitionedExceptionsAntiAbuse = 100251,
+  kProfileContentSettingsPartitionedExceptionsAutomaticDownloads = 100252,
+  kProfileContentSettingsPartitionedExceptionsCookies = 100253,
+  kProfileContentSettingsPartitionedExceptionsGetDisplayMediaSetSelectAllScreens =
+      100254,
+  kProfileContentSettingsPartitionedExceptionsImages = 100255,
+  kProfileContentSettingsPartitionedExceptionsJavascript = 100256,
+  kProfileContentSettingsPartitionedExceptionsLocalFonts = 100257,
+  kProfileContentSettingsPartitionedExceptionsMouselock = 100258,
+  kProfileContentSettingsPartitionedExceptionsPopups = 100259,
+  kProfileContentSettingsPartitionedExceptionsWindowPlacement = 100260,
   // See components/sync_preferences/README.md about adding new entries here.
   // vvvvv IMPORTANT! vvvvv
   // Note to the reviewer: IT IS YOUR RESPONSIBILITY to ensure that new syncable
@@ -1216,6 +1227,7 @@
        {syncable_prefs_ids::kSpellCheckEnable, syncer::PREFERENCES,
         sync_preferences::PrefSensitivity::kNone,
         sync_preferences::MergeBehavior::kNone}},
+#if !BUILDFLAG(IS_ANDROID)
       // The following prefs are constructed from a prefix in
       // website_settings_info and are registered in
       // content_settings_registry.
@@ -1271,6 +1283,64 @@
         syncer::PREFERENCES,
         sync_preferences::PrefSensitivity::kSensitiveRequiresHistory,
         sync_preferences::MergeBehavior::kMergeableDict}},
+      {"profile.content_settings.partitioned_exceptions.anti_abuse",
+       {syncable_prefs_ids::
+            kProfileContentSettingsPartitionedExceptionsAntiAbuse,
+        syncer::PREFERENCES,
+        sync_preferences::PrefSensitivity::kSensitiveRequiresHistory,
+        sync_preferences::MergeBehavior::kMergeableDict}},
+      {"profile.content_settings.partitioned_exceptions.automatic_downloads",
+       {syncable_prefs_ids::
+            kProfileContentSettingsPartitionedExceptionsAutomaticDownloads,
+        syncer::PREFERENCES,
+        sync_preferences::PrefSensitivity::kSensitiveRequiresHistory,
+        sync_preferences::MergeBehavior::kMergeableDict}},
+      {"profile.content_settings.partitioned_exceptions.cookies",
+       {syncable_prefs_ids::kProfileContentSettingsPartitionedExceptionsCookies,
+        syncer::PREFERENCES,
+        sync_preferences::PrefSensitivity::kSensitiveRequiresHistory,
+        sync_preferences::MergeBehavior::kMergeableDict}},
+      {"profile.content_settings.partitioned_exceptions.get_display_media_set_"
+       "select_all_screens",
+       {syncable_prefs_ids::
+            kProfileContentSettingsPartitionedExceptionsGetDisplayMediaSetSelectAllScreens,
+        syncer::PREFERENCES,
+        sync_preferences::PrefSensitivity::kSensitiveRequiresHistory,
+        sync_preferences::MergeBehavior::kMergeableDict}},
+      {"profile.content_settings.partitioned_exceptions.images",
+       {syncable_prefs_ids::kProfileContentSettingsPartitionedExceptionsImages,
+        syncer::PREFERENCES,
+        sync_preferences::PrefSensitivity::kSensitiveRequiresHistory,
+        sync_preferences::MergeBehavior::kMergeableDict}},
+      {"profile.content_settings.partitioned_exceptions.javascript",
+       {syncable_prefs_ids::
+            kProfileContentSettingsPartitionedExceptionsJavascript,
+        syncer::PREFERENCES,
+        sync_preferences::PrefSensitivity::kSensitiveRequiresHistory,
+        sync_preferences::MergeBehavior::kMergeableDict}},
+      {"profile.content_settings.partitioned_exceptions.local_fonts",
+       {syncable_prefs_ids::
+            kProfileContentSettingsPartitionedExceptionsLocalFonts,
+        syncer::PREFERENCES,
+        sync_preferences::PrefSensitivity::kSensitiveRequiresHistory,
+        sync_preferences::MergeBehavior::kMergeableDict}},
+      {"profile.content_settings.partitioned_exceptions.mouselock",
+       {syncable_prefs_ids::
+            kProfileContentSettingsPartitionedExceptionsMouselock,
+        syncer::PREFERENCES,
+        sync_preferences::PrefSensitivity::kSensitiveRequiresHistory,
+        sync_preferences::MergeBehavior::kMergeableDict}},
+      {"profile.content_settings.partitioned_exceptions.popups",
+       {syncable_prefs_ids::kProfileContentSettingsPartitionedExceptionsPopups,
+        syncer::PREFERENCES,
+        sync_preferences::PrefSensitivity::kSensitiveRequiresHistory,
+        sync_preferences::MergeBehavior::kMergeableDict}},
+      {"profile.content_settings.partitioned_exceptions.window_placement",
+       {syncable_prefs_ids::
+            kProfileContentSettingsPartitionedExceptionsWindowPlacement,
+        syncer::PREFERENCES,
+        sync_preferences::PrefSensitivity::kSensitiveRequiresHistory,
+        sync_preferences::MergeBehavior::kMergeableDict}},
       {"profile.default_content_setting_values.anti_abuse",
        {syncable_prefs_ids::kProfileDefaultContentSettingValuesAntiAbuse,
         syncer::PREFERENCES, sync_preferences::PrefSensitivity::kNone,
@@ -1314,6 +1384,7 @@
        {syncable_prefs_ids::kProfileDefaultContentSettingValuesWindowPlacement,
         syncer::PREFERENCES, sync_preferences::PrefSensitivity::kNone,
         sync_preferences::MergeBehavior::kNone}},
+#endif
       // This is not exposed in a header.
       // TODO(crbug.com/1420978): Declare this in the corresponding header.
       {"webauthn.cablev2_pairings",
diff --git a/chrome/browser/ui/ash/download_status/display_manager.cc b/chrome/browser/ui/ash/download_status/display_manager.cc
index 4971b02df..ad81b642 100644
--- a/chrome/browser/ui/ash/download_status/display_manager.cc
+++ b/chrome/browser/ui/ash/download_status/display_manager.cc
@@ -13,6 +13,9 @@
 #include "base/files/file_path.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
+#include "base/logging.h"
+#include "base/ranges/algorithm.h"
+#include "base/strings/string_number_conversions.h"
 #include "chrome/browser/ash/crosapi/download_status_updater_ash.h"
 #include "chrome/browser/ui/ash/download_status/display_client.h"
 #include "chrome/browser/ui/ash/download_status/display_metadata.h"
@@ -25,6 +28,13 @@
 
 namespace {
 
+// Constants -------------------------------------------------------------------
+
+// Indicates an unknown total bytes count of `crosapi::mojom::DownloadStatus`.
+constexpr int64_t kUnknownTotalBytes = -1;
+
+// Helpers ---------------------------------------------------------------------
+
 // Returns true if `download_status` provides sufficient data to display the
 // associated download update.
 bool CanDisplay(const crosapi::mojom::DownloadStatus& download_status) {
@@ -32,33 +42,65 @@
   return file_path.has_value() && !file_path->empty();
 }
 
-// Returns the total number of bytes, or `std::nullopt` if the
-// `download_status` total bytes count is null or less than one.
-std::optional<int64_t> GetTotalBytes(
-    const crosapi::mojom::DownloadStatus& download_status) {
-  const std::optional<int64_t>& total_bytes = download_status.total_bytes;
-  return total_bytes > 0 ? total_bytes : std::nullopt;
+std::string GetPrintString(const std::optional<int64_t>& data) {
+  return data.has_value() ? base::NumberToString(data.value()) : "null";
 }
 
-// Returns the number of received bytes, or `std::nullopt` if the
-// `download_status` received bytes count is null or a negative value.
-// NOTE: This function ensures that the number of received bytes is less than
-// the number of total bytes if the download is not complete.
-std::optional<int64_t> GetReceivedBytes(
-    const crosapi::mojom::DownloadStatus& download_status) {
+// Returns the progress indicated by `download_status`.
+Progress GetProgress(const crosapi::mojom::DownloadStatus& download_status) {
   const std::optional<int64_t>& received_bytes = download_status.received_bytes;
-  if (received_bytes < 0) {
-    return std::nullopt;
+  const std::optional<int64_t>& total_bytes = download_status.total_bytes;
+
+  // `received_bytes` and `total_bytes` could be invalid. Correct these numbers
+  // if necessary. NOTE: `total_bytes` could be negative but `Progress` expects
+  // a non-negative if `updated_total_bytes` has a value.
+  std::optional<int64_t> updated_received_bytes = received_bytes;
+  std::optional<int64_t> updated_total_bytes = total_bytes;
+
+  if (received_bytes && received_bytes < 0) {
+    LOG(ERROR) << "The received bytes count is invalid: expected a non "
+                  "negative value; the actual value is "
+               << GetPrintString(received_bytes);
+    updated_received_bytes = std::nullopt;
   }
 
-  if (const std::optional<int64_t>& total_bytes =
-          GetTotalBytes(download_status);
-      received_bytes == total_bytes &&
-      download_status.state != crosapi::mojom::DownloadState::kComplete) {
-    return *received_bytes - 1;
+  if (total_bytes && total_bytes < kUnknownTotalBytes) {
+    LOG(ERROR) << "The total bytes count is invalid: expected to be a non "
+                  "negative value or -1 that indicates an unknown total bytes "
+                  "count; the actual value is "
+               << GetPrintString(total_bytes);
   }
 
-  return received_bytes;
+  // `Progress` does not accept a negative total bytes count.
+  if (updated_total_bytes < 0) {
+    updated_total_bytes = std::nullopt;
+  }
+
+  const bool is_determinate =
+      received_bytes && total_bytes && total_bytes != kUnknownTotalBytes;
+
+  if (is_determinate && received_bytes > total_bytes) {
+    LOG(ERROR) << "For a download that is determinate, its received bytes "
+                  "count should not be greater than the total bytes count; the "
+                  "actual received bytes count is "
+               << GetPrintString(received_bytes)
+               << " and the actual total bytes count is "
+               << GetPrintString(total_bytes);
+  }
+
+  const bool complete =
+      download_status.state == crosapi::mojom::DownloadState::kComplete;
+
+  if (complete) {
+    updated_received_bytes = updated_total_bytes =
+        base::ranges::max({updated_received_bytes, updated_total_bytes,
+                           std::optional<int64_t>(0)});
+  } else if (updated_total_bytes >= 0 &&
+             updated_received_bytes > updated_total_bytes) {
+    updated_total_bytes = updated_received_bytes;
+  }
+
+  return Progress(updated_received_bytes, updated_total_bytes, complete);
 }
 
 // Returns the text to display for the download specified by `download_status`.
@@ -165,10 +207,9 @@
   display_metadata.command_infos = std::move(command_infos);
 
   display_metadata.file_path = *download_status.full_path;
-  display_metadata.received_bytes = GetReceivedBytes(download_status);
+  display_metadata.progress = GetProgress(download_status);
   display_metadata.secondary_text = download_status.status_text;
   display_metadata.text = GetText(download_status);
-  display_metadata.total_bytes = GetTotalBytes(download_status);
 
   return display_metadata;
 }
diff --git a/chrome/browser/ui/ash/download_status/display_metadata.cc b/chrome/browser/ui/ash/download_status/display_metadata.cc
index 23fc1b37..6ed359a 100644
--- a/chrome/browser/ui/ash/download_status/display_metadata.cc
+++ b/chrome/browser/ui/ash/download_status/display_metadata.cc
@@ -6,6 +6,9 @@
 
 #include <utility>
 
+#include "base/check.h"
+#include "base/check_op.h"
+
 namespace ash::download_status {
 
 // CommandInfo -----------------------------------------------------------------
@@ -35,4 +38,32 @@
 
 DisplayMetadata::~DisplayMetadata() = default;
 
+// Progress --------------------------------------------------------------------
+
+Progress::Progress()
+    : Progress(/*received_bytes=*/std::nullopt,
+               /*total_bytes=*/std::nullopt,
+               /*complete=*/false) {}
+
+Progress::Progress(const std::optional<int64_t>& received_bytes,
+                   const std::optional<int64_t>& total_bytes,
+                   bool complete)
+    : received_bytes_(received_bytes),
+      total_bytes_(total_bytes),
+      complete_(complete) {
+  const bool is_indeterminate = (!received_bytes_ || !total_bytes_);
+
+  CHECK(is_indeterminate || received_bytes_ <= total_bytes_);
+  CHECK_GE(received_bytes_.value_or(0), 0);
+  CHECK_GE(total_bytes_.value_or(0), 0);
+
+  // Check that for a completed download, `received_bytes` and `total_bytes`
+  // have the same value. NOTE: When `received_bytes` and `total_bytes` have the
+  // same value, `complete` can be false.
+  if (complete_) {
+    CHECK(!is_indeterminate);
+    CHECK_EQ(received_bytes_.value(), total_bytes_.value());
+  }
+}
+
 }  // namespace ash::download_status
diff --git a/chrome/browser/ui/ash/download_status/display_metadata.h b/chrome/browser/ui/ash/download_status/display_metadata.h
index 0329281..ee1c21ce1 100644
--- a/chrome/browser/ui/ash/download_status/display_metadata.h
+++ b/chrome/browser/ui/ash/download_status/display_metadata.h
@@ -12,7 +12,6 @@
 #include "base/files/file_path.h"
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace gfx {
 struct VectorIcon;
@@ -51,6 +50,38 @@
   CommandType type;
 };
 
+// Indicates a download's progress. A progress is indeterminate if either
+// `received_bytes` or `total_bytes` is unknown.
+class Progress {
+ public:
+  Progress();
+
+  // Creates an instance for the specified `received_bytes`, `total_bytes` and
+  // `complete`. NOTE:
+  // 1. The values of `received_bytes` and `total_bytes`, if any, must be
+  //    non-negative.
+  // 2. `received_bytes` must not be greater than `total_bytes` unless the
+  //     progress is indeterminate.
+  // 3. When `complete` is true, `received_bytes` and `total_bytes` must have
+  //    values and be equal.
+  Progress(const std::optional<int64_t>& received_bytes,
+           const std::optional<int64_t>& total_bytes,
+           bool complete);
+
+  bool complete() const { return complete_; }
+
+  const std::optional<int64_t>& received_bytes() const {
+    return received_bytes_;
+  }
+
+  const std::optional<int64_t>& total_bytes() const { return total_bytes_; }
+
+ private:
+  std::optional<int64_t> received_bytes_;
+  std::optional<int64_t> total_bytes_;
+  bool complete_;
+};
+
 // The metadata used to display downloads.
 struct DisplayMetadata {
   DisplayMetadata();
@@ -65,17 +96,14 @@
   // NOTE: This path is different from the download target path.
   base::FilePath file_path;
 
-  // The received bytes of download.
-  std::optional<int64_t> received_bytes;
+  // Indicates the progress of the underlying download.
+  Progress progress;
 
   // The text that provides additional details about the download.
   std::optional<std::u16string> secondary_text;
 
   // The primary text of the displayed download.
   std::optional<std::u16string> text;
-
-  // The total bytes of download.
-  std::optional<int64_t> total_bytes;
 };
 
 }  // namespace ash::download_status
diff --git a/chrome/browser/ui/ash/download_status/holding_space_display_client.cc b/chrome/browser/ui/ash/download_status/holding_space_display_client.cc
index 79d4ef8..0a606b0 100644
--- a/chrome/browser/ui/ash/download_status/holding_space_display_client.cc
+++ b/chrome/browser/ui/ash/download_status/holding_space_display_client.cc
@@ -57,8 +57,12 @@
 
   HoldingSpaceKeyedService* const service =
       HoldingSpaceKeyedServiceFactory::GetInstance()->GetService(profile());
-  const HoldingSpaceProgress progress(display_metadata.received_bytes,
-                                      display_metadata.total_bytes);
+
+  // Create a `HoldingSpaceProgress` instance from a `Progress` instance.
+  const Progress& download_progress = display_metadata.progress;
+  const HoldingSpaceProgress progress(download_progress.received_bytes(),
+                                      download_progress.total_bytes(),
+                                      download_progress.complete());
 
   if (item_id_by_guid == item_ids_by_guids_.end() ||
       !HoldingSpaceController::Get()->model()->GetItem(
@@ -97,8 +101,6 @@
   const GURL file_system_url =
       holding_space_util::ResolveFileSystemUrl(profile(), file_path);
 
-  // TODO(http://b/307347158): Update the holding space item specified by
-  // `holding_space_item_id` with `display_metadata`.
   service->UpdateItem(item_id_by_guid->second)
       ->SetBackingFile(HoldingSpaceFile(
           file_path,
diff --git a/chrome/browser/ui/ash/download_status/holding_space_display_client_browsertest.cc b/chrome/browser/ui/ash/download_status/holding_space_display_client_browsertest.cc
index b6c67fc..3471bdd 100644
--- a/chrome/browser/ui/ash/download_status/holding_space_display_client_browsertest.cc
+++ b/chrome/browser/ui/ash/download_status/holding_space_display_client_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include <limits>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -493,6 +494,24 @@
 }
 
 IN_PROC_BROWSER_TEST_F(HoldingSpaceDisplayClientBrowserTest,
+                       IndeterminateDownload) {
+  // Create a download with an unknown total bytes count.
+  crosapi::mojom::DownloadStatusPtr download = CreateInProgressDownloadStatus(
+      ProfileManager::GetActiveUserProfile(), /*received_bytes=*/0,
+      /*target_bytes=*/std::nullopt);
+  Update(download->Clone());
+  test_api().Show();
+
+  // Verify the existence of a single download chip.
+  ASSERT_EQ(test_api().GetDownloadChips().size(), 1u);
+
+  // Complete the download and check the existence of the download chip.
+  download->state = crosapi::mojom::DownloadState::kComplete;
+  Update(download->Clone());
+  EXPECT_EQ(test_api().GetDownloadChips().size(), 1u);
+}
+
+IN_PROC_BROWSER_TEST_F(HoldingSpaceDisplayClientBrowserTest,
                        InterruptDownload) {
   crosapi::mojom::DownloadStatusPtr download = CreateInProgressDownloadStatus(
       ProfileManager::GetActiveUserProfile(), /*received_bytes=*/0,
diff --git a/chrome/browser/ui/ash/download_status/notification_display_client.cc b/chrome/browser/ui/ash/download_status/notification_display_client.cc
index 7feed9b..24d26dd 100644
--- a/chrome/browser/ui/ash/download_status/notification_display_client.cc
+++ b/chrome/browser/ui/ash/download_status/notification_display_client.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/ash/download_status/notification_display_client.h"
 
-#include <array>
 #include <optional>
 #include <utility>
 #include <vector>
@@ -34,6 +33,7 @@
 #include "ui/base/models/image_model.h"
 #include "ui/message_center/public/cpp/notification.h"
 #include "ui/message_center/public/cpp/notification_delegate.h"
+#include "ui/message_center/public/cpp/notification_types.h"
 #include "ui/message_center/public/cpp/notifier_id.h"
 #include "url/gurl.h"
 
@@ -48,10 +48,6 @@
 
 constexpr char kNotificationOrigin[] = "chrome://downloads";
 
-// The commands supported by notification buttons.
-constexpr std::array<CommandType, 3> kButtonCommands = {
-    CommandType::kCancel, CommandType::kPause, CommandType::kResume};
-
 // DownloadNotificationDelegate ------------------------------------------------
 
 class DownloadNotificationDelegate
@@ -158,29 +154,42 @@
   std::vector<base::RepeatingClosure> button_click_callbacks;
   std::vector<message_center::ButtonInfo> buttons;
   for (const auto& command_info : display_metadata.command_infos) {
-    if (base::Contains(kButtonCommands, command_info.type)) {
-      button_click_callbacks.push_back(command_info.command_callback);
-      buttons.emplace_back(l10n_util::GetStringUTF16(command_info.text_id));
+    switch (command_info.type) {
+      case CommandType::kCancel:
+      case CommandType::kPause:
+      case CommandType::kResume:
+        button_click_callbacks.push_back(command_info.command_callback);
+        buttons.emplace_back(l10n_util::GetStringUTF16(command_info.text_id));
+        break;
+      case CommandType::kShowInBrowser:
+        // NOTE: The `kShowInBrowser` command is associated with the
+        // notification body and is not rendered as a button.
+        break;
     }
   }
 
-  // Calculate progress from `display_metadata`.
-  int progress = 0;
-  const std::optional<int64_t>& received_bytes =
-      display_metadata.received_bytes;
-  const std::optional<int64_t>& total_bytes = display_metadata.total_bytes;
-  if (received_bytes >= 0 && total_bytes > 0) {
-    progress = *received_bytes * 100.f / *total_bytes;
-  } else {
-    // A negative progress value shows an indeterminate progress bar.
-    progress = -1;
+  // Calculate `progress_value` from `display_metadata`. Initialize with a
+  // negative value that shows an indeterminate progress bar.
+  int progress_value = -1;
+  const Progress& progress = display_metadata.progress;
+  const std::optional<int64_t>& received_bytes = progress.received_bytes();
+  const std::optional<int64_t>& total_bytes = progress.total_bytes();
+  const bool complete = progress.complete();
+  if (complete || (received_bytes && received_bytes == total_bytes)) {
+    // NOTE: `total_bytes` could be zero. Therefore, check the equality of
+    // `received_bytes` and `total_bytes` before division.
+    // In addition, the equality of `received_bytes` and `total_bytes` does not
+    // necessarily mean that `complete` is true.
+    progress_value = 100;
+  } else if (received_bytes >= 0 && total_bytes > 0) {
+    progress_value = *received_bytes * 100.f / *total_bytes;
   }
 
   message_center::RichNotificationData rich_notification_data;
   rich_notification_data.buttons = std::move(buttons);
   rich_notification_data.fullscreen_visibility =
       message_center::FullscreenVisibility::OVER_USER;
-  rich_notification_data.progress = progress;
+  rich_notification_data.progress = progress_value;
   rich_notification_data.progress_status =
       display_metadata.secondary_text.value_or(std::u16string());
   rich_notification_data.should_make_spoken_feedback_for_popup_updates = false;
@@ -204,16 +213,15 @@
           .SetOptionalFields(std::move(rich_notification_data))
           .SetOriginUrl(GURL(kNotificationOrigin))
           .SetTitle(display_metadata.text.value_or(std::u16string()))
-          .SetType(message_center::NOTIFICATION_TYPE_PROGRESS)
+          .SetType(complete ? message_center::NOTIFICATION_TYPE_SIMPLE
+                            : message_center::NOTIFICATION_TYPE_PROGRESS)
           .Build(/*keep_timestamp=*/false);
 
   NotificationDisplayService::GetForProfile(profile())->Display(
       NotificationHandler::Type::TRANSIENT, std::move(notification),
       /*metadata=*/nullptr);
 
-  // TODO(http://b/306459683): Change this code after `DisplayMetadata` uses a
-  // data structure to represent download progress.
-  if (received_bytes > 0 && received_bytes == total_bytes) {
+  if (complete) {
     // The download associated with `guid` completes. We no longer anticipate
     // receiving download updates. Therefore, remove `guid` from the collection.
     notifications_closed_by_user_guids_.erase(guid);
diff --git a/chrome/browser/ui/ash/download_status/notification_display_client_browsertest.cc b/chrome/browser/ui/ash/download_status/notification_display_client_browsertest.cc
index b28796c0..e6d6c1f 100644
--- a/chrome/browser/ui/ash/download_status/notification_display_client_browsertest.cc
+++ b/chrome/browser/ui/ash/download_status/notification_display_client_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <memory>
+#include <optional>
 #include <set>
 #include <string>
 #include <utility>
@@ -21,6 +22,7 @@
 #include "ash/system/status_area_widget.h"
 #include "ash/test/view_drawn_waiter.h"
 #include "base/ranges/algorithm.h"
+#include "base/run_loop.h"
 #include "base/scoped_observation.h"
 #include "base/test/bind.h"
 #include "base/test/gmock_callback_support.h"
@@ -49,6 +51,7 @@
 #include "ui/message_center/views/message_popup_view.h"
 #include "ui/message_center/views/notification_control_buttons_view.h"
 #include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/progress_bar.h"
 #include "ui/views/view_utils.h"
 #include "ui/wm/public/activation_client.h"
 
@@ -445,6 +448,15 @@
   Update(download->Clone());
   Mock::VerifyAndClearExpectations(&service_observer());
 
+  // Verify that the notification view of an in-progress download has a visible
+  // progress bar.
+  AshNotificationView* popup_view = GetPopupView(profile, notification_id);
+  ASSERT_TRUE(popup_view);
+  const views::ProgressBar* const progress_bar =
+      popup_view->progress_bar_view_for_testing();
+  ASSERT_TRUE(progress_bar);
+  EXPECT_TRUE(progress_bar->GetVisible());
+
   // Complete download and then check the notification.
   download->received_bytes = download->total_bytes;
   download->state = crosapi::mojom::DownloadState::kComplete;
@@ -457,6 +469,12 @@
           _));
   Update(download->Clone());
   EXPECT_THAT(GetDisplayedNotificationIds(), Contains(notification_id));
+
+  // Verify that the notification view of a completed download does not have
+  // a progress bar.
+  popup_view = GetPopupView(profile, notification_id);
+  ASSERT_TRUE(popup_view);
+  EXPECT_FALSE(popup_view->progress_bar_view_for_testing());
 }
 
 // Verifies that a download notification should not show again if it has been
@@ -498,6 +516,46 @@
   EXPECT_THAT(GetDisplayedNotificationIds(), Not(Contains(notification_id)));
 }
 
+// Verifies that the notification of a download with an unknown total bytes
+// count works as expected.
+IN_PROC_BROWSER_TEST_F(NotificationDisplayClientBrowserTest,
+                       IndeterminateDownload) {
+  std::string notification_id;
+  EXPECT_CALL(service_observer(), OnNotificationDisplayed)
+      .WillOnce(WithArg<0>(
+          [&notification_id](const message_center::Notification& notification) {
+            notification_id = notification.id();
+          }));
+
+  Profile* const profile = ProfileManager::GetActiveUserProfile();
+  crosapi::mojom::DownloadStatusPtr download =
+      CreateInProgressDownloadStatus(profile, /*received_bytes=*/0,
+                                     /*target_bytes=*/std::nullopt);
+
+  Update(download->Clone());
+  Mock::VerifyAndClearExpectations(&service_observer());
+
+  // Verify that the notification view of an in-progress download has a visible
+  // progress bar.
+  AshNotificationView* popup_view = GetPopupView(profile, notification_id);
+  ASSERT_TRUE(popup_view);
+  const views::ProgressBar* const progress_bar =
+      popup_view->progress_bar_view_for_testing();
+  ASSERT_TRUE(progress_bar);
+  EXPECT_TRUE(progress_bar->GetVisible());
+
+  // Complete the download. Check the existence of the associated notification.
+  download->state = crosapi::mojom::DownloadState::kComplete;
+  Update(download->Clone());
+  EXPECT_THAT(GetDisplayedNotificationIds(), Contains(notification_id));
+
+  // Verify that the notification view of a completed download does not have
+  // a progress bar.
+  popup_view = GetPopupView(profile, notification_id);
+  ASSERT_TRUE(popup_view);
+  EXPECT_FALSE(popup_view->progress_bar_view_for_testing());
+}
+
 // Verifies that when an in-progress download is interrupted, its notification
 // should be removed.
 IN_PROC_BROWSER_TEST_F(NotificationDisplayClientBrowserTest,
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc
index 85e0af7..a3af6122 100644
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc
@@ -7,6 +7,7 @@
 #include <utility>
 #include <vector>
 
+#include "ash/constants/ash_features.h"
 #include "ash/keyboard/ui/keyboard_ui_controller.h"
 #include "ash/keyboard/ui/resources/keyboard_resource_util.h"
 #include "ash/public/cpp/keyboard/keyboard_switches.h"
@@ -397,13 +398,21 @@
 void ChromeKeyboardControllerClient::OnSessionStateChanged() {
   TRACE_EVENT0("login",
                "ChromeKeyboardControllerClient::OnSessionStateChanged");
-  if (!session_manager::SessionManager::Get()->IsSessionStarted()) {
-    // Reset the registrar so that prefs are re-registered after a crash.
+  if (base::FeatureList::IsEnabled(
+          ash::features::kTouchVirtualKeyboardPolicyListenPrefsAtLogin)) {
+    // We need to listen for pref changes even in login screen to control the
+    // virtual keyboard behavior on the login screen.
     pref_change_registrar_.RemoveAll();
-    return;
+  } else {
+    if (!session_manager::SessionManager::Get()->IsSessionStarted()) {
+      // Reset the registrar so that prefs are re-registered after a crash.
+      pref_change_registrar_.RemoveAll();
+      return;
+    }
+    if (!pref_change_registrar_.IsEmpty()) {
+      return;
+    }
   }
-  if (!pref_change_registrar_.IsEmpty())
-    return;
 
   Profile* profile = ProfileManager::GetPrimaryUserProfile();
   pref_change_registrar_.Init(profile->GetPrefs());
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller.cc
index bf784c9f..d55f490a 100644
--- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller.cc
+++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller.cc
@@ -1525,12 +1525,15 @@
 void ChromeShelfController::UpdateForcedPinStateForItemAtIndex(
     int model_index) {
   ash::ShelfItem item = model_->items()[model_index];
-  auto app_type = apps::AppServiceProxyFactory::GetForProfile(profile())
-                      ->AppRegistryCache()
-                      .GetAppType(item.id.app_id);
+  bool pin_state_forced_by_type = true;
 
-  const bool pin_state_forced_by_type =
-      !IsAppPinEditable(app_type, item.id.app_id, profile());
+  if (item.type == ash::TYPE_PINNED_APP || item.type == ash::TYPE_APP) {
+    auto app_type = apps::AppServiceProxyFactory::GetForProfile(profile())
+                        ->AppRegistryCache()
+                        .GetAppType(item.id.app_id);
+    pin_state_forced_by_type =
+        !IsAppPinEditable(app_type, item.id.app_id, profile());
+  }
   if (item.pin_state_forced_by_type != pin_state_forced_by_type) {
     item.pin_state_forced_by_type = pin_state_forced_by_type;
     model_->Set(model_index, item);
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc
index a9d9652..b14679e 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -52,6 +52,9 @@
 #include "chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h"
 #include "chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl.h"
 #include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/browser/ui/hats/hats_service.h"
+#include "chrome/browser/ui/hats/hats_service_factory.h"
+#include "chrome/browser/ui/hats/survey_config.h"
 #include "chrome/browser/ui/page_info/page_info_dialog.h"
 #include "chrome/browser/ui/passwords/ui_utils.h"
 #include "chrome/browser/ui/plus_addresses/plus_address_creation_controller.h"
@@ -1218,6 +1221,27 @@
       autofill_progress_dialog_type, std::move(cancel_callback));
 }
 
+void ChromeAutofillClient::TriggerUserPerceptionOfAutofillSurvey(
+    const std::map<std::string, std::string>& field_filling_stats_data) {
+#if !BUILDFLAG(IS_ANDROID)
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
+  HatsService* hats_service =
+      HatsServiceFactory::GetForProfile(profile, /*create_if_necessary=*/true);
+  CHECK(hats_service);
+  // Also add information about whether the granular filling feature is
+  // available". The goal is to correlate the user's perception of autofill with
+  // the feature.
+  hats_service->LaunchDelayedSurveyForWebContents(
+      kHatsSurveyTriggerAutofillAddressUserPerception, web_contents(),
+      /*timeout_ms=*/10000, /*product_specific_bits_data=*/
+      {{"granular filling available",
+        base::FeatureList::IsEnabled(
+            features::kAutofillGranularFillingAvailable)}},
+      field_filling_stats_data);
+#endif
+}
+
 void ChromeAutofillClient::CloseAutofillProgressDialog(
     bool show_confirmation_before_closing,
     base::OnceClosure no_interactive_authentication_callback) {
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h
index d706d3f..5c01a3b0 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.h
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -18,6 +18,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.h"
 #include "chrome/browser/ui/autofill/payments/autofill_progress_dialog_controller_impl.h"
+#include "chrome/browser/ui/hats/hats_service_desktop.h"
 #include "components/autofill/content/browser/content_autofill_client.h"
 #include "components/autofill/core/browser/autofill_driver.h"
 #include "components/autofill/core/browser/country_type.h"
@@ -267,6 +268,9 @@
   void ShowAutofillProgressDialog(
       AutofillProgressDialogType autofill_progress_dialog_type,
       base::OnceClosure cancel_callback) override;
+  void TriggerUserPerceptionOfAutofillSurvey(
+      const std::map<std::string, std::string>& field_filling_stats_data)
+      override;
   void CloseAutofillProgressDialog(
       bool show_confirmation_before_closing,
       base::OnceClosure no_interactive_authentication_callback) override;
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 49297d66..51e81e6 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -565,7 +565,6 @@
   kDefault,
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
     BUILDFLAG(IS_FUCHSIA)
-  kEnabledWithLaunchOption,
   kEnabledWithNoLaunch,
   kDisabled,
 #endif
@@ -581,9 +580,6 @@
       break;
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
     BUILDFLAG(IS_FUCHSIA)
-    case ChromeAppDeprecationFeatureValue::kEnabledWithLaunchOption:
-      result = "ChromeAppDeprecationFeatureEnabledWithLaunchOption";
-      break;
     case ChromeAppDeprecationFeatureValue::kEnabledWithNoLaunch:
       result = "ChromeAppDeprecationFeatureEnabledWithNoLaunch";
       break;
@@ -607,23 +603,9 @@
         break;
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
     BUILDFLAG(IS_FUCHSIA)
-      case ChromeAppDeprecationFeatureValue::kEnabledWithLaunchOption:
-        scoped_feature_list_.InitWithFeaturesAndParameters(
-            {{ features::kChromeAppsDeprecation,
-               {
-                 { "HideLaunchAnyways",
-                   "false" }
-               } }},
-            {});
-        break;
       case ChromeAppDeprecationFeatureValue::kEnabledWithNoLaunch:
-        scoped_feature_list_.InitWithFeaturesAndParameters(
-            {{ features::kChromeAppsDeprecation,
-               {
-                 { "HideLaunchAnyways",
-                   "true" }
-               } }},
-            {});
+        scoped_feature_list_.InitAndEnableFeature(
+            features::kChromeAppsDeprecation);
         break;
       case ChromeAppDeprecationFeatureValue::kDisabled:
         scoped_feature_list_.InitAndDisableFeature(
@@ -680,10 +662,8 @@
 
   enum class ExpectedLaunchBehavior{kLaunchAnywaysInTab, kLaunchAnywaysInWindow,
                                     kNoLaunch};
-  Browser* ExpectBlockLaunchWithLaunchBehavior(
-      const std::string& app_id,
-      bool force_install_dialog,
-      ExpectedLaunchBehavior behavior) {
+  void ExpectBlockLaunchWithLaunchBehavior(const std::string& app_id,
+                                           bool force_install_dialog) {
     EXPECT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
     auto waiter = views::NamedWidgetShownWaiter(
         views::test::AnyWidgetTestPasskey{},
@@ -733,68 +713,21 @@
       dialog->widget_delegate()->AsDialogDelegate()->Cancel();
     }
 
-    switch (behavior) {
-      case ExpectedLaunchBehavior::kLaunchAnywaysInTab:
-        same_tab_observer.Wait();
-        return other_browser;
-      case ExpectedLaunchBehavior::kLaunchAnywaysInWindow: {
-        Browser* app_browser =
-            ui_test_utils::GetBrowserNotInSet(initial_browsers);
-        if (!app_browser) {
-          app_browser = ui_test_utils::WaitForBrowserToOpen();
-          // The new browser should never be in |excluded_browsers|.
-          DCHECK(!base::Contains(initial_browsers, app_browser));
-        }
-        DCHECK(app_browser);
-        TabStripModel* app_tab_strip = app_browser->tab_strip_model();
-        EXPECT_EQ(1, app_tab_strip->count());
-        EXPECT_TRUE(app_browser->is_type_app());
-        EXPECT_FALSE(app_browser->is_type_normal());
-        return app_browser;
-      }
-      case ExpectedLaunchBehavior::kNoLaunch:
-        // To ensure that no launch happens, run the run loop until idle.
-        base::RunLoop().RunUntilIdle();
-        Browser* app_browser =
-            ui_test_utils::GetBrowserNotInSet(initial_browsers);
-        EXPECT_EQ(app_browser, nullptr);
-        return nullptr;
-    }
+    // To ensure that no launch happens, run the run loop until idle.
+    base::RunLoop().RunUntilIdle();
+    Browser* app_browser = ui_test_utils::GetBrowserNotInSet(initial_browsers);
+    EXPECT_EQ(app_browser, nullptr);
   }
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 
   bool IsExpectedToAllowLaunch() {
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
     BUILDFLAG(IS_FUCHSIA)
-    // Under no circumstance can the kChromeAppsDeprecation flag be used to
-    // globally disable deprecation.
-    switch (GetParam()) {
-      case ChromeAppDeprecationFeatureValue::kEnabledWithLaunchOption:
-      case ChromeAppDeprecationFeatureValue::kEnabledWithNoLaunch:
-      case ChromeAppDeprecationFeatureValue::kDefault:
-      case ChromeAppDeprecationFeatureValue::kDisabled:
-        return false;
-    }
-#endif
+    return false;
+#else
     return true;
-  }
-
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-  ExpectedLaunchBehavior GetLaunchBehaviorExpected(bool would_launch_tab) {
-    switch (GetParam()) {
-      case ChromeAppDeprecationFeatureValue::kEnabledWithLaunchOption:
-        return would_launch_tab
-                   ? ExpectedLaunchBehavior::kLaunchAnywaysInTab
-                   : ExpectedLaunchBehavior::kLaunchAnywaysInWindow;
-      case ChromeAppDeprecationFeatureValue::kEnabledWithNoLaunch:
-      case ChromeAppDeprecationFeatureValue::kDefault:
-      case ChromeAppDeprecationFeatureValue::kDisabled:
-        // Under no circumstance can the kChromeAppsDeprecation flag be used to
-        // globally disable deprecation.
-        return ExpectedLaunchBehavior::kNoLaunch;
-    }
-  }
 #endif
+  }
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -986,7 +919,6 @@
         ChromeAppDeprecationFeatureValue::kDefault
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
         ,
-        ChromeAppDeprecationFeatureValue::kEnabledWithLaunchOption,
         ChromeAppDeprecationFeatureValue::kEnabledWithNoLaunch,
         ChromeAppDeprecationFeatureValue::kDisabled
 #endif
@@ -1017,26 +949,10 @@
       command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       {browser()->profile(), StartupProfileMode::kBrowserWindow}, {}));
 
-  ExpectedLaunchBehavior launch_behavior =
-      GetLaunchBehaviorExpected(/*would_launch_tab=*/true);
-  Browser* tabbed_browser = ExpectBlockLaunchWithLaunchBehavior(
-      extension_app->id(),
-      /*force_install_dialog=*/false, launch_behavior);
+  ExpectBlockLaunchWithLaunchBehavior(extension_app->id(),
+                                      /*force_install_dialog=*/false);
 
-  if (launch_behavior == ExpectedLaunchBehavior::kNoLaunch) {
-    ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
-    return;
-  }
-  // When we block the launch, we always create a new browser window to
-  // display chrome://apps and the dialog. After launch, the tab should open to
-  // the extension.
   ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
-  tab_strip = tabbed_browser->tab_strip_model();
-  EXPECT_EQ(1, tab_strip->count());
-
-  // It should be a standard tabbed window, not an app window.
-  EXPECT_FALSE(tabbed_browser->is_type_app());
-  EXPECT_TRUE(tabbed_browser->is_type_normal());
 }
 
 IN_PROC_BROWSER_TEST_P(StartupBrowserCreatorChromeAppShortcutTestWithLaunch,
@@ -1056,33 +972,10 @@
       command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       {browser()->profile(), StartupProfileMode::kBrowserWindow}, {}));
 
-  ExpectedLaunchBehavior launch_behavior =
-      GetLaunchBehaviorExpected(/*would_launch_tab=*/false);
-  Browser* app_browser = ExpectBlockLaunchWithLaunchBehavior(
-      extension_app->id(),
-      /*force_install_dialog=*/false, launch_behavior);
+  ExpectBlockLaunchWithLaunchBehavior(extension_app->id(),
+                                      /*force_install_dialog=*/false);
 
-  if (launch_behavior == ExpectedLaunchBehavior::kNoLaunch) {
-    ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
-    return;
-  }
-
-  // When we block the launch, we always create a new browser window to
-  // display chrome://apps and the dialog, and then another to launch the app.
-  ASSERT_EQ(3u, chrome::GetBrowserCount(browser()->profile()));
-
-  // Pref was set to open in a window, so the app should have opened in a
-  // window.  The launch should have created a new browser. Find the new
-  // browser.
-  ASSERT_TRUE(app_browser);
-
-  // Expect an app window.
-  EXPECT_TRUE(app_browser->is_type_app());
-
-  // The browser's app_name should include the app's ID.
-  EXPECT_NE(app_browser->app_name().find(extension_app->id()),
-            std::string::npos)
-      << app_browser->app_name();
+  ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
 }
 
 IN_PROC_BROWSER_TEST_P(StartupBrowserCreatorChromeAppShortcutTestWithLaunch,
@@ -1105,27 +998,10 @@
       command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       {browser()->profile(), StartupProfileMode::kBrowserWindow}, {}));
 
-  ExpectedLaunchBehavior launch_behavior =
-      GetLaunchBehaviorExpected(/*would_launch_tab=*/true);
-  Browser* tabbed_browser = ExpectBlockLaunchWithLaunchBehavior(
-      extension_app->id(),
-      /*force_install_dialog=*/false, launch_behavior);
+  ExpectBlockLaunchWithLaunchBehavior(extension_app->id(),
+                                      /*force_install_dialog=*/false);
 
-  if (launch_behavior == ExpectedLaunchBehavior::kNoLaunch) {
-    ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
-    return;
-  }
-  // When we block the launch, we always create a new browser window to
-  // display chrome://apps and the dialog.
   ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
-  tab_strip = tabbed_browser->tab_strip_model();
-  EXPECT_EQ(1, tab_strip->count());
-
-  // The browser's app_name should not include the app's ID: it is in a normal
-  // tabbed browser.
-  EXPECT_EQ(tabbed_browser->app_name().find(extension_app->id()),
-            std::string::npos)
-      << browser()->app_name();
 }
 
 IN_PROC_BROWSER_TEST_P(StartupBrowserCreatorChromeAppShortcutTestWithLaunch,
@@ -1154,26 +1030,10 @@
       command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       {browser()->profile(), StartupProfileMode::kBrowserWindow}, {}));
 
-  ExpectedLaunchBehavior launch_behavior =
-      GetLaunchBehaviorExpected(/*would_launch_tab=*/true);
-  Browser* tabbed_browser = ExpectBlockLaunchWithLaunchBehavior(
-      extension_app->id(),
-      /*force_install_dialog=*/true, launch_behavior);
+  ExpectBlockLaunchWithLaunchBehavior(extension_app->id(),
+                                      /*force_install_dialog=*/true);
 
-  if (launch_behavior == ExpectedLaunchBehavior::kNoLaunch) {
-    ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
-    return;
-  }
-
-  // When we block the launch, we always create a new browser window to
-  // display chrome://apps and the dialog.
   ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
-  tab_strip = tabbed_browser->tab_strip_model();
-  EXPECT_EQ(1, tab_strip->count());
-
-  // It should be a standard tabbed window, not an app window.
-  EXPECT_FALSE(tabbed_browser->is_type_app());
-  EXPECT_TRUE(tabbed_browser->is_type_normal());
 }
 
 // These tests are specifically for testing what happens when the "Launch
@@ -1182,7 +1042,6 @@
     All,
     StartupBrowserCreatorChromeAppShortcutTestWithLaunch,
     ::testing::Values(
-        ChromeAppDeprecationFeatureValue::kEnabledWithLaunchOption,
         ChromeAppDeprecationFeatureValue::kEnabledWithNoLaunch),
     ChromeAppDeprecationFeatureValueToString);
 
diff --git a/chrome/browser/ui/tab_dialogs.h b/chrome/browser/ui/tab_dialogs.h
index 938193b..2942c851 100644
--- a/chrome/browser/ui/tab_dialogs.h
+++ b/chrome/browser/ui/tab_dialogs.h
@@ -54,14 +54,12 @@
   virtual void ShowDeprecatedAppsDialog(
       const extensions::ExtensionId& optional_launched_extension_id,
       const std::set<extensions::ExtensionId>& deprecated_app_ids,
-      content::WebContents* web_contents,
-      base::OnceClosure launch_anyways) = 0;
+      content::WebContents* web_contents) = 0;
 
   // Shows the force installed and deprecated app dialog.
   virtual void ShowForceInstalledDeprecatedAppsDialog(
       const extensions::ExtensionId& app_id,
-      content::WebContents* web_contents,
-      base::OnceClosure launch_anyways) = 0;
+      content::WebContents* web_contents) = 0;
 
   // Shows the force installed and deprecated app dialog.
   virtual void ShowForceInstalledPreinstalledDeprecatedAppDialog(
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
index d7813696..ed360472 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
@@ -240,12 +240,10 @@
   void ShowDeprecatedAppsDialog(
       const extensions::ExtensionId& optional_launched_extension_id,
       const std::set<extensions::ExtensionId>& deprecated_app_ids,
-      content::WebContents* web_contents,
-      base::OnceClosure launch_anyways) override {}
+      content::WebContents* web_contents) override {}
   void ShowForceInstalledDeprecatedAppsDialog(
       const extensions::ExtensionId& app_id,
-      content::WebContents* web_contents,
-      base::OnceClosure launch_anyways) override {}
+      content::WebContents* web_contents) override {}
   void ShowForceInstalledPreinstalledDeprecatedAppDialog(
       const extensions::ExtensionId& app_id,
       content::WebContents* web_contents) override {}
diff --git a/chrome/browser/ui/views/tab_dialogs_views.cc b/chrome/browser/ui/views/tab_dialogs_views.cc
index 52c0833..8b69835 100644
--- a/chrome/browser/ui/views/tab_dialogs_views.cc
+++ b/chrome/browser/ui/views/tab_dialogs_views.cc
@@ -84,22 +84,19 @@
 void TabDialogsViews::ShowDeprecatedAppsDialog(
     const extensions::ExtensionId& optional_launched_extension_id,
     const std::set<extensions::ExtensionId>& deprecated_app_ids,
-    content::WebContents* web_contents,
-    base::OnceClosure launch_anyways) {
+    content::WebContents* web_contents) {
 #if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_CHROMEOS)
   DeprecatedAppsDialogView::CreateAndShowDialog(
-      optional_launched_extension_id, deprecated_app_ids, web_contents,
-      std::move(launch_anyways));
+      optional_launched_extension_id, deprecated_app_ids, web_contents);
 #endif
 }
 
 void TabDialogsViews::ShowForceInstalledDeprecatedAppsDialog(
     const extensions::ExtensionId& app_id,
-    content::WebContents* web_contents,
-    base::OnceClosure launch_anyways) {
+    content::WebContents* web_contents) {
 #if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_CHROMEOS)
-  ForceInstalledDeprecatedAppsDialogView::CreateAndShowDialog(
-      app_id, web_contents, std::move(launch_anyways));
+  ForceInstalledDeprecatedAppsDialogView::CreateAndShowDialog(app_id,
+                                                              web_contents);
 #endif
 }
 
diff --git a/chrome/browser/ui/views/tab_dialogs_views.h b/chrome/browser/ui/views/tab_dialogs_views.h
index 3e3125e..f1cf9080 100644
--- a/chrome/browser/ui/views/tab_dialogs_views.h
+++ b/chrome/browser/ui/views/tab_dialogs_views.h
@@ -32,12 +32,10 @@
   void ShowDeprecatedAppsDialog(
       const extensions::ExtensionId& optional_launched_extension_id,
       const std::set<extensions::ExtensionId>& deprecated_app_ids,
-      content::WebContents* web_contents,
-      base::OnceClosure launch_anyways) override;
+      content::WebContents* web_contents) override;
   void ShowForceInstalledDeprecatedAppsDialog(
       const extensions::ExtensionId& app_id,
-      content::WebContents* web_contents,
-      base::OnceClosure launch_anyways) override;
+      content::WebContents* web_contents) override;
   void ShowForceInstalledPreinstalledDeprecatedAppDialog(
       const extensions::ExtensionId& app_id,
       content::WebContents* web_contents) override;
diff --git a/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view.cc b/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view.cc
index 437e834e..6151d32 100644
--- a/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view.cc
+++ b/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view.cc
@@ -115,11 +115,9 @@
 DeprecatedAppsDialogView* DeprecatedAppsDialogView::CreateAndShowDialog(
     const extensions::ExtensionId& optional_launched_extension_id,
     const std::set<extensions::ExtensionId>& deprecated_app_ids,
-    content::WebContents* web_contents,
-    base::OnceClosure launch_anyways) {
+    content::WebContents* web_contents) {
   DeprecatedAppsDialogView* view = new DeprecatedAppsDialogView(
-      optional_launched_extension_id, deprecated_app_ids, web_contents,
-      std::move(launch_anyways));
+      optional_launched_extension_id, deprecated_app_ids, web_contents);
   view->InitDialog();
   constrained_window::ShowWebModalDialogViews(view, web_contents);
   return view;
@@ -148,11 +146,8 @@
 DeprecatedAppsDialogView::DeprecatedAppsDialogView(
     const extensions::ExtensionId& optional_launched_extension_id,
     const std::set<extensions::ExtensionId>& deprecated_app_ids,
-    content::WebContents* web_contents,
-    base::OnceClosure launch_anyways)
-    : deprecated_app_ids_(deprecated_app_ids),
-      launch_anyways_(std::move(launch_anyways)),
-      web_contents_(web_contents) {
+    content::WebContents* web_contents)
+    : deprecated_app_ids_(deprecated_app_ids), web_contents_(web_contents) {
   if (!optional_launched_extension_id.empty()) {
     const extensions::Extension* extension =
         extensions::ExtensionRegistry::Get(web_contents_->GetBrowserContext())
@@ -193,16 +188,8 @@
   SetAcceptCallback(base::BindOnce(&DeprecatedAppsDialogView::OnAccept,
                                    base::Unretained(this)));
 
-  bool hide_launch_anyways =
-      features::kChromeAppsDeprecationHideLaunchAnyways.Get();
-  if (launched_extension_name_ && !hide_launch_anyways) {
-    SetButtonLabel(
-        ui::DIALOG_BUTTON_CANCEL,
-        l10n_util::GetStringUTF16(IDS_DEPRECATED_APPS_LAUNCH_ANYWAY_LABEL));
-  } else {
     SetButtonLabel(ui::DIALOG_BUTTON_CANCEL,
                    l10n_util::GetStringUTF16(IDS_DEPRECATED_APPS_CANCEL_LABEL));
-  }
   SetCancelCallback(base::BindOnce(&DeprecatedAppsDialogView::OnCancel,
                                    base::Unretained(this)));
 
@@ -269,11 +256,6 @@
 }
 
 void DeprecatedAppsDialogView::OnCancel() {
-  bool hide_launch_anyways =
-      features::kChromeAppsDeprecationHideLaunchAnyways.Get();
-  if (!hide_launch_anyways) {
-    std::move(launch_anyways_).Run();
-  }
   CloseDialog();
 }
 
diff --git a/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view.h b/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view.h
index d6cbe5c..7773930 100644
--- a/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view.h
+++ b/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view.h
@@ -35,6 +35,8 @@
 class TableModel;
 }
 
+// Creates a dialog with two buttons. "Accept" causes the extension to be
+// uninstalled and closes the dialog. "Cancel" closes the dialog.
 class DeprecatedAppsDialogView : public views::DialogDelegateView {
   METADATA_HEADER(DeprecatedAppsDialogView, views::DialogDelegateView)
 
@@ -55,8 +57,7 @@
   static DeprecatedAppsDialogView* CreateAndShowDialog(
       const extensions::ExtensionId& optional_launched_extension_id,
       const std::set<extensions::ExtensionId>& deprecated_app_ids,
-      content::WebContents* web_contents,
-      base::OnceClosure launch_anyways);
+      content::WebContents* web_contents);
 
   base::WeakPtr<DeprecatedAppsDialogView> AsWeakPtr();
 
@@ -70,8 +71,7 @@
   DeprecatedAppsDialogView(
       const extensions::ExtensionId& optional_launched_extension_id,
       const std::set<extensions::ExtensionId>& deprecated_app_ids,
-      content::WebContents* web_contents,
-      base::OnceClosure launch_anyways);
+      content::WebContents* web_contents);
 
   // Initialize the dialog when the object is instantiated.
   void InitDialog();
@@ -98,7 +98,6 @@
   std::optional<std::u16string> launched_extension_name_;
   std::set<extensions::ExtensionId> deprecated_app_ids_;
   std::optional<std::u16string> single_app_name_;
-  base::OnceClosure launch_anyways_;
 
   raw_ptr<content::WebContents, AcrossTasksDanglingUntriaged> web_contents_;
 
diff --git a/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view_browsertest.cc b/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view_browsertest.cc
index fadf3f77..17101401 100644
--- a/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/deprecated_apps_dialog_view_browsertest.cc
@@ -6,17 +6,13 @@
 
 #include <set>
 
-#include "base/feature_list.h"
 #include "base/functional/callback_helpers.h"
 #include "base/run_loop.h"
 #include "base/strings/string_piece.h"
 #include "base/test/bind.h"
-#include "base/test/mock_callback.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/ui_features.h"
-#include "chrome/common/chrome_features.h"
 #include "chrome/common/logging_chrome.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -84,27 +80,10 @@
   base::RunLoop run_loop_;
 };
 
-enum class HideLaunchAnywaysOption { kHide, kShow };
-
 class DeprecatedAppsDialogViewBrowserTest
-    : public extensions::ExtensionBrowserTest,
-      public testing::WithParamInterface<HideLaunchAnywaysOption> {
+    : public extensions::ExtensionBrowserTest {
  public:
   DeprecatedAppsDialogViewBrowserTest() {
-    switch (GetParam()) {
-      case HideLaunchAnywaysOption::kShow:
-        feature_list_.InitWithFeaturesAndParameters(
-            {{features::kChromeAppsDeprecation,
-              {{"HideLaunchAnyways", "false"}}}},
-            {});
-        break;
-      case HideLaunchAnywaysOption::kHide:
-        feature_list_.InitWithFeaturesAndParameters(
-            {{features::kChromeAppsDeprecation,
-              {{"HideLaunchAnyways", "true"}}}},
-            {});
-        break;
-    }
   }
 
   DeprecatedAppsDialogViewBrowserTest(
@@ -169,52 +148,49 @@
  protected:
   std::set<extensions::ExtensionId> deprecated_app_ids_for_testing_;
   base::WeakPtr<DeprecatedAppsDialogView> test_dialog_view_;
-  base::test::ScopedFeatureList feature_list_;
 };
 
-IN_PROC_BROWSER_TEST_P(DeprecatedAppsDialogViewBrowserTest,
+IN_PROC_BROWSER_TEST_F(DeprecatedAppsDialogViewBrowserTest,
                        VerifyTableModelForSingleApp) {
   auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
 
   InstallExtensionForTesting(mock_app_manifest1, mock_url1);
-  test_dialog_view_ = DeprecatedAppsDialogView::CreateAndShowDialog(
-                          std::string(), deprecated_app_ids_for_testing_,
-                          web_contents, base::DoNothing())
-                          ->AsWeakPtr();
+  test_dialog_view_ =
+      DeprecatedAppsDialogView::CreateAndShowDialog(
+          std::string(), deprecated_app_ids_for_testing_, web_contents)
+          ->AsWeakPtr();
 
   EXPECT_TRUE(IsDialogShown());
   EXPECT_EQ(static_cast<int>(deprecated_app_ids_for_testing_.size()),
             GetRowCountForDialog());
 }
 
-IN_PROC_BROWSER_TEST_P(DeprecatedAppsDialogViewBrowserTest,
+IN_PROC_BROWSER_TEST_F(DeprecatedAppsDialogViewBrowserTest,
                        VerifyTableModelForMultipleApps) {
   auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
 
   InstallExtensionForTesting(mock_app_manifest1, mock_url1);
   InstallExtensionForTesting(mock_app_manifest2, mock_url2);
-  test_dialog_view_ = DeprecatedAppsDialogView::CreateAndShowDialog(
-                          std::string(), deprecated_app_ids_for_testing_,
-                          web_contents, base::DoNothing())
-                          ->AsWeakPtr();
+  test_dialog_view_ =
+      DeprecatedAppsDialogView::CreateAndShowDialog(
+          std::string(), deprecated_app_ids_for_testing_, web_contents)
+          ->AsWeakPtr();
 
   EXPECT_TRUE(IsDialogShown());
   EXPECT_EQ(static_cast<int>(deprecated_app_ids_for_testing_.size()),
             GetRowCountForDialog());
 }
 
-IN_PROC_BROWSER_TEST_P(DeprecatedAppsDialogViewBrowserTest,
+IN_PROC_BROWSER_TEST_F(DeprecatedAppsDialogViewBrowserTest,
                        AcceptDialogAndVerify) {
   auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
 
-  base::MockCallback<base::OnceClosure> mock_callback;
   extensions::ExtensionId test_id(
       InstallExtensionForTesting(mock_app_manifest1, mock_url1));
-  test_dialog_view_ = DeprecatedAppsDialogView::CreateAndShowDialog(
-                          std::string(), deprecated_app_ids_for_testing_,
-                          web_contents, mock_callback.Get())
-                          ->AsWeakPtr();
-  EXPECT_CALL(mock_callback, Run()).Times(0);
+  test_dialog_view_ =
+      DeprecatedAppsDialogView::CreateAndShowDialog(
+          std::string(), deprecated_app_ids_for_testing_, web_contents)
+          ->AsWeakPtr();
 
   // Verify dialog is shown.
   ASSERT_TRUE(IsDialogShown());
@@ -232,42 +208,14 @@
           ->GetInstalledExtension(test_id) == nullptr);
 }
 
-IN_PROC_BROWSER_TEST_P(DeprecatedAppsDialogViewBrowserTest,
-                       CloseDialogAndVerify) {
-  auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
-
-  base::MockCallback<base::OnceClosure> mock_callback;
-  InstallExtensionForTesting(mock_app_manifest1, mock_url1);
-  test_dialog_view_ = DeprecatedAppsDialogView::CreateAndShowDialog(
-                          std::string(), deprecated_app_ids_for_testing_,
-                          web_contents, mock_callback.Get())
-                          ->AsWeakPtr();
-
-  // Verify dialog is shown.
-  ASSERT_TRUE(IsDialogShown());
-  EXPECT_EQ(static_cast<int>(deprecated_app_ids_for_testing_.size()),
-            GetRowCountForDialog());
-
-  if (GetParam() == HideLaunchAnywaysOption::kShow) {
-    EXPECT_CALL(mock_callback, Run()).Times(1);
-  } else {
-    EXPECT_CALL(mock_callback, Run()).Times(0);
-  }
-
-  // Verify dialog is closed on cancellation
-  ASSERT_TRUE(test_dialog_view_->Cancel());
-  WaitForDialogToBeDestroyed();
-  ASSERT_FALSE(IsDialogShown());
-}
-
-IN_PROC_BROWSER_TEST_P(DeprecatedAppsDialogViewBrowserTest,
+IN_PROC_BROWSER_TEST_F(DeprecatedAppsDialogViewBrowserTest,
                        DialogDoesNotLoadOnNavigationToChromeApps) {
   ASSERT_TRUE(
       ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIAppsURL)));
   ASSERT_FALSE(IsDialogShown());
 }
 
-IN_PROC_BROWSER_TEST_P(DeprecatedAppsDialogViewBrowserTest,
+IN_PROC_BROWSER_TEST_F(DeprecatedAppsDialogViewBrowserTest,
                        DeprecatedAppsDialogShownFromLinkClick) {
   auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
   InstallExtensionForTesting(mock_app_manifest1, mock_url1);
@@ -280,17 +228,3 @@
       content::EvalJs(web_contents, ClickDeprecatedDialogLinkString());
   EXPECT_NE(waiter.WaitIfNeededAndGet(), nullptr);
 }
-
-INSTANTIATE_TEST_SUITE_P(
-    All,
-    DeprecatedAppsDialogViewBrowserTest,
-    ::testing::Values(HideLaunchAnywaysOption::kShow,
-                      HideLaunchAnywaysOption::kHide),
-    [](const ::testing::TestParamInfo<HideLaunchAnywaysOption> info) {
-      switch (info.param) {
-        case HideLaunchAnywaysOption::kShow:
-          return "ShowLaunchAnyways";
-        case HideLaunchAnywaysOption::kHide:
-          return "HideLaunchAnyways";
-      }
-    });
diff --git a/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view.cc b/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view.cc
index d713268..0764338 100644
--- a/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view.cc
+++ b/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view.cc
@@ -27,8 +27,7 @@
 // static
 void ForceInstalledDeprecatedAppsDialogView::CreateAndShowDialog(
     const extensions::ExtensionId& app_id,
-    content::WebContents* web_contents,
-    base::OnceClosure launch_anyways) {
+    content::WebContents* web_contents) {
   auto delegate = std::make_unique<views::DialogDelegate>();
   delegate->SetModalType(ui::MODAL_TYPE_CHILD);
   delegate->SetShowCloseButton(false);
@@ -40,16 +39,7 @@
   std::u16string app_name = base::UTF8ToUTF16(extension->name());
   delegate->SetTitle(l10n_util::GetStringFUTF16(
       IDS_DEPRECATED_APPS_RENDERER_TITLE_WITH_APP_NAME, app_name));
-  bool hide_launch_anyways =
-      features::kChromeAppsDeprecationHideLaunchAnyways.Get();
-  if (hide_launch_anyways) {
-    delegate->SetButtons(ui::DIALOG_BUTTON_OK);
-  } else {
-    delegate->SetButtonLabel(
-        ui::DIALOG_BUTTON_OK,
-        l10n_util::GetStringUTF16(IDS_DEPRECATED_APPS_LAUNCH_ANYWAY_LABEL));
-    delegate->SetAcceptCallback(std::move(launch_anyways));
-  }
+  delegate->SetButtons(ui::DIALOG_BUTTON_OK);
   delegate->SetContentsView(
       base::WrapUnique<ForceInstalledDeprecatedAppsDialogView>(
           new ForceInstalledDeprecatedAppsDialogView(app_name, web_contents)));
diff --git a/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view.h b/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view.h
index 7bd0dc1..6a78bd9 100644
--- a/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view.h
+++ b/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view.h
@@ -15,6 +15,8 @@
 class WebContents;
 }  // namespace content
 
+// Creates a dialog with one button. Clicking it opens a new tab to
+// kChromeAppsDeprecationLearnMoreURL.
 class ForceInstalledDeprecatedAppsDialogView : public views::BoxLayoutView {
   METADATA_HEADER(ForceInstalledDeprecatedAppsDialogView, views::BoxLayoutView)
 
@@ -27,8 +29,7 @@
 
   // Create the dialog metadata and show it.
   static void CreateAndShowDialog(const extensions::ExtensionId& app_id,
-                                  content::WebContents* web_contents,
-                                  base::OnceClosure launch_anyways);
+                                  content::WebContents* web_contents);
 
  private:
   ForceInstalledDeprecatedAppsDialogView(const std::u16string& app_name,
diff --git a/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view_browsertest.cc b/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view_browsertest.cc
index f9885fc..c4567c55 100644
--- a/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/force_installed_deprecated_apps_dialog_view_browsertest.cc
@@ -49,21 +49,10 @@
 };
 
 class ForceInstalledDeprecatedAppsDialogViewBrowserTest
-    : public extensions::ExtensionBrowserTest,
-      public testing::WithParamInterface<bool> {
+    : public extensions::ExtensionBrowserTest {
  protected:
   ForceInstalledDeprecatedAppsDialogViewBrowserTest() {
-    bool disable_preinstalled_apps = GetParam();
-    if (disable_preinstalled_apps) {
-      feature_list_.InitWithFeatures(
-          {features::kChromeAppsDeprecation},
-          {features::kKeepForceInstalledPreinstalledApps});
-    } else {
-      feature_list_.InitWithFeatures(
-          {features::kKeepForceInstalledPreinstalledApps,
-           features::kChromeAppsDeprecation},
-          {});
-    }
+    feature_list_.InitAndEnableFeature(features::kChromeAppsDeprecation);
   }
 
   void SetUpOnMainThread() override {
@@ -106,7 +95,7 @@
   content::TestWebUI test_web_ui_{};
 };
 
-IN_PROC_BROWSER_TEST_P(ForceInstalledDeprecatedAppsDialogViewBrowserTest,
+IN_PROC_BROWSER_TEST_F(ForceInstalledDeprecatedAppsDialogViewBrowserTest,
                        DialogLaunchedForForceInstalledApp) {
   auto handler = CreateLauncherHandler();
 
@@ -122,7 +111,7 @@
   EXPECT_NE(waiter.WaitIfNeededAndGet(), nullptr);
 }
 
-IN_PROC_BROWSER_TEST_P(ForceInstalledDeprecatedAppsDialogViewBrowserTest,
+IN_PROC_BROWSER_TEST_F(ForceInstalledDeprecatedAppsDialogViewBrowserTest,
                        DialogLaunchedForForceInstalledPreinstalledApp) {
   ASSERT_TRUE(embedded_test_server()->Start());
   // Set app as a preinstalled app.
@@ -137,9 +126,6 @@
   base::Value::List input;
   input.Append(app_id_);
   input.Append(extension_misc::AppLaunchBucket::APP_LAUNCH_NTP_APPS_MENU);
-  bool disable_preinstalled_apps = GetParam();
-
-  if (disable_preinstalled_apps) {
     auto waiter = views::NamedWidgetShownWaiter(
         views::test::AnyWidgetTestPasskey{},
         "ForceInstalledPreinstalledDeprecatedAppDialogView");
@@ -152,18 +138,6 @@
         content::NotificationService::AllSources());
     views::test::AcceptDialog(view);
     url_observer.Wait();
-
-  } else {
-    ui_test_utils::UrlLoadObserver url_observer(
-        GURL(kAppUrl), content::NotificationService::AllSources());
-    handler.HandleLaunchApp(input);
-    // Preinstalled chrome app is launched.
-    url_observer.Wait();
-  }
 }
 
-INSTANTIATE_TEST_SUITE_P(,
-                         ForceInstalledDeprecatedAppsDialogViewBrowserTest,
-                         testing::Bool());
-
 }  // namespace
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
index 393d2459..d49878804 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -4583,6 +4583,7 @@
   // If Lacros is enabled, WebAppIntegrationTest runs in Lacros with crosapi
   // enabled.
   base::Extend(disabled_features, ash::standalone_browser::GetFeatureRefs());
+  disabled_features.push_back(chromeos::features::kCrosShortstand);
 #endif
 #if BUILDFLAG(IS_CHROMEOS)
   // TODO(crbug.com/1357905): Update test driver to work with new UI.
@@ -4598,6 +4599,14 @@
 
 void WebAppIntegrationTest::SetUp() {
   helper_.SetUp();
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  StartUniqueAshChrome(
+      /*enabled_features=*/{},
+      /*disabled_features=*/{"CrosShortstand"},
+      /*additional_cmdline_switches=*/{},
+      "b/319753599 Migrate shortcuts out of web app system and remove shortcut "
+      "related tests.");
+#endif
   InProcessBrowserTest::SetUp();
 }
 
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
index 47fb011..d06a708 100644
--- a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
+++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
@@ -131,14 +131,7 @@
     if (extensions::IsExtensionUnsupportedDeprecatedApp(profile_, app_id) &&
         !deprecated_app_ids_.empty()) {
       TabDialogs::FromWebContents(web_contents)
-          ->ShowDeprecatedAppsDialog(
-              app_id, deprecated_app_ids_, web_contents,
-              base::BindOnce(
-                  &AppHomePageHandler::LaunchAppInternal,
-                  weak_ptr_factory_.GetWeakPtr(), app_id,
-                  extension_misc::AppLaunchBucket::APP_LAUNCH_CMD_LINE_APP,
-                  std::move(event_ptr),
-                  /*force_launch_deprecated_apps=*/true));
+          ->ShowDeprecatedAppsDialog(app_id, deprecated_app_ids_, web_contents);
     }
   } else if (net::GetValueForKeyInQuery(web_contents->GetLastCommittedURL(),
                                         kForceInstallDialogQueryString,
@@ -151,14 +144,7 @@
                                                                 web_contents);
       } else {
         TabDialogs::FromWebContents(web_contents)
-            ->ShowForceInstalledDeprecatedAppsDialog(
-                app_id, web_contents,
-                base::BindOnce(
-                    &AppHomePageHandler::LaunchAppInternal,
-                    weak_ptr_factory_.GetWeakPtr(), app_id,
-                    extension_misc::AppLaunchBucket::APP_LAUNCH_CMD_LINE_APP,
-                    std::move(event_ptr),
-                    /*force_launch_deprecated_apps=*/true));
+            ->ShowForceInstalledDeprecatedAppsDialog(app_id, web_contents);
       }
     }
   }
@@ -168,26 +154,18 @@
 void AppHomePageHandler::LaunchAppInternal(
     const std::string& app_id,
     extension_misc::AppLaunchBucket launch_bucket,
-    app_home::mojom::ClickEventPtr click_event,
-    bool force_launch_deprecated_apps) {
-  if (!force_launch_deprecated_apps &&
-      extensions::IsExtensionUnsupportedDeprecatedApp(profile_, app_id) &&
+    app_home::mojom::ClickEventPtr click_event) {
+  if (extensions::IsExtensionUnsupportedDeprecatedApp(profile_, app_id) &&
       base::FeatureList::IsEnabled(features::kChromeAppsDeprecation)) {
     if (!extensions::IsExtensionForceInstalled(profile_, app_id, nullptr)) {
       TabDialogs::FromWebContents(web_ui_->GetWebContents())
-          ->ShowDeprecatedAppsDialog(
-              app_id, deprecated_app_ids_, web_ui_->GetWebContents(),
-              base::BindOnce(&AppHomePageHandler::LaunchAppInternal,
-                             weak_ptr_factory_.GetWeakPtr(), app_id,
-                             launch_bucket, std::move(click_event), true));
+          ->ShowDeprecatedAppsDialog(app_id, deprecated_app_ids_,
+                                     web_ui_->GetWebContents());
       return;
     } else {
       TabDialogs::FromWebContents(web_ui_->GetWebContents())
-          ->ShowForceInstalledDeprecatedAppsDialog(
-              app_id, web_ui_->GetWebContents(),
-              base::BindOnce(&AppHomePageHandler::LaunchAppInternal,
-                             weak_ptr_factory_.GetWeakPtr(), app_id,
-                             launch_bucket, std::move(click_event), true));
+          ->ShowForceInstalledDeprecatedAppsDialog(app_id,
+                                                   web_ui_->GetWebContents());
       return;
     }
   }
@@ -737,7 +715,7 @@
 void AppHomePageHandler::LaunchApp(const std::string& app_id,
                                    app_home::mojom::ClickEventPtr click_event) {
   LaunchAppInternal(app_id, extension_misc::APP_LAUNCH_NTP_APPS_MAXIMIZED,
-                    std::move(click_event), false);
+                    std::move(click_event));
 }
 
 void AppHomePageHandler::SetRunOnOsLoginMode(
@@ -759,7 +737,7 @@
 void AppHomePageHandler::LaunchDeprecatedAppDialog() {
   TabDialogs::FromWebContents(web_ui_->GetWebContents())
       ->ShowDeprecatedAppsDialog(extensions::ExtensionId(), deprecated_app_ids_,
-                                 web_ui_->GetWebContents(), base::DoNothing());
+                                 web_ui_->GetWebContents());
 }
 
 void AppHomePageHandler::InstallAppLocally(const std::string& app_id) {
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.h b/chrome/browser/ui/webui/app_home/app_home_page_handler.h
index 22ea9c2..d73216cf 100644
--- a/chrome/browser/ui/webui/app_home/app_home_page_handler.h
+++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.h
@@ -138,8 +138,7 @@
   void InstallOsHooks(const webapps::AppId& app_id, web_app::AppLock* lock);
   void LaunchAppInternal(const std::string& app_id,
                          extension_misc::AppLaunchBucket bucket,
-                         app_home::mojom::ClickEventPtr click_event,
-                         bool force_launch_deprecated_apps);
+                         app_home::mojom::ClickEventPtr click_event);
   void ShowWebAppSettings(const std::string& app_id);
   void ShowExtensionAppSettings(const extensions::Extension* extension);
   void CreateWebAppShortcut(const std::string& app_id, base::OnceClosure done);
diff --git a/chrome/browser/ui/webui/ash/mako/mako_rewrite_view.cc b/chrome/browser/ui/webui/ash/mako/mako_rewrite_view.cc
index e84af2a..72114f80 100644
--- a/chrome/browser/ui/webui/ash/mako/mako_rewrite_view.cc
+++ b/chrome/browser/ui/webui/ash/mako/mako_rewrite_view.cc
@@ -13,7 +13,8 @@
 
 namespace {
 
-constexpr int kMakoRewritePadding = 16;
+constexpr int kMakoAnchorVerticalPadding = 16;
+constexpr int kMakoScreenEdgePadding = 16;
 constexpr int kMakoRewriteCornerRadius = 20;
 
 // Height threshold of the mako rewrite UI which determines its screen position.
@@ -21,9 +22,6 @@
 // UI is anchored at the caret.
 constexpr int kMakoRewriteHeightThreshold = 400;
 
-// Default caret height to use when the actual caret height is unknown.
-constexpr int kDefaultCaretHeight = 10;
-
 }  // namespace
 
 MakoRewriteView::MakoRewriteView(BubbleContentsWrapper* contents_wrapper,
@@ -41,49 +39,40 @@
 void MakoRewriteView::ResizeDueToAutoResize(content::WebContents* source,
                                             const gfx::Size& new_size) {
   WebUIBubbleDialogView::ResizeDueToAutoResize(source, new_size);
-  const gfx::Rect screen_work_area = display::Screen::GetScreen()
-                                         ->GetDisplayMatching(caret_bounds_)
-                                         .work_area();
+  gfx::Rect screen_work_area = display::Screen::GetScreen()
+                                   ->GetDisplayMatching(caret_bounds_)
+                                   .work_area();
+  screen_work_area.Inset(kMakoScreenEdgePadding);
 
-  // If the UI is very tall, just place it at the center of the screen.
+  // If the contents is very tall, just place it at the center of the screen.
   if (new_size.height() > kMakoRewriteHeightThreshold) {
     SetArrowWithoutResizing(views::BubbleBorder::FLOAT);
     SetAnchorRect(screen_work_area);
     return;
   }
 
-  // Otherwise, try to place it near the selection. First, try to left align
-  // with the selection, but adjust to keep on screen if needed.
-  int x =
-      std::min(caret_bounds_.x(), screen_work_area.right() - new_size.width() -
-                                      kMakoRewritePadding);
+  // Otherwise, try to place it under at the bottom left of the selection.
+  gfx::Rect anchor = caret_bounds_;
+  anchor.Outset(gfx::Outsets::VH(kMakoAnchorVerticalPadding, 0));
+  gfx::Rect mako_contents_bounds(anchor.bottom_left(), new_size);
 
-  // Then, try to place the mako UI just under the first line of the selection.
-  // Use a default caret height here since `caret bounds` is currently the
-  // bounds of the entire selection, which may span several lines.
-  // TODO: b/302043981 - Use the actual height of the first line.
-  int y = caret_bounds_.y() + kDefaultCaretHeight + kMakoRewritePadding;
-  // If that puts it offscreen, try placing it above the selection instead.
-  if (y + new_size.height() + kMakoRewritePadding > screen_work_area.bottom()) {
-    y = caret_bounds_.y() - kMakoRewritePadding - new_size.height();
+  // If horizontally offscreen, just move it to the right edge of the screen.
+  if (mako_contents_bounds.right() > screen_work_area.right()) {
+    mako_contents_bounds.set_x(screen_work_area.right() - new_size.width());
   }
 
-  // If it's still offscreen, place it at the bottom of the screen and adjust
-  // the horizontal position to try to move it out of the way of the
-  // selection.
-  if (y < screen_work_area.y() + kMakoRewritePadding) {
-    y = screen_work_area.bottom() - kMakoRewritePadding - new_size.height();
-    // Place it at the right of the selection edge if there is space
-    // (including padding), otherwise, place it to the left of the selection.
-    x = screen_work_area.right() - caret_bounds_.x() >
-                new_size.width() + 2 * kMakoRewritePadding
-            ? caret_bounds_.x() + kMakoRewritePadding
-            : caret_bounds_.x() - kMakoRewritePadding - new_size.width();
+  // If vertically offscreen, try above the selection.
+  if (mako_contents_bounds.bottom() > screen_work_area.bottom()) {
+    mako_contents_bounds.set_y(anchor.y() - new_size.height());
+  }
+  // If still vertically offscreen, just move it to the bottom of the screen.
+  if (mako_contents_bounds.y() < screen_work_area.y()) {
+    mako_contents_bounds.set_y(screen_work_area.bottom() - new_size.height());
   }
 
   // Compute widget bounds, which includes the border and shadow around the main
   // contents. Then, adjust again to ensure the whole widget is onscreen.
-  gfx::Rect widget_bounds({x, y}, new_size);
+  gfx::Rect widget_bounds(mako_contents_bounds);
   widget_bounds.Inset(-GetBubbleFrameView()->bubble_border()->GetInsets());
   widget_bounds.AdjustToFit(screen_work_area);
 
diff --git a/chrome/browser/ui/webui/ash/mako/mako_rewrite_view_unittest.cc b/chrome/browser/ui/webui/ash/mako/mako_rewrite_view_unittest.cc
index bf9392c8..bd35b0ee 100644
--- a/chrome/browser/ui/webui/ash/mako/mako_rewrite_view_unittest.cc
+++ b/chrome/browser/ui/webui/ash/mako/mako_rewrite_view_unittest.cc
@@ -58,7 +58,7 @@
   EXPECT_EQ(mako_rewrite_view_ptr->GetBoundsInScreen().size(), kWebViewSize);
 }
 
-TEST_F(MakoRewriteViewTest, DefaultBoundsLeftAlignedWithCaret) {
+TEST_F(MakoRewriteViewTest, DefaultBoundsAtBottomLeftOfCaret) {
   TestingProfile profile;
   TestBubbleContentsWrapper contents_wrapper(&profile);
 
@@ -71,26 +71,13 @@
   mako_rewrite_view_ptr->ResizeDueToAutoResize(/*source=*/nullptr,
                                                gfx::Size(100, 200));
 
+  // Should be left aligned and below the caret.
   EXPECT_EQ(mako_rewrite_view_ptr->GetBoundsInScreen().x(), kCaretBounds.x());
+  EXPECT_GE(mako_rewrite_view_ptr->GetBoundsInScreen().y(),
+            kCaretBounds.bottom());
 }
 
-TEST_F(MakoRewriteViewTest, DefaultBoundsBelowCaret) {
-  TestingProfile profile;
-  TestBubbleContentsWrapper contents_wrapper(&profile);
-
-  constexpr gfx::Rect kCaretBounds(30, 40, 0, 10);
-  auto mako_rewrite_view =
-      std::make_unique<MakoRewriteView>(&contents_wrapper, kCaretBounds);
-  auto* mako_rewrite_view_ptr = mako_rewrite_view.get();
-  views::BubbleDialogDelegateView::CreateBubble(std::move(mako_rewrite_view));
-
-  mako_rewrite_view_ptr->ResizeDueToAutoResize(/*source=*/nullptr,
-                                               gfx::Size(100, 200));
-
-  EXPECT_GE(mako_rewrite_view_ptr->GetBoundsInScreen().y(), kCaretBounds.y());
-}
-
-TEST_F(MakoRewriteViewTest, AboveCaretAtScreenBottom) {
+TEST_F(MakoRewriteViewTest, AtTopLeftOfCaretForCaretAtScreenBottom) {
   TestingProfile profile;
   TestBubbleContentsWrapper contents_wrapper(&profile);
 
@@ -104,8 +91,49 @@
 
   mako_rewrite_view_ptr->ResizeDueToAutoResize(/*source=*/nullptr,
                                                gfx::Size(100, 200));
+  // Should be left aligned and above the caret.
+  EXPECT_EQ(mako_rewrite_view_ptr->GetBoundsInScreen().x(), caret_bounds.x());
+  EXPECT_LE(mako_rewrite_view_ptr->GetBoundsInScreen().bottom(),
+            caret_bounds.y());
+}
 
-  EXPECT_LE(mako_rewrite_view_ptr->GetBoundsInScreen().y(), caret_bounds.y());
+TEST_F(MakoRewriteViewTest, OnScreenWithoutOverlapForSmallSelection) {
+  TestingProfile profile;
+  TestBubbleContentsWrapper contents_wrapper(&profile);
+
+  constexpr gfx::Rect kSelectionBounds(100, 40, 200, 100);
+  auto mako_rewrite_view =
+      std::make_unique<MakoRewriteView>(&contents_wrapper, kSelectionBounds);
+  auto* mako_rewrite_view_ptr = mako_rewrite_view.get();
+  views::BubbleDialogDelegateView::CreateBubble(std::move(mako_rewrite_view));
+
+  mako_rewrite_view_ptr->ResizeDueToAutoResize(/*source=*/nullptr,
+                                               gfx::Size(100, 200));
+
+  EXPECT_TRUE(
+      display::Screen::GetScreen()->GetPrimaryDisplay().work_area().Contains(
+          mako_rewrite_view_ptr->GetBoundsInScreen()));
+  EXPECT_FALSE(
+      mako_rewrite_view_ptr->GetBoundsInScreen().Intersects(kSelectionBounds));
+}
+
+TEST_F(MakoRewriteViewTest, OnScreenForLargeSelection) {
+  TestingProfile profile;
+  TestBubbleContentsWrapper contents_wrapper(&profile);
+
+  const gfx::Rect selection_bounds =
+      display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
+  auto mako_rewrite_view =
+      std::make_unique<MakoRewriteView>(&contents_wrapper, selection_bounds);
+  auto* mako_rewrite_view_ptr = mako_rewrite_view.get();
+  views::BubbleDialogDelegateView::CreateBubble(std::move(mako_rewrite_view));
+
+  mako_rewrite_view_ptr->ResizeDueToAutoResize(/*source=*/nullptr,
+                                               gfx::Size(100, 200));
+
+  EXPECT_TRUE(
+      display::Screen::GetScreen()->GetPrimaryDisplay().work_area().Contains(
+          mako_rewrite_view_ptr->GetBoundsInScreen()));
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc
index d975a42..ce59c21 100644
--- a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc
+++ b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc
@@ -19,9 +19,13 @@
 
 namespace {
 
-// Width/height of the Fallback dialog as found with the inspector tool.
-const int kWidth = 496;
-const int kHeight = 198;
+// Width of the Fallback dialog as found with the inspector tool.
+const int kWidth = 512;
+
+// Height of the Fallback dialogs for different text lengths as found with the
+// inspector tool.
+const int kOfflineHeight = 264;
+const int kDriveUnavailableHeight = 244;
 
 // Return the task title id for the task represented by the `action_id`.
 int GetTaskTitleId(const std::string& action_id) {
@@ -42,21 +46,25 @@
   return 0;
 }
 
-// TODO(cassycc): replace with UX chosen text.
 // Get the text ids for the `fallback_reason` specific translated strings that
 // will be displayed in dialog. Store them in the out parameters `title_id`,
-// `reason_message_id` and `instructions_message_id`.
-void GetDialogTextIds(
+// `reason_message_id` and `instructions_message_id`. Get the corresponding
+// width and height needed to display these strings in the dialog. Store them in
+// the out parameters `width` and `height`.
+void GetDialogTextIdsAndSize(
     const ash::office_fallback::FallbackReason fallback_reason,
     int& title_id,
     int& reason_message_id,
-    int& instructions_message_id) {
-  instructions_message_id = IDS_OFFICE_FALLBACK_INSTRUCTIONS;
+    int& instructions_message_id,
+    int& width,
+    int& height) {
+  width = kWidth;
   switch (fallback_reason) {
     case ash::office_fallback::FallbackReason::kOffline:
       title_id = IDS_OFFICE_FALLBACK_TITLE_OFFLINE;
       reason_message_id = IDS_OFFICE_FALLBACK_REASON_OFFLINE;
       instructions_message_id = IDS_OFFICE_FALLBACK_INSTRUCTIONS_OFFLINE;
+      height = kOfflineHeight;
       break;
     case ash::office_fallback::FallbackReason::kDriveDisabled:
     case ash::office_fallback::FallbackReason::kNoDriveService:
@@ -67,6 +75,7 @@
       reason_message_id = IDS_OFFICE_FALLBACK_REASON_DRIVE_UNAVAILABLE;
       instructions_message_id =
           IDS_OFFICE_FALLBACK_INSTRUCTIONS_DRIVE_UNAVAILABLE;
+      height = kDriveUnavailableHeight;
       break;
   }
 }
@@ -117,8 +126,10 @@
   int title_id;
   int reason_message_id;
   int instructions_message_id;
-  GetDialogTextIds(fallback_reason, title_id, reason_message_id,
-                   instructions_message_id);
+  int width;
+  int height;
+  GetDialogTextIdsAndSize(fallback_reason, title_id, reason_message_id,
+                          instructions_message_id, width, height);
   // TODO(cassycc): Figure out how to add the web_drive to the placeholder in
   // IDS_OFFICE_FALLBACK_TITLE_WEB_DRIVE_UNAVAILABLE.
   const std::string title_text = l10n_util::GetStringFUTF8(title_id, file_name);
@@ -129,9 +140,9 @@
 
   // The pointer is managed by an instance of `views::WebDialogView` and removed
   // in `SystemWebDialogDelegate::OnDialogClosed`.
-  OfficeFallbackDialog* dialog =
-      new OfficeFallbackDialog(file_urls, title_text, reason_message,
-                               instructions_message, std::move(callback));
+  OfficeFallbackDialog* dialog = new OfficeFallbackDialog(
+      file_urls, title_text, reason_message, instructions_message, width,
+      height, std::move(callback));
 
   dialog->ShowSystemDialog();
   return true;
@@ -153,6 +164,8 @@
     const std::string& title_text,
     const std::string& reason_message,
     const std::string& instructions_message,
+    const int& width,
+    const int& height,
     DialogChoiceCallback callback)
     : SystemWebDialogDelegate(GURL(chrome::kChromeUIOfficeFallbackURL),
                               std::u16string() /* title */),
@@ -160,6 +173,8 @@
       title_text_(title_text),
       reason_message_(reason_message),
       instructions_message_(instructions_message),
+      width_(width),
+      height_(height),
       callback_(std::move(callback)) {}
 
 OfficeFallbackDialog::~OfficeFallbackDialog() = default;
@@ -175,7 +190,7 @@
 }
 
 void OfficeFallbackDialog::GetDialogSize(gfx::Size* size) const {
-  size->SetSize(kWidth, kHeight);
+  size->SetSize(width_, height_);
 }
 
 bool OfficeFallbackDialog::ShouldCloseDialogOnEscape() const {
diff --git a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h
index 32c2353..cc9d5f9 100644
--- a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h
+++ b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h
@@ -49,6 +49,8 @@
                        const std::string& title_text,
                        const std::string& reason_message,
                        const std::string& instructions_message,
+                       const int& width,
+                       const int& height,
                        DialogChoiceCallback callback);
   std::string GetDialogArgs() const override;
   void GetDialogSize(gfx::Size* size) const override;
@@ -60,6 +62,8 @@
   const std::string title_text_;
   const std::string reason_message_;
   const std::string instructions_message_;
+  const int width_;
+  const int height_;
   DialogChoiceCallback callback_;
 };
 
diff --git a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog_browsertest.cc b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog_browsertest.cc
new file mode 100644
index 0000000..88f2982
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog_browsertest.cc
@@ -0,0 +1,212 @@
+// Copyright 2024 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/test/bind.h"
+#include "chrome/browser/ash/file_manager/file_manager_test_util.h"
+#include "chrome/browser/ash/file_manager/office_file_tasks.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h"
+#include "chrome/browser/ui/webui/ash/office_fallback/office_fallback_ui.h"
+#include "chrome/grit/generated_resources.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chromeos/constants/chromeos_features.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace ash::office_fallback {
+
+content::WebContents* GetWebContentsFromOfficeFallbackDialog() {
+  ash::SystemWebDialogDelegate* dialog =
+      ash::SystemWebDialogDelegate::FindInstance(
+          chrome::kChromeUIOfficeFallbackURL);
+  EXPECT_TRUE(dialog);
+  content::WebUI* webui = dialog->GetWebUIForTest();
+  EXPECT_TRUE(webui);
+  content::WebContents* web_contents = webui->GetWebContents();
+  EXPECT_TRUE(web_contents);
+  return web_contents;
+}
+
+// Launch the Office Fallback dialog by calling OfficeFallbackDialog::Show()
+// with the arguments provided. Wait for the dialog to open and then grab the
+// web contents.
+content::WebContents* LaunchOfficeFallbackDialogAndGetWebContents(
+    const std::vector<storage::FileSystemURL>& file_urls,
+    FallbackReason fallback_reason,
+    const std::string& action_id,
+    DialogChoiceCallback callback) {
+  // Watch for Office Fallback dialog URL chrome://office-fallback.
+  content::TestNavigationObserver navigation_observer_dialog(
+      (GURL(chrome::kChromeUIOfficeFallbackURL)));
+  navigation_observer_dialog.StartWatchingNewWebContents();
+
+  // Launch Office Fallback dialog.
+  base::RunLoop run_loop;
+  EXPECT_TRUE(OfficeFallbackDialog::Show(file_urls, fallback_reason, action_id,
+                                         std::move(callback)));
+
+  // Wait for Office Fallback dialog to open at chrome://office-fallback.
+  navigation_observer_dialog.Wait();
+  EXPECT_TRUE(navigation_observer_dialog.last_navigation_succeeded());
+
+  // Get the web contents of the dialog to be able to query
+  // `OfficeFallbackElement`.
+  return GetWebContentsFromOfficeFallbackDialog();
+}
+
+class OfficeFallbackDialogBrowserTest : public InProcessBrowserTest {
+ public:
+  OfficeFallbackDialogBrowserTest() {
+    feature_list_.InitWithFeatures(
+        {chromeos::features::kUploadOfficeToCloud,
+         chromeos::features::kUploadOfficeToCloudForEnterprise},
+        {});
+  }
+
+  OfficeFallbackDialogBrowserTest(const OfficeFallbackDialogBrowserTest&) =
+      delete;
+  OfficeFallbackDialogBrowserTest& operator=(
+      const OfficeFallbackDialogBrowserTest&) = delete;
+
+  void SetUpOnMainThread() override {
+    InProcessBrowserTest::SetUpOnMainThread();
+
+    files_ = file_manager::test::CopyTestFilesIntoMyFiles(browser()->profile(),
+                                                          {"text.docx"});
+  }
+
+ protected:
+  std::vector<storage::FileSystemURL> files_;
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// Test which launches an `OfficeFallbackDialog` which in turn creates an
+// `OfficeFallbackElement`. Tests that the correct title is displayed when the
+// fallback reason is that the system is offline.
+IN_PROC_BROWSER_TEST_F(OfficeFallbackDialogBrowserTest,
+                       OfficeFallbackDialogWhenOffline) {
+  // Launch Office Fallback dialog.
+  content::WebContents* web_contents =
+      LaunchOfficeFallbackDialogAndGetWebContents(
+          files_, FallbackReason::kOffline,
+          file_manager::file_tasks::kActionIdWebDriveOfficeWord,
+          base::DoNothing());
+
+  content::EvalJsResult eval_result =
+      content::EvalJs(web_contents,
+                      "document.querySelector('office-fallback')"
+                      ".$('#title').innerText");
+  EXPECT_EQ(eval_result.ExtractString(),
+            l10n_util::GetStringFUTF8(
+                IDS_OFFICE_FALLBACK_TITLE_OFFLINE,
+                files_.front().path().BaseName().LossyDisplayName()));
+}
+
+// Test which launches an `OfficeFallbackDialog` which in turn creates an
+// `OfficeFallbackElement`. Tests that the correct title is displayed when the
+// fallback reason is that Drive is unavailable.
+IN_PROC_BROWSER_TEST_F(OfficeFallbackDialogBrowserTest,
+                       OfficeFallbackDialogWhenDriveUnavailable) {
+  // Launch Office Fallback dialog.
+  content::WebContents* web_contents =
+      LaunchOfficeFallbackDialogAndGetWebContents(
+          files_, FallbackReason::kDriveDisabled,
+          file_manager::file_tasks::kActionIdWebDriveOfficeWord,
+          base::DoNothing());
+
+  content::EvalJsResult eval_result =
+      content::EvalJs(web_contents,
+                      "document.querySelector('office-fallback')"
+                      ".$('#title').innerText");
+  EXPECT_EQ(eval_result.ExtractString(),
+            l10n_util::GetStringFUTF8(
+                IDS_OFFICE_FALLBACK_TITLE_DRIVE_UNAVAILABLE,
+                files_.front().path().BaseName().LossyDisplayName()));
+}
+
+// Test which launches an `OfficeFallbackDialog` which in turn creates an
+// `OfficeFallbackElement`. Tests that the cancel button works.
+IN_PROC_BROWSER_TEST_F(OfficeFallbackDialogBrowserTest, ClickCancel) {
+  base::RunLoop run_loop;
+  content::WebContents* web_contents =
+      LaunchOfficeFallbackDialogAndGetWebContents(
+          files_, FallbackReason::kOffline,
+          file_manager::file_tasks::kActionIdWebDriveOfficeWord,
+          base::BindLambdaForTesting(
+              [&run_loop](std::optional<const std::string> choice) {
+                // Expect the dialog is closed with the "cancel" user choice.
+                if (choice.has_value() &&
+                    choice.value() ==
+                        ash::office_fallback::kDialogChoiceCancel) {
+                  run_loop.Quit();
+                }
+              }));
+
+  // Click the close button and wait until the dialog is closed with the correct
+  // user choice.
+  EXPECT_TRUE(content::ExecJs(web_contents,
+                              "document.querySelector('office-fallback')"
+                              ".$('#cancel-button').click()"));
+
+  run_loop.Run();
+}
+
+// Test which launches an `OfficeFallbackDialog` which in turn creates an
+// `OfficeFallbackElement`. Tests that the try again button works.
+IN_PROC_BROWSER_TEST_F(OfficeFallbackDialogBrowserTest, ClickTryAgain) {
+  base::RunLoop run_loop;
+  content::WebContents* web_contents =
+      LaunchOfficeFallbackDialogAndGetWebContents(
+          files_, FallbackReason::kOffline,
+          file_manager::file_tasks::kActionIdWebDriveOfficeWord,
+          base::BindLambdaForTesting(
+              [&run_loop](std::optional<const std::string> choice) {
+                // Expect the dialog is closed with the "cancel" user choice.
+                if (choice.has_value() &&
+                    choice.value() ==
+                        ash::office_fallback::kDialogChoiceTryAgain) {
+                  run_loop.Quit();
+                }
+              }));
+
+  // Click the try again button and wait until the dialog is closed with the
+  // correct user choice.
+  EXPECT_TRUE(content::ExecJs(web_contents,
+                              "document.querySelector('office-fallback')"
+                              ".$('#try-again-button').click()"));
+
+  run_loop.Run();
+}
+
+// Test which launches an `OfficeFallbackDialog` which in turn creates an
+// `OfficeFallbackElement`. Tests that the quick office button works.
+IN_PROC_BROWSER_TEST_F(OfficeFallbackDialogBrowserTest, ClickQuickOffice) {
+  base::RunLoop run_loop;
+  content::WebContents* web_contents =
+      LaunchOfficeFallbackDialogAndGetWebContents(
+          files_, FallbackReason::kOffline,
+          file_manager::file_tasks::kActionIdWebDriveOfficeWord,
+          base::BindLambdaForTesting(
+              [&run_loop](std::optional<const std::string> choice) {
+                // Expect the dialog is closed with the "cancel" user choice.
+                if (choice.has_value() &&
+                    choice.value() ==
+                        ash::office_fallback::kDialogChoiceQuickOffice) {
+                  run_loop.Quit();
+                }
+              }));
+
+  // Click the try again button and wait until the dialog is closed with the
+  // correct user choice.
+  EXPECT_TRUE(content::ExecJs(web_contents,
+                              "document.querySelector('office-fallback')"
+                              ".$('#quick-office-button').click()"));
+
+  run_loop.Run();
+}
+
+}  // namespace ash::office_fallback
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 7c78e9fc..0a5958bb 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -742,13 +742,8 @@
       if (extensions::IsExtensionUnsupportedDeprecatedApp(profile, app_id) &&
           !deprecated_app_ids_.empty()) {
         TabDialogs::FromWebContents(web_contents)
-            ->ShowDeprecatedAppsDialog(
-                app_id, deprecated_app_ids_, web_contents,
-                base::BindOnce(
-                    &AppLauncherHandler::LaunchApp,
-                    weak_ptr_factory_.GetWeakPtr(), app_id,
-                    extension_misc::AppLaunchBucket::APP_LAUNCH_CMD_LINE_APP,
-                    "", WindowOpenDisposition::CURRENT_TAB, true));
+            ->ShowDeprecatedAppsDialog(app_id, deprecated_app_ids_,
+                                       web_contents);
       }
     }
     if (net::GetValueForKeyInQuery(web_contents->GetLastCommittedURL(),
@@ -761,13 +756,7 @@
                                                                   web_contents);
         } else {
           TabDialogs::FromWebContents(web_contents)
-              ->ShowForceInstalledDeprecatedAppsDialog(
-                  app_id, web_contents,
-                  base::BindOnce(
-                      &AppLauncherHandler::LaunchApp,
-                      weak_ptr_factory_.GetWeakPtr(), app_id,
-                      extension_misc::AppLaunchBucket::APP_LAUNCH_CMD_LINE_APP,
-                      "", WindowOpenDisposition::CURRENT_TAB, true));
+              ->ShowForceInstalledDeprecatedAppsDialog(app_id, web_contents);
         }
       }
     }
@@ -791,28 +780,23 @@
   if (args.size() > 2) {
     source_value = args[2].GetString();
   }
-  LaunchApp(extension_id, launch_bucket, source_value, disposition, false);
+  LaunchApp(extension_id, launch_bucket, source_value, disposition);
 }
 
 void AppLauncherHandler::LaunchApp(
     std::string extension_id,
     extension_misc::AppLaunchBucket launch_bucket,
     const std::string& source_value,
-    WindowOpenDisposition disposition,
-    bool force_launch_deprecated_apps) {
+    WindowOpenDisposition disposition) {
   Profile* profile = extension_service_->profile();
 
-  if (!force_launch_deprecated_apps &&
-      extensions::IsExtensionUnsupportedDeprecatedApp(profile, extension_id) &&
+  if (extensions::IsExtensionUnsupportedDeprecatedApp(profile, extension_id) &&
       base::FeatureList::IsEnabled(features::kChromeAppsDeprecation)) {
     if (!extensions::IsExtensionForceInstalled(profile, extension_id,
                                                nullptr)) {
       TabDialogs::FromWebContents(web_ui()->GetWebContents())
-          ->ShowDeprecatedAppsDialog(
-              extension_id, deprecated_app_ids_, web_ui()->GetWebContents(),
-              base::BindOnce(&AppLauncherHandler::LaunchApp,
-                             weak_ptr_factory_.GetWeakPtr(), extension_id,
-                             launch_bucket, source_value, disposition, true));
+          ->ShowDeprecatedAppsDialog(extension_id, deprecated_app_ids_,
+                                     web_ui()->GetWebContents());
       return;
     } else if (extensions::IsPreinstalledAppId(extension_id)) {
       TabDialogs::FromWebContents(web_ui()->GetWebContents())
@@ -821,11 +805,8 @@
       return;
     } else {
       TabDialogs::FromWebContents(web_ui()->GetWebContents())
-          ->ShowForceInstalledDeprecatedAppsDialog(
-              extension_id, web_ui()->GetWebContents(),
-              base::BindOnce(&AppLauncherHandler::LaunchApp,
-                             weak_ptr_factory_.GetWeakPtr(), extension_id,
-                             launch_bucket, source_value, disposition, true));
+          ->ShowForceInstalledDeprecatedAppsDialog(extension_id,
+                                                   web_ui()->GetWebContents());
       return;
     }
   }
@@ -1249,7 +1230,7 @@
     const base::Value::List& args) {
   TabDialogs::FromWebContents(web_ui()->GetWebContents())
       ->ShowDeprecatedAppsDialog(extensions::ExtensionId(), deprecated_app_ids_,
-                                 web_ui()->GetWebContents(), base::DoNothing());
+                                 web_ui()->GetWebContents());
 }
 
 void AppLauncherHandler::OnFaviconForAppInstallFromLink(
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.h b/chrome/browser/ui/webui/ntp/app_launcher_handler.h
index 78662fc2..b427820 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.h
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.h
@@ -140,8 +140,7 @@
   void LaunchApp(std::string extension_id,
                  extension_misc::AppLaunchBucket launch_bucket,
                  const std::string& source_value,
-                 WindowOpenDisposition disposition,
-                 bool force_launch_deprecated_apps);
+                 WindowOpenDisposition disposition);
 
   // Handles the "setLaunchType" message with args containing [extension_id,
   // launch_type].
diff --git a/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui.cc b/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui.cc
index f49ccc6..77d9703 100644
--- a/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui.cc
+++ b/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui.cc
@@ -107,6 +107,8 @@
                              IDS_SHORT_PRODUCT_LOGO_ALT_TEXT);
   source->AddLocalizedString("fakeOmniboxText",
                              IDS_SEARCH_ENGINE_CHOICE_FAKE_OMNIBOX_TEXT);
+  source->AddLocalizedString("chevronA11yLabel",
+                             IDS_SEARCH_ENGINE_CHOICE_CHEVRON_A11Y_LABEL);
   source->AddLocalizedString("moreButtonText",
                              IDS_SEARCH_ENGINE_CHOICE_MORE_BUTTON);
   source->AddResourcePath("images/left_illustration.svg",
diff --git a/chrome/browser/ui/webui/settings/search_engines_handler.cc b/chrome/browser/ui/webui/settings/search_engines_handler.cc
index 1659a5f..6ab849b 100644
--- a/chrome/browser/ui/webui/settings/search_engines_handler.cc
+++ b/chrome/browser/ui/webui/settings/search_engines_handler.cc
@@ -8,8 +8,6 @@
 #include <utility>
 
 #include "base/check_deref.h"
-#include "base/debug/crash_logging.h"
-#include "base/debug/dump_without_crashing.h"
 #include "base/functional/bind.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/user_metrics.h"
@@ -27,7 +25,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/country_codes/country_codes.h"
 #include "components/prefs/pref_service.h"
 #include "components/search_engines/search_engine_choice_utils.h"
 #include "components/search_engines/search_engines_pref_names.h"
@@ -243,18 +240,7 @@
       template_url->prepopulate_id() != 0) {
     std::string_view icon_path =
         GetSearchEngineGeneratedIconPath(template_url->keyword());
-    if (icon_path.empty()) {
-      SCOPED_CRASH_KEY_NUMBER("SearchEnginesHandler", "engine_id",
-                              template_url->prepopulate_id());
-      SCOPED_CRASH_KEY_STRING64("SearchEnginesHandler", "engine_keyword",
-                                base::UTF16ToUTF8(template_url->keyword()));
-      SCOPED_CRASH_KEY_STRING32(
-          "SearchEnginesHandler", "user_country",
-          country_codes::CountryIDToCountryString(
-              search_engines::GetSearchEngineChoiceCountryId(
-                  profile_->GetPrefs())));
-      base::debug::DumpWithoutCrashing();
-    } else {
+    if (!icon_path.empty()) {
       // The search engine icon path are 24px, but displayed at 16px, or 32px on
       // HiDPI screens. Use the 2x version (48px) for a large enough icon.
       // Note that this icon path is used in `site-favicon` which does not
diff --git a/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc b/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc
index 946b4946..433aa54 100644
--- a/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc
@@ -325,6 +325,14 @@
 };
 
 IN_PROC_BROWSER_TEST_F(LaunchWebAppCommandTest, TabbedLaunchCurrentBrowser) {
+#if BUILDFLAG(IS_CHROMEOS)
+  // When shortstand enabled, we no longer allow web app to be launched in
+  // browser tab. This test is no longer valid. The shortstand behaviour is
+  // tested in LaunchWebAppCommandTest_Shortstand.* below.
+  if (chromeos::features::IsCrosShortstandEnabled()) {
+    GTEST_SKIP();
+  }
+#endif
   apps::AppLaunchParams launch_params = CreateLaunchParams(
       app_id_, apps::LaunchContainer::kLaunchContainerTab,
       WindowOpenDisposition::NEW_FOREGROUND_TAB,
diff --git a/chrome/browser/web_applications/extensions/extension_status_utils.cc b/chrome/browser/web_applications/extensions/extension_status_utils.cc
index 11cc767..c8b3ca2e 100644
--- a/chrome/browser/web_applications/extensions/extension_status_utils.cc
+++ b/chrome/browser/web_applications/extensions/extension_status_utils.cc
@@ -138,15 +138,6 @@
 
   bool force_installed =
       IsExtensionForceInstalled(context, extension_id, nullptr);
-  bool preinstalled = IsPreinstalledAppId(extension_id);
-
-  // This feature allows us to keep chrome apps that are force installed AND
-  // preinstalled.
-  if (base::FeatureList::IsEnabled(
-          features::kKeepForceInstalledPreinstalledApps) &&
-      force_installed && preinstalled) {
-    return false;
-  }
 
   if (base::FeatureList::IsEnabled(
           kChromeAppsDeprecationExcludeForceInstalls) &&
diff --git a/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc b/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc
index b1983d2e..e19330a 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc
@@ -819,6 +819,7 @@
   {
     auto info = std::make_unique<WebAppInstallInfo>();
     info->start_url = embedded_test_server()->GetURL("/webapps/migration/old/");
+    info->scope = info->start_url;
     info->title = u"Old app";
     old_app_id = web_app::test::InstallWebApp(profile(), std::move(info));
     apps::AppReadinessWaiter(profile(), old_app_id).Await();
@@ -837,6 +838,7 @@
   {
     auto info = std::make_unique<WebAppInstallInfo>();
     info->start_url = embedded_test_server()->GetURL("/webapps/migration/new/");
+    info->scope = info->start_url;
     info->title = u"New app";
 
     WebAppInstallParams install_params;
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index 941b5a94..6a4b6cc 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1705253482-aa495e7841a760469951626a6c39015bfd142490.profdata
+chrome-android32-main-1705298219-066a6afe664edfb0f64fc98f88c51050986b8338.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 10d3249..654fb02 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1705231310-75070945fa109763638ff8667d5851826bc956c9.profdata
+chrome-android64-main-1705298219-e633a407157e3d3e84d1f19a3be4bad290fbb97a.profdata
diff --git a/chrome/build/lacros-arm64.pgo.txt b/chrome/build/lacros-arm64.pgo.txt
index fbcf5f3..5cad6b4 100644
--- a/chrome/build/lacros-arm64.pgo.txt
+++ b/chrome/build/lacros-arm64.pgo.txt
@@ -1 +1 @@
-chrome-chromeos-arm64-generic-main-1705231310-8ebfb45163906b5701510cde8d8bed77cf2dad3c.profdata
+chrome-chromeos-arm64-generic-main-1705275060-880b7af5d219b128882780eba57347f159733911.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index fc775cf..9ade67a 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1705253482-d6eadd99b5fe4c391bafe83110d2badb2e511fd6.profdata
+chrome-linux-main-1705298219-417104096f51f35b17972e39732eed4c6a979ffc.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 8c67986..2fc0185 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1705262212-7b6306a3cc47758757a66e281059548e047f2d30.profdata
+chrome-mac-arm-main-1705305508-f0dc220728a6fdd26a7f39f099729711f1c7b40f.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 909a884a..727bc20e 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1705253482-2f00cd1b8208f26c7f72e6f9c6cfe5bf5c70bed8.profdata
+chrome-mac-main-1705298219-982a89b31811bfe637fc7f48cdf8e9b1b716bbde.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index 7074b52e..aaddff8 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1705253482-3c5395b18b6a8924ad25227eb3d19c77fd5c1d11.profdata
+chrome-win-arm64-main-1705275060-8a233fd84798a67c0ba62cba1518adb393f85bb8.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 06d0510..805de6e 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1705243657-9b925415dc25463cd354f8d9f57104a597ce13f2.profdata
+chrome-win64-main-1705298219-ba39876ced89b564be7f0256210bb0316b2423b4.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index ac4a029..e0730bb 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -367,14 +367,6 @@
 BASE_FEATURE(kChromeAppsDeprecation,
              "ChromeAppsDeprecation",
              base::FEATURE_ENABLED_BY_DEFAULT);
-// Controls whether force installed and preinstalled apps should be exempt from
-// deprecation.
-BASE_FEATURE(kKeepForceInstalledPreinstalledApps,
-             "KeepForceInstalledPreinstalledApps",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-// Controls if the 'launch anyways' button is shown.
-const base::FeatureParam<bool> kChromeAppsDeprecationHideLaunchAnyways{
-    &kChromeAppsDeprecation, "HideLaunchAnyways", true};
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) ||
         // BUILDFLAG(IS_FUCHSIA)
 
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 9da0f6e..a858e982 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -232,10 +232,6 @@
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
     BUILDFLAG(IS_FUCHSIA)
 COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kChromeAppsDeprecation);
-COMPONENT_EXPORT(CHROME_FEATURES)
-BASE_DECLARE_FEATURE(kKeepForceInstalledPreinstalledApps);
-COMPONENT_EXPORT(CHROME_FEATURES)
-extern const base::FeatureParam<bool> kChromeAppsDeprecationHideLaunchAnyways;
 #endif
 
 COMPONENT_EXPORT(CHROME_FEATURES)
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index d244404..2d7e45b 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -288,6 +288,9 @@
 using content::WebPluginInfo;
 using content::WebPluginMimeType;
 using extensions::Extension;
+using UsesKeyboardAccessoryForSuggestions =
+    AutofillAgent::UsesKeyboardAccessoryForSuggestions;
+using ExtractAllDatalists = autofill::AutofillAgent::ExtractAllDatalists;
 
 namespace {
 
@@ -687,9 +690,12 @@
         render_frame, associated_interfaces);
     auto password_generation_agent = std::make_unique<PasswordGenerationAgent>(
         render_frame, password_autofill_agent.get(), associated_interfaces);
-    new AutofillAgent(render_frame, std::move(password_autofill_agent),
-                      std::move(password_generation_agent),
-                      associated_interfaces);
+    new AutofillAgent(
+        render_frame,
+        {UsesKeyboardAccessoryForSuggestions(BUILDFLAG(IS_ANDROID)),
+         ExtractAllDatalists(false)},
+        std::move(password_autofill_agent),
+        std::move(password_generation_agent), associated_interfaces);
 
 #if BUILDFLAG(IS_ANDROID)
     if (render_frame->IsMainFrame() &&
@@ -1767,8 +1773,8 @@
 std::unique_ptr<blink::URLLoaderThrottleProvider>
 ChromeContentRendererClient::CreateURLLoaderThrottleProvider(
     blink::URLLoaderThrottleProviderType provider_type) {
-  return std::make_unique<URLLoaderThrottleProviderImpl>(
-      browser_interface_broker_.get(), provider_type, this);
+  return URLLoaderThrottleProviderImpl::Create(provider_type, this,
+                                               browser_interface_broker_.get());
 }
 
 blink::WebFrame* ChromeContentRendererClient::FindFrame(
diff --git a/chrome/renderer/url_loader_throttle_provider_impl.cc b/chrome/renderer/url_loader_throttle_provider_impl.cc
index 0156fb2..a41caaa 100644
--- a/chrome/renderer/url_loader_throttle_provider_impl.cc
+++ b/chrome/renderer/url_loader_throttle_provider_impl.cc
@@ -4,12 +4,14 @@
 
 #include "chrome/renderer/url_loader_throttle_provider_impl.h"
 
+#include <memory>
 #include <utility>
 
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/task/sequenced_task_runner.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/common/google_url_loader_throttle.h"
@@ -89,57 +91,68 @@
 
 }  // namespace
 
-URLLoaderThrottleProviderImpl::URLLoaderThrottleProviderImpl(
-    blink::ThreadSafeBrowserInterfaceBrokerProxy* broker,
+// static
+std::unique_ptr<blink::URLLoaderThrottleProvider>
+URLLoaderThrottleProviderImpl::Create(
     blink::URLLoaderThrottleProviderType type,
-    ChromeContentRendererClient* chrome_content_renderer_client)
-    : type_(type),
-      chrome_content_renderer_client_(chrome_content_renderer_client) {
-  DETACH_FROM_SEQUENCE(sequence_checker_);
-  broker->GetInterface(pending_safe_browsing_.InitWithNewPipeAndPassReceiver());
+    ChromeContentRendererClient* chrome_content_renderer_client,
+    blink::ThreadSafeBrowserInterfaceBrokerProxy* broker) {
+  mojo::PendingRemote<safe_browsing::mojom::SafeBrowsing> pending_safe_browsing;
+  broker->GetInterface(pending_safe_browsing.InitWithNewPipeAndPassReceiver());
 #if BUILDFLAG(ENABLE_EXTENSIONS)
+  mojo::PendingRemote<safe_browsing::mojom::ExtensionWebRequestReporter>
+      pending_extension_web_request_reporter;
   broker->GetInterface(
-      pending_extension_web_request_reporter_.InitWithNewPipeAndPassReceiver());
+      pending_extension_web_request_reporter.InitWithNewPipeAndPassReceiver());
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+
+  return std::make_unique<URLLoaderThrottleProviderImpl>(
+      type, chrome_content_renderer_client, std::move(pending_safe_browsing),
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+      std::move(pending_extension_web_request_reporter),
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+      /*main_thread_task_runner=*/
+      content::RenderThread::IsMainThread()
+          ? base::SequencedTaskRunner::GetCurrentDefault()
+          : nullptr,
+      base::PassKey<URLLoaderThrottleProviderImpl>());
+}
+
+URLLoaderThrottleProviderImpl::URLLoaderThrottleProviderImpl(
+    blink::URLLoaderThrottleProviderType type,
+    ChromeContentRendererClient* chrome_content_renderer_client,
+    mojo::PendingRemote<safe_browsing::mojom::SafeBrowsing>
+        pending_safe_browsing,
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+    mojo::PendingRemote<safe_browsing::mojom::ExtensionWebRequestReporter>
+        pending_extension_web_request_reporter,
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+    scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner,
+    base::PassKey<URLLoaderThrottleProviderImpl>)
+    : type_(type),
+      chrome_content_renderer_client_(chrome_content_renderer_client),
+      pending_safe_browsing_(std::move(pending_safe_browsing)),
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+      pending_extension_web_request_reporter_(
+          std::move(pending_extension_web_request_reporter)),
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+      main_thread_task_runner_(std::move(main_thread_task_runner)) {
+  DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
 URLLoaderThrottleProviderImpl::~URLLoaderThrottleProviderImpl() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-URLLoaderThrottleProviderImpl::URLLoaderThrottleProviderImpl(
-    const URLLoaderThrottleProviderImpl& other)
-    : type_(other.type_),
-      chrome_content_renderer_client_(other.chrome_content_renderer_client_) {
-  DETACH_FROM_SEQUENCE(sequence_checker_);
-  if (other.safe_browsing_) {
-    other.safe_browsing_->Clone(
-        pending_safe_browsing_.InitWithNewPipeAndPassReceiver());
-  }
-
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-  if (other.extension_web_request_reporter_) {
-    other.extension_web_request_reporter_->Clone(
-        pending_extension_web_request_reporter_
-            .InitWithNewPipeAndPassReceiver());
-  }
-#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
-}
-
 std::unique_ptr<blink::URLLoaderThrottleProvider>
 URLLoaderThrottleProviderImpl::Clone() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (pending_safe_browsing_) {
-    safe_browsing_.Bind(std::move(pending_safe_browsing_));
-  }
-
+  return std::make_unique<URLLoaderThrottleProviderImpl>(
+      type_, chrome_content_renderer_client_, CloneSafeBrowsingPendingRemote(),
 #if BUILDFLAG(ENABLE_EXTENSIONS)
-  if (pending_extension_web_request_reporter_) {
-    extension_web_request_reporter_.Bind(
-        std::move(pending_extension_web_request_reporter_));
-  }
+      CloneExtensionWebRequestReporterPendingRemote(),
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
-  return base::WrapUnique(new URLLoaderThrottleProviderImpl(*this));
+      main_thread_task_runner_, base::PassKey<URLLoaderThrottleProviderImpl>());
 }
 
 blink::WebVector<std::unique_ptr<blink::URLLoaderThrottle>>
@@ -235,16 +248,26 @@
           ->chromeos_listener()));
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-  // Workers can call us on a background thread. We don't care about such
-  // requests because we purposefully only look at resources from frames
-  // that the user can interact with.
-  blink::WebLocalFrame* frame = nullptr;
-  if (content::RenderThread::IsMainThread() && local_frame_token.has_value()) {
-    frame = blink::WebLocalFrame::FromFrameToken(local_frame_token.value());
-  }
-  if (frame) {
-    auto throttle = content::MaybeCreateIdentityUrlLoaderThrottle(
-        base::BindRepeating(blink::SetIdpSigninStatus, frame));
+  if (local_frame_token.has_value()) {
+    auto throttle =
+        content::MaybeCreateIdentityUrlLoaderThrottle(base::BindRepeating(
+            [](const blink::LocalFrameToken& local_frame_token,
+               const scoped_refptr<base::SequencedTaskRunner>
+                   main_thread_task_runner,
+               const url::Origin& origin,
+               blink::mojom::IdpSigninStatus status) {
+              if (content::RenderThread::IsMainThread()) {
+                blink::SetIdpSigninStatus(local_frame_token, origin, status);
+                return;
+              }
+              if (main_thread_task_runner) {
+                main_thread_task_runner->PostTask(
+                    FROM_HERE,
+                    base::BindOnce(&blink::SetIdpSigninStatus,
+                                   local_frame_token, origin, status));
+              }
+            },
+            local_frame_token.value(), main_thread_task_runner_));
     if (throttle)
       throttles.push_back(std::move(throttle));
   }
@@ -258,3 +281,37 @@
     extension_throttle_manager_->SetOnline(is_online);
 #endif
 }
+
+mojo::PendingRemote<safe_browsing::mojom::SafeBrowsing>
+URLLoaderThrottleProviderImpl::CloneSafeBrowsingPendingRemote() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  mojo::PendingRemote<safe_browsing::mojom::SafeBrowsing>
+      new_pending_safe_browsing;
+  if (pending_safe_browsing_) {
+    safe_browsing_.Bind(std::move(pending_safe_browsing_));
+  }
+  if (safe_browsing_) {
+    safe_browsing_->Clone(
+        new_pending_safe_browsing.InitWithNewPipeAndPassReceiver());
+  }
+  return new_pending_safe_browsing;
+}
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+mojo::PendingRemote<safe_browsing::mojom::ExtensionWebRequestReporter>
+URLLoaderThrottleProviderImpl::CloneExtensionWebRequestReporterPendingRemote() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  mojo::PendingRemote<safe_browsing::mojom::ExtensionWebRequestReporter>
+      new_pending_extension_web_request_reporter;
+  if (pending_extension_web_request_reporter_) {
+    extension_web_request_reporter_.Bind(
+        std::move(pending_extension_web_request_reporter_));
+  }
+  if (extension_web_request_reporter_) {
+    extension_web_request_reporter_->Clone(
+        new_pending_extension_web_request_reporter
+            .InitWithNewPipeAndPassReceiver());
+  }
+  return new_pending_extension_web_request_reporter;
+}
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/renderer/url_loader_throttle_provider_impl.h b/chrome/renderer/url_loader_throttle_provider_impl.h
index 2f69a25..ace2a32 100644
--- a/chrome/renderer/url_loader_throttle_provider_impl.h
+++ b/chrome/renderer/url_loader_throttle_provider_impl.h
@@ -10,6 +10,7 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/sequence_checker.h"
+#include "base/types/pass_key.h"
 #include "components/safe_browsing/content/common/safe_browsing.mojom.h"
 #include "extensions/buildflags/buildflags.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -21,6 +22,10 @@
 #include "extensions/renderer/extension_throttle_manager.h"
 #endif
 
+namespace base {
+class SequencedTaskRunner;
+}  // namespace base
+
 class ChromeContentRendererClient;
 
 // Instances must be constructed on the render main thread, and then used and
@@ -28,10 +33,22 @@
 // thread.
 class URLLoaderThrottleProviderImpl : public blink::URLLoaderThrottleProvider {
  public:
-  URLLoaderThrottleProviderImpl(
-      blink::ThreadSafeBrowserInterfaceBrokerProxy* broker,
+  static std::unique_ptr<blink::URLLoaderThrottleProvider> Create(
       blink::URLLoaderThrottleProviderType type,
-      ChromeContentRendererClient* chrome_content_renderer_client);
+      ChromeContentRendererClient* chrome_content_renderer_client,
+      blink::ThreadSafeBrowserInterfaceBrokerProxy* broker);
+
+  URLLoaderThrottleProviderImpl(
+      blink::URLLoaderThrottleProviderType type,
+      ChromeContentRendererClient* chrome_content_renderer_client,
+      mojo::PendingRemote<safe_browsing::mojom::SafeBrowsing>
+          pending_safe_browsing,
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+      mojo::PendingRemote<safe_browsing::mojom::ExtensionWebRequestReporter>
+          pending_extension_web_request_reporter,
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+      scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner,
+      base::PassKey<URLLoaderThrottleProviderImpl>);
 
   URLLoaderThrottleProviderImpl& operator=(
       const URLLoaderThrottleProviderImpl&) = delete;
@@ -46,9 +63,12 @@
   void SetOnline(bool is_online) override;
 
  private:
-  // This copy constructor works in conjunction with Clone(), not intended for
-  // general use.
-  URLLoaderThrottleProviderImpl(const URLLoaderThrottleProviderImpl& other);
+  mojo::PendingRemote<safe_browsing::mojom::SafeBrowsing>
+  CloneSafeBrowsingPendingRemote();
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  mojo::PendingRemote<safe_browsing::mojom::ExtensionWebRequestReporter>
+  CloneExtensionWebRequestReporterPendingRemote();
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
   blink::URLLoaderThrottleProviderType type_;
   const raw_ptr<ChromeContentRendererClient, ExperimentalRenderer>
@@ -66,7 +86,11 @@
 
   std::unique_ptr<extensions::ExtensionThrottleManager>
       extension_throttle_manager_;
-#endif
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+
+  // Set only when `this` was created on the main thread, or cloned from a
+  // provider which was created on the main thread.
+  scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 };
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 2f30d973..d0e3dcd 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -369,6 +369,7 @@
     "//components/ukm:test_support",
     "//components/user_education/common",
     "//components/user_manager",
+    "//components/web_package",
     "//components/webapps/browser:browser",
     "//components/webapps/common",
     "//ui/webui",
@@ -4684,6 +4685,7 @@
         "../browser/ash/policy/networking/network_policy_application_browsertest.cc",
         "../browser/ash/policy/networking/policy_certs_browsertest.cc",
         "../browser/ash/policy/remote_commands/curtain_mode_chromeos_browsertest.cc",
+        "../browser/ash/policy/remote_commands/device_command_fetch_support_packet_job_browsertest.cc",
         "../browser/ash/policy/remote_commands/device_command_reboot_job_browsertest.cc",
         "../browser/ash/policy/remote_commands/device_command_set_volume_job_browsertest.cc",
         "../browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer_browsertest.cc",
@@ -4868,6 +4870,7 @@
         "../browser/ui/webui/ash/login/oobe_display_chooser_browsertest.cc",
         "../browser/ui/webui/ash/login/testapi/oobe_test_api_browsertest.cc",
         "../browser/ui/webui/ash/manage_mirrorsync/manage_mirrorsync_dialog_browsertest.cc",
+        "../browser/ui/webui/ash/office_fallback/office_fallback_dialog_browsertest.cc",
         "../browser/ui/webui/ash/parent_access/parent_access_browsertest_base.cc",
         "../browser/ui/webui/ash/parent_access/parent_access_browsertest_base.h",
         "../browser/ui/webui/ash/parent_access/parent_access_dialog_browsertest.cc",
diff --git a/chrome/test/DEPS b/chrome/test/DEPS
index cb42a5a..11de9e7 100644
--- a/chrome/test/DEPS
+++ b/chrome/test/DEPS
@@ -108,6 +108,7 @@
   "+components/webapps",
   "+components/webauthn/android",
   "+components/webdata_services",
+  "+components/web_package",
   "+components/zoom",
   "+device/bluetooth/dbus",
   "+extensions",
diff --git a/chrome/test/base/chrome_render_view_test.cc b/chrome/test/base/chrome_render_view_test.cc
index 320a967..88c870f 100644
--- a/chrome/test/base/chrome_render_view_test.cc
+++ b/chrome/test/base/chrome_render_view_test.cc
@@ -83,7 +83,7 @@
           &associated_interfaces_);
   password_generation_ = unique_password_generation.get();
   autofill_agent_ = new AutofillAgent(
-      GetMainRenderFrame(), std::move(unique_password_autofill_agent),
+      GetMainRenderFrame(), {}, std::move(unique_password_autofill_agent),
       std::move(unique_password_generation), &associated_interfaces_);
 }
 
diff --git a/chrome/test/base/chrome_unit_test_suite.cc b/chrome/test/base/chrome_unit_test_suite.cc
index e146891f..a18bb865 100644
--- a/chrome/test/base/chrome_unit_test_suite.cc
+++ b/chrome/test/base/chrome_unit_test_suite.cc
@@ -47,6 +47,11 @@
 #include "crypto/nss_util_internal.h"
 #endif
 
+#if !BUILDFLAG(IS_ANDROID)
+#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_trust_checker.h"
+#include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
+#endif  // !BUILDFLAG(IS_ANDROID)
+
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 #include "chrome/common/initialize_extensions_client.h"
 #include "extensions/common/extension_paths.h"
@@ -56,7 +61,7 @@
 namespace extensions {
 class ContextData;
 }  // namespace extensions
-#endif
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
 namespace {
 
@@ -106,6 +111,9 @@
     arc::ClearArcAllowedCheckForTesting();
     crypto::ResetTokenManagerForTesting();
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+#if !BUILDFLAG(IS_ANDROID)
+    web_app::SetTrustedWebBundleIdsForTesting({});
+#endif  // !BUILDFLAG(IS_ANDROID)
     browser_shutdown::ResetShutdownGlobalsForTesting();
   }
 };
diff --git a/chrome/test/data/extensions/api_test/autotest_private/test.js b/chrome/test/data/extensions/api_test/autotest_private/test.js
index 58be7c4..b86f989 100644
--- a/chrome/test/data/extensions/api_test/autotest_private/test.js
+++ b/chrome/test/data/extensions/api_test/autotest_private/test.js
@@ -590,7 +590,7 @@
       chrome.test.assertEq('Running', item.status);
       chrome.test.assertTrue(item.showsTooltip);
       chrome.test.assertFalse(item.pinnedByPolicy);
-      chrome.test.assertFalse(item.pinStateForcedByType);
+      chrome.test.assertTrue(item.pinStateForcedByType);
       chrome.test.assertFalse(item.hasNotification);
     }));
   },
diff --git a/clank b/clank
index 0f214c7..d9fbbb1 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 0f214c7f87366bba55645490815654cb6f2f34ba
+Subproject commit d9fbbb1a8ba25f6fe6d396882b1a8649fbeac966
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.cc b/components/autofill/content/browser/content_autofill_driver_factory.cc
index 3812d73..f2433aa1 100644
--- a/components/autofill/content/browser/content_autofill_driver_factory.cc
+++ b/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -65,8 +65,8 @@
 
 // static
 void ContentAutofillDriverFactory::BindAutofillDriver(
-    mojo::PendingAssociatedReceiver<mojom::AutofillDriver> pending_receiver,
-    content::RenderFrameHost* render_frame_host) {
+    content::RenderFrameHost* render_frame_host,
+    mojo::PendingAssociatedReceiver<mojom::AutofillDriver> pending_receiver) {
   DCHECK(render_frame_host);
 
   content::WebContents* web_contents =
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.h b/components/autofill/content/browser/content_autofill_driver_factory.h
index ab029173..956c7046 100644
--- a/components/autofill/content/browser/content_autofill_driver_factory.h
+++ b/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -77,8 +77,8 @@
       content::WebContents* contents);
 
   static void BindAutofillDriver(
-      mojo::PendingAssociatedReceiver<mojom::AutofillDriver> pending_receiver,
-      content::RenderFrameHost* render_frame_host);
+      content::RenderFrameHost* render_frame_host,
+      mojo::PendingAssociatedReceiver<mojom::AutofillDriver> pending_receiver);
 
   ContentAutofillDriverFactory(content::WebContents* web_contents,
                                AutofillClient* client,
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index 0c8226c..d5e8603 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -118,23 +118,6 @@
 
 using FormAndField = std::pair<FormData, FormFieldData>;
 
-DenseSet<ExtractOption> MaybeExtractDatalist(
-    DenseSet<ExtractOption> extract_options) {
-  if (base::FeatureList::IsEnabled(features::kAutofillExtractAllDatalists)) {
-    extract_options.insert(ExtractOption::kDatalist);
-  }
-  return extract_options;
-}
-
-bool UsesKeyboardAccessoryForSuggestions() {
-#if !BUILDFLAG(IS_ANDROID)
-  return false;  // The keyboard accessory is specific to Android.
-#else
-  return !base::FeatureList::IsEnabled(
-      features::kAutofillLegacyDatalistDropdown);
-#endif
-}
-
 }  // namespace
 
 // During prerendering, we do not want the renderer to send messages to the
@@ -317,10 +300,12 @@
 
 AutofillAgent::AutofillAgent(
     content::RenderFrame* render_frame,
+    Config config,
     std::unique_ptr<PasswordAutofillAgent> password_autofill_agent,
     std::unique_ptr<PasswordGenerationAgent> password_generation_agent,
     blink::AssociatedInterfaceRegistry* registry)
     : content::RenderFrameObserver(render_frame),
+      config_(config),
       form_cache_(std::make_unique<FormCache>(render_frame->GetWebFrame())),
       password_autofill_agent_(std::move(password_autofill_agent)),
       password_generation_agent_(std::move(password_generation_agent)),
@@ -447,7 +432,8 @@
   // element because that will be done by HandleFocusChangeComplete() which
   // triggers FormControlElementClicked().
   // Refer to http://crbug.com/1105254
-  if ((UsesKeyboardAccessoryForSuggestions() || !focus_requires_scroll_) &&
+  if ((config_.uses_keyboard_accessory_for_suggestions ||
+       !focus_requires_scroll_) &&
       !element.IsNull() &&
       element.GetDocument().GetFrame()->HasTransientUserActivation()) {
     // If the focus change was caused by a user gesture,
@@ -1026,16 +1012,18 @@
     }
   }
 
-  const bool element_value_valid = [&element, trigger_source] {
+  const bool show_for_empty_value =
+      config_.uses_keyboard_accessory_for_suggestions ||
+      ShouldAutofillOnEmptyValues(trigger_source);
+  const bool element_value_valid = [&element, trigger_source,
+                                    show_for_empty_value] {
     WebString value = element.EditingValue();
     // Don't attempt to autofill with values that are too large.
     if (!ShouldAutofillOnLongValues(trigger_source) &&
         value.length() > kMaxStringLength) {
       return false;
     }
-    // Keyboard Accessory may still be shown when `value` is empty.
-    if (!UsesKeyboardAccessoryForSuggestions() &&
-        !ShouldAutofillOnEmptyValues(trigger_source) && value.IsEmpty()) {
+    if (!show_for_empty_value && value.IsEmpty()) {
       return false;
     }
     return !(RequiresCaretAtEnd(trigger_source) &&
@@ -1138,7 +1126,7 @@
     return;
   }
 
-  if (!base::FeatureList::IsEnabled(features::kAutofillExtractAllDatalists)) {
+  if (!config_.extract_all_datalists) {
     const WebInputElement input_element = element.DynamicTo<WebInputElement>();
     if (!input_element.IsNull()) {
       // Find the datalist values and send them to the browser process.
@@ -1285,7 +1273,7 @@
   is_popup_possibly_visible_ = false;
 
   // The keyboard accessory has a separate, more complex hiding logic.
-  if (UsesKeyboardAccessoryForSuggestions()) {
+  if (config_.uses_keyboard_accessory_for_suggestions) {
     return;
   }
 
@@ -1326,7 +1314,8 @@
     SendFocusedInputChangedNotificationToBrowser(focused_element);
   }
 
-  if (!UsesKeyboardAccessoryForSuggestions() && focus_requires_scroll_) {
+  if (!config_.uses_keyboard_accessory_for_suggestions &&
+      focus_requires_scroll_) {
     HandleFocusChangeComplete(
         /*focused_node_was_last_clicked=*/
         last_left_mouse_down_or_gesture_tap_in_node_caused_focus_);
@@ -1792,6 +1781,14 @@
   submitted_forms_.clear();
 }
 
+DenseSet<ExtractOption> AutofillAgent::MaybeExtractDatalist(
+    DenseSet<ExtractOption> extract_options) {
+  if (config_.extract_all_datalists) {
+    extract_options.insert(ExtractOption::kDatalist);
+  }
+  return extract_options;
+}
+
 mojom::AutofillDriver* AutofillAgent::unsafe_autofill_driver() {
   if (IsPrerendering()) {
     if (!deferring_autofill_driver_) {
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h
index 9503823..7f92628 100644
--- a/components/autofill/content/renderer/autofill_agent.h
+++ b/components/autofill/content/renderer/autofill_agent.h
@@ -18,6 +18,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "base/types/strong_alias.h"
 #include "components/autofill/content/common/mojom/autofill_agent.mojom.h"
 #include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
 #include "components/autofill/content/renderer/form_autofill_util.h"
@@ -84,11 +85,30 @@
  public:
   static constexpr base::TimeDelta kFormsSeenThrottle = base::Milliseconds(100);
 
+  using UsesKeyboardAccessoryForSuggestions =
+      base::StrongAlias<class UsesKeyboardAccessoryForSuggestionsTag, bool>;
+  using ExtractAllDatalists =
+      base::StrongAlias<class ExtractAllDatalistsTag, bool>;
+
+  struct Config {
+    // Is true iff the platform doesn't show any popups but renders the same
+    // information in or near the keyboard instead.
+    UsesKeyboardAccessoryForSuggestions uses_keyboard_accessory_for_suggestions{
+        BUILDFLAG(IS_ANDROID)};
+
+    // Controls whether or not all datalists shall be extracted into
+    // FormFieldData. This feature is enabled when all datalists (instead of
+    // only the focused one) shall be extracted and sent to the Android Autofill
+    // service when the autofill session is created.
+    ExtractAllDatalists extract_all_datalists{false};
+  };
+
   // PasswordAutofillAgent is guaranteed to outlive AutofillAgent.
   // PasswordGenerationAgent and AutofillAssistantAgent may be nullptr. If they
   // are not, then they are also guaranteed to outlive AutofillAgent.
   AutofillAgent(
       content::RenderFrame* render_frame,
+      Config config,
       std::unique_ptr<PasswordAutofillAgent> password_autofill_agent,
       std::unique_ptr<PasswordGenerationAgent> password_generation_agent,
       blink::AssociatedInterfaceRegistry* registry);
@@ -371,6 +391,10 @@
   // cleared in this method.
   void OnFormNoLongerSubmittable();
 
+  // Amends the given `extract_options` with datalists if required.
+  DenseSet<form_util::ExtractOption> MaybeExtractDatalist(
+      DenseSet<form_util::ExtractOption> extract_options);
+
   // Helpers for SelectOrSelectListFieldOptionsChanged() and
   // DataListOptionsChanged(), which get called after a timer that is restarted
   // when another event of the same type started.
@@ -378,6 +402,10 @@
       const blink::WebFormControlElement& element);
   void BatchDataListOptionChange(const blink::WebFormControlElement& element);
 
+  // Stores immutable configuration this agent was created with. It contains
+  // features and settings that are available for the lifetime of this class.
+  const Config config_;
+
   // Return the next web node of `current_node` in the DOM. `next` determines
   // the direction to traverse in.
   blink::WebNode NextWebNode(const blink::WebNode& current_node, bool next);
diff --git a/components/autofill/content/renderer/autofill_agent_form_interaction_browsertest.cc b/components/autofill/content/renderer/autofill_agent_form_interaction_browsertest.cc
index 1d4a193..24b639c 100644
--- a/components/autofill/content/renderer/autofill_agent_form_interaction_browsertest.cc
+++ b/components/autofill/content/renderer/autofill_agent_form_interaction_browsertest.cc
@@ -389,8 +389,6 @@
 
 // Tests that unfocusing a contenteditable triggers a call to
 // `AutofillDriver::HidePopup()`.
-// The test is not enabled on Android because the keyboard accessory has
-// different hiding logic for which `HidePopup` is not called.
 TEST_F(AutofillAgentContentEditableInteractionTest,
        LossOfFocusOfContentEditableTriggersHideAutofillPopup) {
   MockFunction<void()> check;
diff --git a/components/autofill/content/renderer/autofill_renderer_test.cc b/components/autofill/content/renderer/autofill_renderer_test.cc
index 7ec4a4a..ba60d57 100644
--- a/components/autofill/content/renderer/autofill_renderer_test.cc
+++ b/components/autofill/content/renderer/autofill_renderer_test.cc
@@ -48,8 +48,9 @@
       GetMainRenderFrame(), password_autofill_agent.get(),
       &associated_interfaces_);
   autofill_agent_ = std::make_unique<AutofillAgent>(
-      GetMainRenderFrame(), std::move(password_autofill_agent),
-      std::move(password_generation), &associated_interfaces_);
+      GetMainRenderFrame(), AutofillAgent::Config(),
+      std::move(password_autofill_agent), std::move(password_generation),
+      &associated_interfaces_);
 }
 
 void AutofillRendererTest::TearDown() {
diff --git a/components/autofill/core/browser/autofill_client.cc b/components/autofill/core/browser/autofill_client.cc
index 7611704..b7035e0 100644
--- a/components/autofill/core/browser/autofill_client.cc
+++ b/components/autofill/core/browser/autofill_client.cc
@@ -297,6 +297,11 @@
   NOTIMPLEMENTED();
 }
 
+void AutofillClient::TriggerUserPerceptionOfAutofillSurvey(
+    const std::map<std::string, std::string>& field_filling_stats_data) {
+  NOTIMPLEMENTED();
+}
+
 std::unique_ptr<device_reauth::DeviceAuthenticator>
 AutofillClient::GetDeviceAuthenticator() {
   return nullptr;
diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h
index 3a4907f..1cc988c4 100644
--- a/components/autofill/core/browser/autofill_client.h
+++ b/components/autofill/core/browser/autofill_client.h
@@ -219,8 +219,8 @@
     // The user declined the save/update/migration flow from the edit dialog.
     kEditDeclined,
     // The user selected to never migrate a `kLocalOrSyncable` profile to the
-    // account storage.
-    // Currently unused for new profile and update prompts.
+    // account storage. Currently unused for new profile and update prompts, but
+    // is triggered by explicitly declining a migration prompt.
     kNever,
     // The user ignored the prompt.
     kIgnored,
@@ -858,6 +858,16 @@
       base::OnceClosure no_interactive_authentication_callback =
           base::OnceClosure());
 
+  // Maybe triggers a hats survey that measures the user's perception of
+  // Autofill. When triggering happens, the survey dialog will be displayed with
+  // a 10s delay. Note:  This survey should be triggered after form submissions.
+  // `field_filling_stats_data` contains a key-value string representation of
+  // `autofill_metrics::FormGroupFillingStats`. See
+  // chrome/browser/ui/hats/survey_config.cc for details on what values should
+  // be present.
+  virtual void TriggerUserPerceptionOfAutofillSurvey(
+      const std::map<std::string, std::string>& field_filling_stats_data);
+
   // Whether the Autocomplete feature of Autofill should be enabled.
   virtual bool IsAutocompleteEnabled() const = 0;
 
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index ab89e250..c728e727 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -305,14 +305,6 @@
              "AutofillEnableSupportForPhoneNumberTrunkTypes",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Controls whether or not all datalist shall be extracted into FormFieldData.
-// This feature is enabled in both WebView and WebLayer where all datalists
-// instead of only the focused one shall be extracted and sent to Android
-// autofill service when the autofill session created.
-BASE_FEATURE(kAutofillExtractAllDatalists,
-             "AutofillExtractAllDatalists",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 // If enabled, whenever form controls are removed from the DOM, the ChromeClient
 // is informed about this. This enables Autofill to trigger a reparsing of
 // forms.
@@ -320,13 +312,6 @@
              "AutofillDetectRemovedFormControls",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Indicates whether the platform requires support for the legacy dropdown for
-// datalists. This is enabled on WebView because the keyboard accessory is not
-// available.
-BASE_FEATURE(kAutofillLegacyDatalistDropdown,
-             "AutofillLegacyDatalistDropdown",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 // Replaces cached web elements in AutofillAgent and FormTracker by their
 // renderer ids.
 BASE_FEATURE(kAutofillReplaceCachedWebElementsByRendererIds,
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index de4600f..5f14b082 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -101,14 +101,10 @@
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillEnableZipOnlyAddressForms);
 COMPONENT_EXPORT(AUTOFILL)
-BASE_DECLARE_FEATURE(kAutofillExtractAllDatalists);
-COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillEnableSupportForPhoneNumberTrunkTypes);
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillDetectRemovedFormControls);
 COMPONENT_EXPORT(AUTOFILL)
-BASE_DECLARE_FEATURE(kAutofillLegacyDatalistDropdown);
-COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillReplaceCachedWebElementsByRendererIds);
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillUseAddressRewriterInProfileSubsetComparison);
diff --git a/components/content_settings/core/browser/website_settings_info.cc b/components/content_settings/core/browser/website_settings_info.cc
index 7366584..74c69f3 100644
--- a/components/content_settings/core/browser/website_settings_info.cc
+++ b/components/content_settings/core/browser/website_settings_info.cc
@@ -15,6 +15,8 @@
 namespace {
 
 const char kPrefPrefix[] = "profile.content_settings.exceptions.";
+const char kPartitionedPrefPrefix[] =
+    "profile.content_settings.partitioned_exceptions.";
 const char kDefaultPrefPrefix[] = "profile.default_content_setting_values.";
 
 std::string GetPreferenceName(const std::string& name, const char* prefix) {
@@ -37,6 +39,7 @@
     : type_(type),
       name_(name),
       pref_name_(GetPreferenceName(name, kPrefPrefix)),
+      partitioned_pref_name_(GetPreferenceName(name, kPartitionedPrefPrefix)),
       default_value_pref_name_(GetPreferenceName(name, kDefaultPrefPrefix)),
       initial_default_value_(std::move(initial_default_value)),
       sync_status_(sync_status),
diff --git a/components/content_settings/core/browser/website_settings_info.h b/components/content_settings/core/browser/website_settings_info.h
index c639abcc..c44e599 100644
--- a/components/content_settings/core/browser/website_settings_info.h
+++ b/components/content_settings/core/browser/website_settings_info.h
@@ -118,6 +118,9 @@
   const std::string& name() const { return name_; }
 
   const std::string& pref_name() const { return pref_name_; }
+  const std::string& partitioned_pref_name() const {
+    return partitioned_pref_name_;
+  }
   const std::string& default_value_pref_name() const {
     return default_value_pref_name_;
   }
@@ -137,6 +140,7 @@
   const std::string name_;
 
   const std::string pref_name_;
+  const std::string partitioned_pref_name_;
   const std::string default_value_pref_name_;
   const base::Value initial_default_value_;
   const SyncStatus sync_status_;
diff --git a/components/exo/buffer_unittest.cc b/components/exo/buffer_unittest.cc
index 6e1da35..1d06f3e 100644
--- a/components/exo/buffer_unittest.cc
+++ b/components/exo/buffer_unittest.cc
@@ -43,31 +43,6 @@
   base::test::ScopedFeatureList feature_list_;
 };
 
-base::RepeatingClosure CreateReleaseBufferClosure(
-    int* release_buffer_call_count,
-    base::RepeatingClosure closure) {
-  return base::BindLambdaForTesting(
-      [release_buffer_call_count, closure = std::move(closure)]() {
-        if (release_buffer_call_count) {
-          (*release_buffer_call_count)++;
-        }
-        closure.Run();
-      });
-}
-
-base::OnceCallback<void(gfx::GpuFenceHandle)> CreateExplicitReleaseCallback(
-    int* release_call_count,
-    base::RepeatingClosure closure) {
-  return base::BindLambdaForTesting(
-      [release_call_count,
-       closure = std::move(closure)](gfx::GpuFenceHandle release_fence) {
-        if (release_call_count) {
-          (*release_call_count)++;
-        }
-        closure.Run();
-      });
-}
-
 void VerifySyncTokensInCompositorFrame(viz::CompositorFrame* frame) {
   std::vector<GLbyte*> sync_tokens;
   for (auto& resource : frame->resource_list)
@@ -125,7 +100,7 @@
   // Set the release callback.
   int release_call_count = 0;
   base::RunLoop run_loop_1;
-  buffer->set_release_callback(CreateReleaseBufferClosure(
+  buffer->set_release_callback(test::CreateReleaseBufferClosure(
       &release_call_count, run_loop_1.QuitClosure()));
 
   buffer->OnAttach();
@@ -136,8 +111,8 @@
   bool rv = buffer->ProduceTransferableResource(
       frame_sink_holder->resource_manager(), nullptr, false, &resource,
       gfx::ColorSpace::CreateSRGB(), nullptr,
-      CreateExplicitReleaseCallback(&release_resource_count,
-                                    run_loop_2.QuitClosure()));
+      test::CreateExplicitReleaseCallback(&release_resource_count,
+                                          run_loop_2.QuitClosure()));
   ASSERT_TRUE(rv);
 
   // Release buffer.
@@ -173,8 +148,8 @@
   // Set the release callback.
   int release_call_count = 0;
   base::RunLoop run_loop;
-  buffer->set_release_callback(
-      CreateReleaseBufferClosure(&release_call_count, run_loop.QuitClosure()));
+  buffer->set_release_callback(test::CreateReleaseBufferClosure(
+      &release_call_count, run_loop.QuitClosure()));
 
   buffer->OnAttach();
   viz::TransferableResource resource;
@@ -183,8 +158,8 @@
   bool rv = buffer->ProduceTransferableResource(
       frame_sink_holder->resource_manager(), nullptr, false, &resource,
       gfx::ColorSpace::CreateSRGB(), nullptr,
-      CreateExplicitReleaseCallback(&release_resource_count,
-                                    base::DoNothing()));
+      test::CreateExplicitReleaseCallback(&release_resource_count,
+                                          base::DoNothing()));
   // Solid color buffer is immediately released after commit.
   EXPECT_EQ(release_resource_count, 1);
   EXPECT_FALSE(rv);
@@ -226,7 +201,7 @@
     bool rv = buffer->ProduceTransferableResource(
         frame_sink_holder->resource_manager(), nullptr, false, &resource,
         gfx::ColorSpace::CreateSRGB(), nullptr,
-        CreateExplicitReleaseCallback(nullptr, run_loop_1.QuitClosure()));
+        test::CreateExplicitReleaseCallback(nullptr, run_loop_1.QuitClosure()));
     ASSERT_TRUE(rv);
 
     scoped_refptr<viz::RasterContextProvider> context_provider =
@@ -255,7 +230,7 @@
     bool rv = buffer->ProduceTransferableResource(
         frame_sink_holder->resource_manager(), nullptr, false, &new_resource,
         gfx::ColorSpace::CreateSRGB(), nullptr,
-        CreateExplicitReleaseCallback(nullptr, run_loop_2.QuitClosure()));
+        test::CreateExplicitReleaseCallback(nullptr, run_loop_2.QuitClosure()));
     ASSERT_TRUE(rv);
     buffer->OnDetach();
 
@@ -320,8 +295,8 @@
   base::RunLoop run_loop;
   auto combined_quit_closure = BarrierClosure(2, run_loop.QuitClosure());
 
-  buffer->set_release_callback(
-      CreateReleaseBufferClosure(&release_call_count, combined_quit_closure));
+  buffer->set_release_callback(test::CreateReleaseBufferClosure(
+      &release_call_count, combined_quit_closure));
 
   buffer->OnAttach();
   viz::TransferableResource resource;
@@ -330,8 +305,8 @@
   bool rv = buffer->ProduceTransferableResource(
       frame_sink_holder->resource_manager(), nullptr, false, &resource,
       gfx::ColorSpace::CreateSRGB(), nullptr,
-      CreateExplicitReleaseCallback(&release_resource_count,
-                                    combined_quit_closure));
+      test::CreateExplicitReleaseCallback(&release_resource_count,
+                                          combined_quit_closure));
   ASSERT_TRUE(rv);
 
   // Submit frame with resource.
@@ -380,8 +355,8 @@
   base::RunLoop run_loop;
   auto combined_quit_closure = BarrierClosure(2, run_loop.QuitClosure());
 
-  buffer->set_release_callback(
-      CreateReleaseBufferClosure(&release_call_count, combined_quit_closure));
+  buffer->set_release_callback(test::CreateReleaseBufferClosure(
+      &release_call_count, combined_quit_closure));
 
   buffer->OnAttach();
   viz::TransferableResource resource;
@@ -390,8 +365,8 @@
   bool rv = buffer->ProduceTransferableResource(
       frame_sink_holder->resource_manager(), nullptr, false, &resource,
       gfx::ColorSpace::CreateSRGB(), nullptr,
-      CreateExplicitReleaseCallback(&release_resource_count,
-                                    combined_quit_closure));
+      test::CreateExplicitReleaseCallback(&release_resource_count,
+                                          combined_quit_closure));
   ASSERT_TRUE(rv);
 
   // Submit frame with resource.
@@ -513,8 +488,8 @@
   base::RunLoop run_loop1;
   auto combined_quit_closure = BarrierClosure(2, run_loop1.QuitClosure());
 
-  buffer->set_release_callback(
-      CreateReleaseBufferClosure(&release_call_count, combined_quit_closure));
+  buffer->set_release_callback(test::CreateReleaseBufferClosure(
+      &release_call_count, combined_quit_closure));
 
   buffer->OnAttach();
   viz::TransferableResource resource;
@@ -523,8 +498,8 @@
   bool rv = buffer->ProduceTransferableResource(
       frame_sink_holder->resource_manager(), nullptr, false, &resource,
       gfx::ColorSpace::CreateSRGB(), nullptr,
-      CreateExplicitReleaseCallback(&release_resource_count,
-                                    combined_quit_closure));
+      test::CreateExplicitReleaseCallback(&release_resource_count,
+                                          combined_quit_closure));
   ASSERT_TRUE(rv);
 
   // Submit frame with `resource`.
@@ -610,8 +585,8 @@
   base::RunLoop run_loop;
   auto combined_quit_closure = BarrierClosure(2, run_loop.QuitClosure());
 
-  buffer->set_release_callback(
-      CreateReleaseBufferClosure(&release_call_count, combined_quit_closure));
+  buffer->set_release_callback(test::CreateReleaseBufferClosure(
+      &release_call_count, combined_quit_closure));
 
   buffer->OnAttach();
   viz::TransferableResource resource;
@@ -620,8 +595,8 @@
   bool rv = buffer->ProduceTransferableResource(
       frame_sink_holder->resource_manager(), nullptr, false, &resource,
       gfx::ColorSpace::CreateSRGB(), nullptr,
-      CreateExplicitReleaseCallback(&release_resource_count,
-                                    combined_quit_closure));
+      test::CreateExplicitReleaseCallback(&release_resource_count,
+                                          combined_quit_closure));
   ASSERT_TRUE(rv);
 
   frame_sink_holder->ClearPendingBeginFramesForTesting();
@@ -689,8 +664,8 @@
   base::RunLoop run_loop1;
   auto combined_quit_closure = BarrierClosure(2, run_loop1.QuitClosure());
 
-  buffer->set_release_callback(
-      CreateReleaseBufferClosure(&release_call_count, combined_quit_closure));
+  buffer->set_release_callback(test::CreateReleaseBufferClosure(
+      &release_call_count, combined_quit_closure));
 
   buffer->OnAttach();
   viz::TransferableResource resource;
@@ -699,8 +674,8 @@
   bool rv = buffer->ProduceTransferableResource(
       frame_sink_holder->resource_manager(), nullptr, false, &resource,
       gfx::ColorSpace::CreateSRGB(), nullptr,
-      CreateExplicitReleaseCallback(&release_resource_count,
-                                    combined_quit_closure));
+      test::CreateExplicitReleaseCallback(&release_resource_count,
+                                          combined_quit_closure));
   ASSERT_TRUE(rv);
 
   // Submit frame with `resource`.
diff --git a/components/exo/surface_unittest.cc b/components/exo/surface_unittest.cc
index 9e45bf8f..437774c 100644
--- a/components/exo/surface_unittest.cc
+++ b/components/exo/surface_unittest.cc
@@ -174,25 +174,6 @@
   base::test::ScopedFeatureList feature_list_;
 };
 
-void ReleaseBuffer(int* release_buffer_call_count) {
-  (*release_buffer_call_count)++;
-}
-
-base::RepeatingClosure CreateReleaseBufferClosure(
-    int* release_buffer_call_count,
-    base::RepeatingClosure closure) {
-  return base::BindLambdaForTesting(
-      [release_buffer_call_count, closure = std::move(closure)]() {
-        (*release_buffer_call_count)++;
-        closure.Run();
-      });
-}
-
-void ExplicitReleaseBuffer(int* release_buffer_call_count,
-                           gfx::GpuFenceHandle release_fence) {
-  (*release_buffer_call_count)++;
-}
-
 // Instantiate the values of frame submission types and device scale factor in
 // the parameterized tests.
 INSTANTIATE_TEST_SUITE_P(
@@ -1293,7 +1274,7 @@
 
   int release_buffer_call_count = 0;
   base::RunLoop run_loop;
-  buffer->set_release_callback(CreateReleaseBufferClosure(
+  buffer->set_release_callback(test::CreateReleaseBufferClosure(
       &release_buffer_call_count, run_loop.QuitClosure()));
 
   surface->Attach(buffer.get());
@@ -1401,9 +1382,8 @@
   EXPECT_FALSE(surface->HasPendingPerCommitBufferReleaseCallback());
 }
 
-// TODO(crbug.com/1292674): Flaky.
-TEST_P(SurfaceTest, DISABLED_PerCommitBufferReleaseCallbackForSameSurface) {
-  gfx::Size buffer_size(1, 1);
+TEST_P(SurfaceTest, PerCommitBufferReleaseCallbackForSameSurface) {
+  gfx::Size buffer_size(64, 64);
   auto buffer1 = std::make_unique<Buffer>(
       exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
   auto buffer2 = std::make_unique<Buffer>(
@@ -1414,39 +1394,48 @@
 
   // Set the release callback that will be run when buffer is no longer in use.
   int buffer_release_count = 0;
-  buffer1->set_release_callback(base::BindRepeating(
-      &ReleaseBuffer, base::Unretained(&buffer_release_count)));
+  base::RunLoop run_loop1;
+  buffer1->set_release_callback(test::CreateReleaseBufferClosure(
+      &buffer_release_count, run_loop1.QuitClosure()));
 
-  surface->SetPerCommitBufferReleaseCallback(base::BindOnce(
-      &ExplicitReleaseBuffer, base::Unretained(&per_commit_release_count)));
+  base::RunLoop run_loop2;
+  surface->SetPerCommitBufferReleaseCallback(
+      test::CreateExplicitReleaseCallback(&per_commit_release_count,
+                                          run_loop2.QuitClosure()));
   surface->Attach(buffer1.get());
+  surface->Damage(gfx::Rect(buffer_size));
   surface->Commit();
-  test::WaitForLastFrameAck(shell_surface.get());
+  test::WaitForLastFramePresentation(shell_surface.get());
   EXPECT_EQ(per_commit_release_count, 0);
   EXPECT_EQ(buffer_release_count, 0);
 
   // Attaching the same buffer causes the per-commit callback to be emitted.
-  surface->SetPerCommitBufferReleaseCallback(base::BindOnce(
-      &ExplicitReleaseBuffer, base::Unretained(&per_commit_release_count)));
+  surface->SetPerCommitBufferReleaseCallback(
+      test::CreateExplicitReleaseCallback(&per_commit_release_count,
+                                          base::DoNothing()));
   surface->Attach(buffer1.get());
+  surface->Damage(gfx::Rect(buffer_size));
   surface->Commit();
-  test::WaitForLastFrameAck(shell_surface.get());
+  test::WaitForLastFramePresentation(shell_surface.get());
+
+  run_loop2.Run();
   EXPECT_EQ(per_commit_release_count, 1);
   EXPECT_EQ(buffer_release_count, 0);
 
   // Attaching a different buffer causes the per-commit callback to be emitted.
   surface->Attach(buffer2.get());
+  surface->Damage(gfx::Rect(buffer_size));
   surface->Commit();
-  test::WaitForLastFrameAck(shell_surface.get());
+  test::WaitForLastFramePresentation(shell_surface.get());
+
+  run_loop1.Run();
   EXPECT_EQ(per_commit_release_count, 2);
   // The buffer should now be completely released.
   EXPECT_EQ(buffer_release_count, 1);
 }
 
-// TODO(crbug.com/1292674): Flaky.
-TEST_P(SurfaceTest,
-       DISABLED_PerCommitBufferReleaseCallbackForDifferentSurfaces) {
-  gfx::Size buffer_size(1, 1);
+TEST_P(SurfaceTest, PerCommitBufferReleaseCallbackForDifferentSurfaces) {
+  gfx::Size buffer_size(64, 64);
   auto buffer1 = std::make_unique<Buffer>(
       exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
   auto buffer2 = std::make_unique<Buffer>(
@@ -1460,35 +1449,48 @@
 
   // Set the release callback that will be run when buffer is no longer in use.
   int buffer_release_count = 0;
-  buffer1->set_release_callback(base::BindRepeating(
-      &ReleaseBuffer, base::Unretained(&buffer_release_count)));
+  base::RunLoop run_loop1;
+  buffer1->set_release_callback(test::CreateReleaseBufferClosure(
+      &buffer_release_count, run_loop1.QuitClosure()));
 
   // Attach buffer1 to both surface1 and surface2.
-  surface1->SetPerCommitBufferReleaseCallback(base::BindOnce(
-      &ExplicitReleaseBuffer, base::Unretained(&per_commit_release_count1)));
+  base::RunLoop run_loop2;
+  surface1->SetPerCommitBufferReleaseCallback(
+      test::CreateExplicitReleaseCallback(&per_commit_release_count1,
+                                          run_loop2.QuitClosure()));
   surface1->Attach(buffer1.get());
+  surface1->Damage(gfx::Rect(buffer_size));
   surface1->Commit();
-  surface2->SetPerCommitBufferReleaseCallback(base::BindOnce(
-      &ExplicitReleaseBuffer, base::Unretained(&per_commit_release_count2)));
+  surface2->SetPerCommitBufferReleaseCallback(
+      test::CreateExplicitReleaseCallback(&per_commit_release_count2,
+                                          base::DoNothing()));
   surface2->Attach(buffer1.get());
+  surface2->Damage(gfx::Rect(buffer_size));
   surface2->Commit();
-  test::WaitForLastFrameAck(shell_surface2.get());
+  test::WaitForLastFramePresentation(shell_surface2.get());
+
   EXPECT_EQ(per_commit_release_count1, 0);
   EXPECT_EQ(per_commit_release_count2, 0);
   EXPECT_EQ(buffer_release_count, 0);
 
   // Attach buffer2 to surface1, only the surface1 callback should be emitted.
   surface1->Attach(buffer2.get());
+  surface1->Damage(gfx::Rect(buffer_size));
   surface1->Commit();
-  test::WaitForLastFrameAck(shell_surface1.get());
+  test::WaitForLastFramePresentation(shell_surface1.get());
+
+  run_loop2.Run();
   EXPECT_EQ(per_commit_release_count1, 1);
   EXPECT_EQ(per_commit_release_count2, 0);
   EXPECT_EQ(buffer_release_count, 0);
 
   // Attach buffer2 to surface2, only the surface2 callback should be emitted.
   surface2->Attach(buffer2.get());
+  surface2->Damage(gfx::Rect(buffer_size));
   surface2->Commit();
-  test::WaitForLastFrameAck(shell_surface2.get());
+  test::WaitForLastFramePresentation(shell_surface2.get());
+
+  run_loop1.Run();
   EXPECT_EQ(per_commit_release_count1, 1);
   EXPECT_EQ(per_commit_release_count2, 1);
   // The buffer should now be completely released.
diff --git a/components/exo/test/surface_tree_host_test_util.cc b/components/exo/test/surface_tree_host_test_util.cc
index ef59585..27a6fa2 100644
--- a/components/exo/test/surface_tree_host_test_util.cc
+++ b/components/exo/test/surface_tree_host_test_util.cc
@@ -61,4 +61,29 @@
   runloop.Run();
 }
 
+base::RepeatingClosure CreateReleaseBufferClosure(
+    int* release_buffer_call_count,
+    base::RepeatingClosure closure) {
+  return base::BindLambdaForTesting(
+      [release_buffer_call_count, closure = std::move(closure)]() {
+        if (release_buffer_call_count) {
+          (*release_buffer_call_count)++;
+        }
+        closure.Run();
+      });
+}
+
+base::OnceCallback<void(gfx::GpuFenceHandle)> CreateExplicitReleaseCallback(
+    int* release_call_count,
+    base::RepeatingClosure closure) {
+  return base::BindLambdaForTesting(
+      [release_call_count,
+       closure = std::move(closure)](gfx::GpuFenceHandle release_fence) {
+        if (release_call_count) {
+          (*release_call_count)++;
+        }
+        closure.Run();
+      });
+}
+
 }  // namespace exo::test
diff --git a/components/exo/test/surface_tree_host_test_util.h b/components/exo/test/surface_tree_host_test_util.h
index 0450ad7d..e6d55ca 100644
--- a/components/exo/test/surface_tree_host_test_util.h
+++ b/components/exo/test/surface_tree_host_test_util.h
@@ -40,6 +40,20 @@
           }));
 }
 
+// Creates a closure which increments `release_buffer_call_count` and then calls
+// `closure` when called. This is used to wait for buffers to be released in
+// tests.
+base::RepeatingClosure CreateReleaseBufferClosure(
+    int* release_buffer_call_count,
+    base::RepeatingClosure closure);
+
+// Creates a closure which increments `release_call_count` and then calls
+// `closure` when called. This is used to wait for buffers to be released in
+// tests.
+base::OnceCallback<void(gfx::GpuFenceHandle)> CreateExplicitReleaseCallback(
+    int* release_call_count,
+    base::RepeatingClosure closure);
+
 }  // namespace exo::test
 
 #endif  // COMPONENTS_EXO_TEST_SURFACE_TREE_HOST_TEST_UTIL_H_
diff --git a/components/nacl/loader/nacl_helper_linux.cc b/components/nacl/loader/nacl_helper_linux.cc
index 2bd6db7..47872b7 100644
--- a/components/nacl/loader/nacl_helper_linux.cc
+++ b/components/nacl/loader/nacl_helper_linux.cc
@@ -135,9 +135,8 @@
   // necessary to get e.g. any field trial handle and feature overrides from
   // whomever initiated the this fork request.
   base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
-  base::CommandLine passed_command_line(base::CommandLine::NO_PROGRAM);
-  passed_command_line.InitFromArgv(args);
-  command_line.AppendArguments(passed_command_line, /*include_program=*/false);
+  command_line.AppendArguments(base::CommandLine::FromArgvWithoutProgram(args),
+                               /*include_program=*/false);
   if (command_line.HasSwitch(switches::kVerboseLoggingInNacl)) {
     base::Environment::Create()->SetVar(
         "NACLVERBOSITY",
diff --git a/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc b/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc
index 5c808b09..bee45b7 100644
--- a/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc
+++ b/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc
@@ -28,6 +28,10 @@
 std::unique_ptr<blink::URLLoaderThrottle>
 NoStatePrefetchHelper::MaybeCreateThrottle(
     const blink::LocalFrameToken& frame_token) {
+  // Currently NoStatePrefetchHelper doesn't work on the background thread.
+  if (!content::RenderThread::IsMainThread()) {
+    return nullptr;
+  }
   blink::WebLocalFrame* web_frame =
       blink::WebLocalFrame::FromFrameToken(frame_token);
   if (!web_frame) {
diff --git a/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc
index efbb0da..50d9e4a 100644
--- a/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc
+++ b/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc
@@ -64,56 +64,6 @@
 const char kPageLoadPrerenderObserverEvent[] =
     "PageLoad.Internal.Prerender2.ObserverEvent";
 
-// This metric is used for debugging https://crbug.com/1379491.
-const char kPageLoadPrerenderForegroundCheckResult[] =
-    "PageLoad.Internal.Prerender2.ForegroundCheckResult";
-
-namespace {
-
-// This is a copy of WasActivatedInForegroundOptionalEventInForeground() in
-// page_load_metrics_util.h but with recording diagnose metrics for
-// https://crbug.com/1379491. Please keep this consistent with the function.
-bool WasActivatedInForegroundOptionalEventInForeground(
-    const absl::optional<base::TimeDelta>& event,
-    const page_load_metrics::PageLoadMetricsObserverDelegate& delegate,
-    PageLoadPrerenderForegroundCheckEvent event_type) {
-  auto result = PageLoadPrerenderForegroundCheckResult::kPassed;
-  if (!delegate.WasPrerenderedThenActivatedInForeground()) {
-    result = PageLoadPrerenderForegroundCheckResult::kActivatedInBackground;
-  } else if (!event) {
-    result = PageLoadPrerenderForegroundCheckResult::kNoEventTime;
-  } else if (delegate.GetTimeToFirstBackground() &&
-             delegate.GetTimeToFirstBackground().value() < event.value()) {
-    result = PageLoadPrerenderForegroundCheckResult::kBackgroundedBeforeEvent;
-  }
-
-  // Make sure that this function is consistent with the original function.
-  CHECK_EQ(result == PageLoadPrerenderForegroundCheckResult::kPassed,
-           page_load_metrics::WasActivatedInForegroundOptionalEventInForeground(
-               event, delegate));
-
-  std::string histogram_name = kPageLoadPrerenderForegroundCheckResult;
-  switch (event_type) {
-    case PageLoadPrerenderForegroundCheckEvent::kFirstPaint:
-      histogram_name += ".FirstPaint";
-      break;
-    case PageLoadPrerenderForegroundCheckEvent::kFirstContentfulPaint:
-      histogram_name += ".FirstContentfulPaint";
-      break;
-    case PageLoadPrerenderForegroundCheckEvent::kFirstInputDelay:
-      histogram_name += ".FirstInputDelay";
-      break;
-    case PageLoadPrerenderForegroundCheckEvent::kLargestContentfulPaint:
-      histogram_name += ".LargestContentfulPaint";
-      break;
-  }
-  base::UmaHistogramEnumeration(histogram_name, result);
-
-  return result == PageLoadPrerenderForegroundCheckResult::kPassed;
-}
-
-}  // namespace
-
 }  // namespace internal
 
 PrerenderPageLoadMetricsObserver::PrerenderPageLoadMetricsObserver() = default;
@@ -200,9 +150,8 @@
       internal::kPageLoadPrerenderObserverEvent,
       internal::PageLoadPrerenderObserverEvent::kOnFirstPaintInPage);
 
-  if (!internal::WasActivatedInForegroundOptionalEventInForeground(
-          timing.paint_timing->first_paint, GetDelegate(),
-          internal::PageLoadPrerenderForegroundCheckEvent::kFirstPaint)) {
+  if (!WasActivatedInForegroundOptionalEventInForeground(
+          timing.paint_timing->first_paint, GetDelegate())) {
     return;
   }
   base::TimeDelta activation_to_fp =
@@ -219,10 +168,8 @@
       internal::kPageLoadPrerenderObserverEvent,
       internal::PageLoadPrerenderObserverEvent::kOnFirstContentfulPaintInPage);
 
-  if (!internal::WasActivatedInForegroundOptionalEventInForeground(
-          timing.paint_timing->first_contentful_paint, GetDelegate(),
-          internal::PageLoadPrerenderForegroundCheckEvent::
-              kFirstContentfulPaint)) {
+  if (!WasActivatedInForegroundOptionalEventInForeground(
+          timing.paint_timing->first_contentful_paint, GetDelegate())) {
     return;
   }
   base::TimeDelta activation_to_fcp =
@@ -244,9 +191,8 @@
       internal::kPageLoadPrerenderObserverEvent,
       internal::PageLoadPrerenderObserverEvent::kOnFirstInputInPage);
 
-  if (!internal::WasActivatedInForegroundOptionalEventInForeground(
-          timing.interactive_timing->first_input_timestamp, GetDelegate(),
-          internal::PageLoadPrerenderForegroundCheckEvent::kFirstInputDelay)) {
+  if (!WasActivatedInForegroundOptionalEventInForeground(
+          timing.interactive_timing->first_input_timestamp, GetDelegate())) {
     return;
   }
 
@@ -326,10 +272,8 @@
           .GetLargestContentfulPaintHandler()
           .MergeMainFrameAndSubframes();
   if (largest_contentful_paint.ContainsValidTime() &&
-      internal::WasActivatedInForegroundOptionalEventInForeground(
-          largest_contentful_paint.Time(), GetDelegate(),
-          internal::PageLoadPrerenderForegroundCheckEvent::
-              kLargestContentfulPaint)) {
+      WasActivatedInForegroundOptionalEventInForeground(
+          largest_contentful_paint.Time(), GetDelegate())) {
     base::TimeDelta activation_to_lcp =
         largest_contentful_paint.Time().value() -
         main_frame_timing.activation_start.value();
diff --git a/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.h b/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.h
index f40373fb..efdb795 100644
--- a/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.h
+++ b/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.h
@@ -50,25 +50,6 @@
   kMaxValue = kRecordNormalizedResponsivenessMetrics,
 };
 
-extern const char kPageLoadPrerenderForegroundCheckResult[];
-
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-enum class PageLoadPrerenderForegroundCheckResult {
-  kActivatedInBackground = 0,
-  kNoEventTime = 1,
-  kBackgroundedBeforeEvent = 2,
-  kPassed = 3,
-  kMaxValue = kPassed
-};
-
-enum class PageLoadPrerenderForegroundCheckEvent {
-  kFirstPaint,
-  kFirstContentfulPaint,
-  kFirstInputDelay,
-  kLargestContentfulPaint
-};
-
 }  // namespace internal
 
 namespace page_load_metrics {
diff --git a/components/permissions/BUILD.gn b/components/permissions/BUILD.gn
index 6f0a6ca..ba0dffc9 100644
--- a/components/permissions/BUILD.gn
+++ b/components/permissions/BUILD.gn
@@ -135,6 +135,7 @@
     "//third_party/blink/public/common",
     "//third_party/sqlite",
     "//ui/base",
+    "//ui/strings:ui_strings_grit",
     "//url",
   ]
   if (is_mac || is_chromeos) {
@@ -188,9 +189,9 @@
       "//components/prefs",
       "//components/resources:android_resources",
       "//components/security_state/core:core",
+      "//components/strings:components_strings_grit",
       "//third_party/jni_zero",
       "//ui/android",
-      "//ui/strings:ui_strings_grit",
     ]
   } else {
     sources += [
diff --git a/components/permissions/DEPS b/components/permissions/DEPS
index affaf19c..ea0efa9 100644
--- a/components/permissions/DEPS
+++ b/components/permissions/DEPS
@@ -42,4 +42,5 @@
   "+ui/base",
   "+ui/events",
   "+ui/gfx",
+  "+ui/strings/grit/ui_strings.h"
 ]
diff --git a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewModelFactory.java b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewModelFactory.java
index 1b956f8..dc5c6b8 100644
--- a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewModelFactory.java
+++ b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewModelFactory.java
@@ -24,6 +24,9 @@
         return new PropertyModel.Builder(PermissionDialogCustomViewProperties.ALL_KEYS)
                 .with(PermissionDialogCustomViewProperties.MESSAGE_TEXT, messageText)
                 .with(
+                        PermissionDialogCustomViewProperties.BOLDED_RANGES,
+                        delegate.getBoldedRanges())
+                .with(
                         PermissionDialogCustomViewProperties.ICON,
                         ResourcesCompat.getDrawable(
                                 context.getResources(),
diff --git a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewProperties.java b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewProperties.java
index a99ee94..e7255678 100644
--- a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewProperties.java
+++ b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewProperties.java
@@ -7,9 +7,13 @@
 import android.content.res.ColorStateList;
 import android.graphics.drawable.Drawable;
 
+import androidx.core.util.Pair;
+
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
+import java.util.List;
+
 /**
  * The class is responsible for specifying the various properties of the Permission Dialog's custom
  * view.
@@ -23,6 +27,8 @@
 
     public static final PropertyModel.ReadableObjectPropertyKey<String> MESSAGE_TEXT =
             new PropertyModel.ReadableObjectPropertyKey();
+    public static final PropertyModel.ReadableObjectPropertyKey<List<Pair<Integer, Integer>>>
+            BOLDED_RANGES = new PropertyModel.ReadableObjectPropertyKey();
 
-    public static final PropertyKey[] ALL_KEYS = {ICON, ICON_TINT, MESSAGE_TEXT};
+    public static final PropertyKey[] ALL_KEYS = {ICON, ICON_TINT, MESSAGE_TEXT, BOLDED_RANGES};
 }
diff --git a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogDelegate.java b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogDelegate.java
index b552ed78..ce51c32 100644
--- a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogDelegate.java
+++ b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogDelegate.java
@@ -6,12 +6,17 @@
 
 import android.graphics.Bitmap;
 
+import androidx.core.util.Pair;
+
 import org.jni_zero.CalledByNative;
 import org.jni_zero.JNINamespace;
 import org.jni_zero.NativeMethods;
 
 import org.chromium.ui.base.WindowAndroid;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Delegate class for modal permission dialogs. Contains all of the data displayed in a prompt,
  * including the button strings, message text and the icon.
@@ -52,6 +57,12 @@
     /** The {@link ContentSettingsType}s requested in this dialog.  */
     private int[] mContentSettingsTypes;
 
+    /**
+     * Defines a (potentially empty) list of ranges represented as pairs of <startIndex, endIndex>,
+     * which shall be used by the UI to format the specified ranges as bold text.
+     */
+    private List<Pair<Integer, Integer>> mBoldedRanges = new ArrayList<>();
+
     public WindowAndroid getWindow() {
         return mWindow;
     }
@@ -72,6 +83,10 @@
         return mMessageText;
     }
 
+    public List<Pair<Integer, Integer>> getBoldedRanges() {
+        return mBoldedRanges;
+    }
+
     public String getPositiveButtonText() {
         return mPositiveButtonText;
     }
@@ -149,6 +164,8 @@
      * @param contentSettingsTypes The content settings types requested by this dialog.
      * @param iconId The id of the icon to display in the dialog.
      * @param message The message to display in the dialog.
+     * @param boldedRanges A list of ranges (pairs of <textOffset, rangeSize>) that should be
+     *     formatted as bold in the message.
      * @param positiveButtonText The text to display on the persistent grant button.
      * @param negativeButtonText The text to display on the persistent deny button.
      * @param positiveEphemeralButtonText The text to display on the ephemeral grant button. May be
@@ -161,15 +178,19 @@
             int[] contentSettingsTypes,
             int iconId,
             String message,
+            int[] boldedRanges,
             String positiveButtonText,
             String negativeButtonText,
             String positiveEphemeralButtonText) {
+        assert (boldedRanges.length % 2 == 0); // Contains a list of offset and length values
+
         return new PermissionDialogDelegate(
                 nativeDelegatePtr,
                 window,
                 contentSettingsTypes,
                 iconId,
                 message,
+                boldedRanges,
                 positiveButtonText,
                 negativeButtonText,
                 positiveEphemeralButtonText);
@@ -182,6 +203,7 @@
             int[] contentSettingsTypes,
             int iconId,
             String message,
+            int[] boldedRanges,
             String positiveButtonText,
             String negativeButtonText,
             String positiveEphemeralButtonText) {
@@ -190,6 +212,9 @@
         mContentSettingsTypes = contentSettingsTypes;
         mDrawableId = iconId;
         mMessageText = message;
+        for (int i = 0; i + 1 < boldedRanges.length; i += 2) {
+            mBoldedRanges.add(new Pair(boldedRanges[i], boldedRanges[i] + boldedRanges[i + 1]));
+        }
         mPositiveButtonText = positiveButtonText;
         mNegativeButtonText = negativeButtonText;
         mPositiveEphemeralButtonText = positiveEphemeralButtonText;
diff --git a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionOneTimeDialogCustomViewBinder.java b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionOneTimeDialogCustomViewBinder.java
index d80a5fa..10d1c6f 100644
--- a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionOneTimeDialogCustomViewBinder.java
+++ b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionOneTimeDialogCustomViewBinder.java
@@ -15,17 +15,28 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.core.util.Pair;
 
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /** The {@View} binder class for the PermissionDialogCustomView MVC. */
 class PermissionOneTimeDialogCustomViewBinder {
     public static void bind(PropertyModel model, View customView, PropertyKey propertyKey) {
         if (PermissionDialogCustomViewProperties.MESSAGE_TEXT == propertyKey) {
             assert model.get(PermissionDialogCustomViewProperties.MESSAGE_TEXT) != null;
+            List<Pair<Integer, Integer>> boldedRanges = new ArrayList<>();
+            if (model.containsKey(PermissionDialogCustomViewProperties.BOLDED_RANGES)
+                    && model.get(PermissionDialogCustomViewProperties.BOLDED_RANGES) != null) {
+                boldedRanges.addAll(model.get(PermissionDialogCustomViewProperties.BOLDED_RANGES));
+            }
             updateMessageText(
-                    customView, model.get(PermissionDialogCustomViewProperties.MESSAGE_TEXT));
+                    customView,
+                    model.get(PermissionDialogCustomViewProperties.MESSAGE_TEXT),
+                    boldedRanges);
         } else if (PermissionDialogCustomViewProperties.ICON == propertyKey) {
             assert model.get(PermissionDialogCustomViewProperties.ICON) != null;
             updateIcon(customView, model.get(PermissionDialogCustomViewProperties.ICON));
@@ -34,14 +45,21 @@
         }
     }
 
-    private static void updateMessageText(@NonNull View customView, @NonNull String messageText) {
+    private static void updateMessageText(
+            @NonNull View customView,
+            @NonNull String messageText,
+            List<Pair<Integer, Integer>> boldedRanges) {
         TextView messageTextView = customView.findViewById(R.id.text);
         final SpannableStringBuilder sb = new SpannableStringBuilder(messageText);
         final StyleSpan bss = new StyleSpan(android.graphics.Typeface.BOLD);
-
-        // TODO(crbug.com/1512613): The assumption that the first word in the message is the origin
-        // doesn't hold for all languages.
-        sb.setSpan(bss, 0, messageText.indexOf(' '), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+        boldedRanges.forEach(
+                boldRange -> {
+                    sb.setSpan(
+                            bss,
+                            boldRange.first,
+                            boldRange.second,
+                            Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+                });
         messageTextView.setText(sb);
     }
 
diff --git a/components/permissions/android/permission_prompt/permission_dialog_delegate.cc b/components/permissions/android/permission_prompt/permission_dialog_delegate.cc
index b4efc44e..6901a85 100644
--- a/components/permissions/android/permission_prompt/permission_dialog_delegate.cc
+++ b/components/permissions/android/permission_prompt/permission_dialog_delegate.cc
@@ -67,14 +67,23 @@
         static_cast<int>(permission_prompt_->GetContentSettingType(i)));
   }
 
+  PermissionRequest::AnnotatedMessageText annotatedMessageText =
+      permission_prompt_->GetAnnotatedMessageText();
+  std::vector<int> bolded_ranges;
+  for (auto [start, length] : annotatedMessageText.bolded_ranges) {
+    bolded_ranges.push_back(base::checked_cast<int>(start));
+    bolded_ranges.push_back(base::checked_cast<int>(length));
+  }
+
   j_delegate_.Reset(Java_PermissionDialogDelegate_create(
       env, reinterpret_cast<uintptr_t>(owner),
       web_contents->GetTopLevelNativeWindow()->GetJavaObject(),
       base::android::ToJavaIntArray(env, content_settings_types),
       PermissionsClient::Get()->MapToJavaDrawableId(
           permission_prompt_->GetIconId()),
-      ConvertUTF16ToJavaString(env, permission_prompt_->GetMessageText()),
-      positiveButtonText, negativeButtonText, positiveEphemeralButtonText));
+      ConvertUTF16ToJavaString(env, annotatedMessageText.text),
+      base::android::ToJavaIntArray(env, bolded_ranges), positiveButtonText,
+      negativeButtonText, positiveEphemeralButtonText));
 }
 
 void PermissionDialogJavaDelegate::CreateDialog(
diff --git a/components/permissions/android/permission_prompt/permission_prompt_android.cc b/components/permissions/android/permission_prompt/permission_prompt_android.cc
index 5ebd924..65b331c 100644
--- a/components/permissions/android/permission_prompt/permission_prompt_android.cc
+++ b/components/permissions/android/permission_prompt/permission_prompt_android.cc
@@ -124,52 +124,27 @@
   return IDR_ANDROID_INFOBAR_MEDIA_STREAM_CAMERA;
 }
 
-std::u16string PermissionPromptAndroid::GetMessageText() const {
+PermissionRequest::AnnotatedMessageText
+PermissionPromptAndroid::GetAnnotatedMessageText() const {
   const std::vector<raw_ptr<PermissionRequest, VectorExperimental>>& requests =
       delegate_->Requests();
   if (requests.size() == 1) {
-    if (requests[0]->request_type() == RequestType::kStorageAccess) {
-      if (base::FeatureList::IsEnabled(
-              permissions::features::kPermissionStorageAccessAPI)) {
-        auto patterns =
-            HostContentSettingsMap::GetPatternsForContentSettingsType(
-                delegate_->GetRequestingOrigin(),
-                delegate_->GetEmbeddingOrigin(),
-                ContentSettingsType::STORAGE_ACCESS);
-
-        auto requesting_origin = url_formatter::FormatUrlForSecurityDisplay(
-            patterns.first.ToRepresentativeUrl(),
-            url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
-        auto embedding_origin = url_formatter::FormatUrlForSecurityDisplay(
-            patterns.second.ToRepresentativeUrl(),
-            url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
-
-        return l10n_util::GetStringFUTF16(
-            IDS_CONCAT_TWO_STRINGS_WITH_PERIODS,
-            l10n_util::GetStringFUTF16(
-                IDS_STORAGE_ACCESS_PERMISSION_TWO_ORIGIN_PROMPT_TITLE,
-                requesting_origin),
-            l10n_util::GetStringFUTF16(
-                IDS_STORAGE_ACCESS_PERMISSION_TWO_ORIGIN_EXPLANATION,
-                requesting_origin, embedding_origin));
-      }
-      return l10n_util::GetStringFUTF16(
-          IDS_STORAGE_ACCESS_INFOBAR_TEXT,
-          url_formatter::FormatUrlForSecurityDisplay(
-              delegate_->GetRequestingOrigin(),
-              url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC),
-          url_formatter::FormatUrlForSecurityDisplay(
-              delegate_->GetEmbeddingOrigin(),
-              url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
-    }
-    return requests[0]->GetDialogMessageText();
+    return requests[0]->GetDialogAnnotatedMessageText(
+        delegate_->GetEmbeddingOrigin());
   }
   CheckValidRequestGroup(requests);
-  return l10n_util::GetStringFUTF16(
-      IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_INFOBAR_TEXT,
+
+  // We only end up here if 2 requests are combined in one prompt (which only
+  // happens for Audio & Video). All other requests are handled in the if block
+  // above. For Audio and Video (which can be allowed once), only format origins
+  // bold if one time permissions are enabled.
+  return PermissionRequest::GetDialogAnnotatedMessageText(
       url_formatter::FormatUrlForSecurityDisplay(
           delegate_->GetRequestingOrigin(),
-          url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
+          url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC),
+      IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_INFOBAR_TEXT,
+      /*format_origin_bold=*/
+      base::FeatureList::IsEnabled(permissions::features::kOneTimePermission));
 }
 
 bool PermissionPromptAndroid::ShouldUseRequestingOriginFavicon() const {
diff --git a/components/permissions/android/permission_prompt/permission_prompt_android.h b/components/permissions/android/permission_prompt/permission_prompt_android.h
index dd4deaf..5b8509f 100644
--- a/components/permissions/android/permission_prompt/permission_prompt_android.h
+++ b/components/permissions/android/permission_prompt/permission_prompt_android.h
@@ -6,14 +6,11 @@
 #define COMPONENTS_PERMISSIONS_ANDROID_PERMISSION_PROMPT_PERMISSION_PROMPT_ANDROID_H_
 
 #include <memory>
-#include <string>
-
 #include "base/memory/raw_ptr.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/permissions/permission_prompt.h"
 #include "components/permissions/permission_uma_util.h"
 #include "components/permissions/permissions_client.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace content {
@@ -60,7 +57,9 @@
   size_t PermissionCount() const;
   ContentSettingsType GetContentSettingType(size_t position) const;
   int GetIconId() const;
-  std::u16string GetMessageText() const;
+
+  PermissionRequest::AnnotatedMessageText GetAnnotatedMessageText() const;
+
   bool ShouldUseRequestingOriginFavicon() const;
 
   GURL GetRequestingOrigin() const;
diff --git a/components/permissions/contexts/geolocation_permission_context_unittest.cc b/components/permissions/contexts/geolocation_permission_context_unittest.cc
index d792cfe4..24daf46 100644
--- a/components/permissions/contexts/geolocation_permission_context_unittest.cc
+++ b/components/permissions/contexts/geolocation_permission_context_unittest.cc
@@ -514,7 +514,10 @@
       PermissionRequestManager::FromWebContents(web_contents());
   PermissionRequest* request = manager->Requests().front();
 #if BUILDFLAG(IS_ANDROID)
-  return request->GetDialogMessageText();
+  return request
+      ->GetDialogAnnotatedMessageText(
+          /*embedding_origin=*/request->requesting_origin())
+      .text;
 #else
   return base::ASCIIToUTF16(request->requesting_origin().spec()) +
          request->GetMessageTextFragment();
diff --git a/components/permissions/permission_request.cc b/components/permissions/permission_request.cc
index 3d3ff10..13916710 100644
--- a/components/permissions/permission_request.cc
+++ b/components/permissions/permission_request.cc
@@ -5,7 +5,9 @@
 #include "components/permissions/permission_request.h"
 
 #include <string>
+#include <utility>
 
+#include "base/check.h"
 #include "base/no_destructor.h"
 #include "base/notreached.h"
 #include "build/build_config.h"
@@ -15,6 +17,8 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/elide_url.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/text_elider.h"
+#include "ui/strings/grit/ui_strings.h"
 
 namespace permissions {
 
@@ -56,8 +60,25 @@
 }
 
 #if BUILDFLAG(IS_ANDROID)
-std::u16string PermissionRequest::GetDialogMessageText() const {
+PermissionRequest::AnnotatedMessageText::AnnotatedMessageText(
+    std::u16string text,
+    std::vector<std::pair<size_t, size_t>> bolded_ranges)
+    : text(text), bolded_ranges(bolded_ranges) {}
+
+PermissionRequest::AnnotatedMessageText::~AnnotatedMessageText() = default;
+
+PermissionRequest::AnnotatedMessageText
+PermissionRequest::GetDialogAnnotatedMessageText(
+    const GURL& embedding_origin) const {
   int message_id = 0;
+  std::u16string requesting_origin_string_formatted =
+      url_formatter::FormatUrlForSecurityDisplay(
+          requesting_origin(),
+          url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
+  std::u16string embedding_origin_string_formatted =
+      url_formatter::FormatUrlForSecurityDisplay(
+          embedding_origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
+
   switch (request_type()) {
     case RequestType::kAccessibilityEvents:
       message_id = IDS_ACCESSIBILITY_EVENTS_INFOBAR_TEXT;
@@ -104,8 +125,27 @@
           IDS_PROTECTED_MEDIA_IDENTIFIER_PER_ORIGIN_PROVISIONING_INFOBAR_TEXT;
       break;
     case RequestType::kStorageAccess:
+      // The SA prompt does not currently bold any part of its message.
+      if (base::FeatureList::IsEnabled(
+              permissions::features::kPermissionStorageAccessAPI)) {
+        return AnnotatedMessageText(
+            l10n_util::GetStringFUTF16(
+                IDS_CONCAT_TWO_STRINGS_WITH_PERIODS,
+                l10n_util::GetStringFUTF16(
+                    IDS_STORAGE_ACCESS_PERMISSION_TWO_ORIGIN_PROMPT_TITLE,
+                    requesting_origin_string_formatted),
+                l10n_util::GetStringFUTF16(
+                    IDS_STORAGE_ACCESS_PERMISSION_TWO_ORIGIN_EXPLANATION,
+                    requesting_origin_string_formatted,
+                    embedding_origin_string_formatted)),
+            /*bolded_ranges=*/{});
+      }
+      return AnnotatedMessageText(
+          l10n_util::GetStringFUTF16(IDS_STORAGE_ACCESS_INFOBAR_TEXT,
+                                     requesting_origin_string_formatted,
+                                     embedding_origin_string_formatted),
+          /*bolded_ranges=*/{});
     case RequestType::kTopLevelStorageAccess:
-      // Handled by `PermissionPromptAndroid::GetMessageText` directly.
       NOTREACHED();
       break;
     case RequestType::kVrSession:
@@ -113,10 +153,34 @@
       break;
   }
   DCHECK_NE(0, message_id);
-  return l10n_util::GetStringFUTF16(
-      message_id, url_formatter::FormatUrlForSecurityDisplay(
-                      requesting_origin(),
-                      url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
+
+  // Only format origins bold iff it's one time allowable (which uses a new
+  // prompt design on Clank)
+  return GetDialogAnnotatedMessageText(
+      requesting_origin_string_formatted, message_id, /*format_origin_bold=*/
+      permissions::PermissionUtil::CanPermissionBeAllowedOnce(
+          GetContentSettingsType()));
+}
+
+// static
+PermissionRequest::AnnotatedMessageText
+PermissionRequest::GetDialogAnnotatedMessageText(
+    std::u16string requesting_origin_formatted_for_display,
+    int message_id,
+    bool format_origin_bold) {
+  std::vector<size_t> offsets;
+  std::u16string text = l10n_util::GetStringFUTF16(
+      message_id, {requesting_origin_formatted_for_display}, &offsets);
+
+  std::vector<std::pair<size_t, size_t>> bolded_ranges;
+  if (format_origin_bold) {
+    for (auto offset : offsets) {
+      bolded_ranges.emplace_back(
+          offset, offset + requesting_origin_formatted_for_display.length());
+    }
+  }
+
+  return AnnotatedMessageText(text, bolded_ranges);
 }
 #endif
 
diff --git a/components/permissions/permission_request.h b/components/permissions/permission_request.h
index cb11a9d..31b7605 100644
--- a/components/permissions/permission_request.h
+++ b/components/permissions/permission_request.h
@@ -21,7 +21,6 @@
 
 namespace permissions {
 enum class RequestType;
-
 // Describes the interface a feature making permission requests should
 // implement. A class of this type is registered with the permission request
 // manager to receive updates about the result of the permissions request
@@ -87,8 +86,33 @@
   virtual bool IsDuplicateOf(PermissionRequest* other_request) const;
 
 #if BUILDFLAG(IS_ANDROID)
+  // A message text with formatting information.
+  struct AnnotatedMessageText {
+    // |text| specifies the text string itself.
+    // |bolded_ranges| defines a (potentially empty) list of ranges represented
+    // as pairs of <textOffset, rangeSize>, which shall be used by the UI to
+    // format the specified ranges as bold text.
+    AnnotatedMessageText(std::u16string text,
+                         std::vector<std::pair<size_t, size_t>> bolded_ranges);
+    ~AnnotatedMessageText();
+    AnnotatedMessageText(const AnnotatedMessageText& other) = delete;
+    AnnotatedMessageText& operator=(const AnnotatedMessageText& other) = delete;
+
+    std::u16string text;
+
+    // A list of ranges defined as pairs of <offset, size> which
+    // will be used by Clank to format the ranges in |text| as bold.
+    std::vector<std::pair<size_t, size_t>> bolded_ranges;
+  };
+
+  virtual AnnotatedMessageText GetDialogAnnotatedMessageText(
+      const GURL& embedding_origin) const;
+
   // Returns prompt text appropriate for displaying in an Android dialog.
-  virtual std::u16string GetDialogMessageText() const;
+  static AnnotatedMessageText GetDialogAnnotatedMessageText(
+      std::u16string requesting_origin_formatted_for_display,
+      int message_id,
+      bool format_origin_bold);
 #endif
 
   // Returns a weak pointer to this instance.
diff --git a/components/permissions/test/mock_permission_prompt.cc b/components/permissions/test/mock_permission_prompt.cc
index ca1c14c..94eba738 100644
--- a/components/permissions/test/mock_permission_prompt.cc
+++ b/components/permissions/test/mock_permission_prompt.cc
@@ -62,7 +62,10 @@
 #if BUILDFLAG(IS_ANDROID)
     // For kStorageAccess, the prompt itself calculates the message text.
     if (request_type != permissions::RequestType::kStorageAccess) {
-      EXPECT_FALSE(request->GetDialogMessageText().empty());
+      EXPECT_FALSE(
+          request
+              ->GetDialogAnnotatedMessageText(delegate_->GetRequestingOrigin())
+              .text.empty());
     }
     EXPECT_NE(0, permissions::GetIconId(request_type));
 #else
diff --git a/components/policy/tools/syntax_check_policy_template_json.py b/components/policy/tools/syntax_check_policy_template_json.py
index 1fcc64e..585b7adb 100755
--- a/components/policy/tools/syntax_check_policy_template_json.py
+++ b/components/policy/tools/syntax_check_policy_template_json.py
@@ -978,11 +978,11 @@
         if (not self._SupportedPolicy(policy, current_version)
             and not policy.get('deprecated', False)):
           self._PolicyError(
-              "Marked as no longer supported, but isn't marked as "
-              '"deprecated.\n'
-              '  Unsupported policies must be marked as "deprecated": True. '
-              'You may see this error after branch point. Please fix the'
-              f' issue and cc the policy owners.', policy, 'supported_on')
+              'Marked as no longer supported, but is not marked as '
+              'deprecated.\n'
+              '  Unsupported policies must be marked as `deprecated: true`. '
+              'You may see this error after branch point. Please fix the '
+              'issue and cc the policy owners.', policy, 'supported_on')
 
       supported_platforms = ExpandChromeStar(supported_platforms)
       future_on = ExpandChromeStar(
diff --git a/components/reporting/client/report_queue_impl.cc b/components/reporting/client/report_queue_impl.cc
index cab041a..7d0f759 100644
--- a/components/reporting/client/report_queue_impl.cc
+++ b/components/reporting/client/report_queue_impl.cc
@@ -219,7 +219,10 @@
                      config_->is_event_allowed_cb(), config_->dm_token(),
                      config_->destination(), config_->reserved_space(),
                      config_->source_info(), std::move(record_producer),
-                     std::move(callback)));
+                     // EnqueueCallback must be run on the current thread, we
+                     // need to bind to make sure it's posted to correct thread
+                     // from the ThreadPool.
+                     base::BindPostTaskToCurrentDefault(std::move(callback))));
 }
 
 void ReportQueueImpl::Flush(Priority priority, FlushCallback callback) {
diff --git a/components/search_engine_choice_strings.grdp b/components/search_engine_choice_strings.grdp
index 36775b19..9750d8a 100644
--- a/components/search_engine_choice_strings.grdp
+++ b/components/search_engine_choice_strings.grdp
@@ -78,4 +78,8 @@
   <message name="IDS_SEARCH_ENGINE_CHOICE_MORE_BUTTON" desc="Title of the button to scroll the choice screen when it is too small to show everything at once.">
     More
   </message>
+
+  <message name="IDS_SEARCH_ENGINE_CHOICE_CHEVRON_A11Y_LABEL" desc="Accessibility action to expand the search engine description.">
+    Search engine details
+  </message>
 </grit-part>
diff --git a/components/search_engine_choice_strings_grdp/IDS_SEARCH_ENGINE_CHOICE_CHEVRON_A11Y_LABEL.png.sha1 b/components/search_engine_choice_strings_grdp/IDS_SEARCH_ENGINE_CHOICE_CHEVRON_A11Y_LABEL.png.sha1
new file mode 100644
index 0000000..6ccc738
--- /dev/null
+++ b/components/search_engine_choice_strings_grdp/IDS_SEARCH_ENGINE_CHOICE_CHEVRON_A11Y_LABEL.png.sha1
@@ -0,0 +1 @@
+f3f04d43af5ec953ceeb03a8eaa5d516b4ac95ab
\ No newline at end of file
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index dfe5f00..494fc01f 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -7,6 +7,7 @@
 #include "base/check_op.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
+#include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/functional/callback_helpers.h"
 #include "base/no_destructor.h"
@@ -117,6 +118,7 @@
 #include "storage/browser/quota/quota_manager.h"
 #include "storage/browser/quota/quota_manager_proxy.h"
 #include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/features_generated.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom.h"
 #include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h"
@@ -153,6 +155,7 @@
 #include "third_party/blink/public/mojom/mediasession/media_session.mojom.h"
 #include "third_party/blink/public/mojom/mediastream/media_devices.mojom.h"
 #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
+#include "third_party/blink/public/mojom/model_execution/model_manager.mojom.h"
 #include "third_party/blink/public/mojom/notifications/notification_service.mojom.h"
 #include "third_party/blink/public/mojom/origin_trial_state/origin_trial_state_host.mojom.h"
 #include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
@@ -1120,6 +1123,8 @@
       &EmptyBinderForFrame<blink::mojom::CredentialManager>));
   map->Add<blink::mojom::LCPCriticalPathPredictorHost>(base::BindRepeating(
       &EmptyBinderForFrame<blink::mojom::LCPCriticalPathPredictorHost>));
+  map->Add<blink::mojom::ModelManager>(
+      base::BindRepeating(&EmptyBinderForFrame<blink::mojom::ModelManager>));
   if (base::FeatureList::IsEnabled(blink::features::kBrowsingTopics) &&
       base::FeatureList::IsEnabled(
           blink::features::kBrowsingTopicsDocumentAPI)) {
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index ca2aac5..2bbc46f 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -1948,6 +1948,7 @@
           .SetStatusText(status_text)
           .SetHeaders(BuildResponseHeaders(info.headers.get()))
           .SetMimeType(info.mime_type)
+          .SetCharset(info.charset)
           .SetConnectionReused(info.load_timing.socket_reused)
           .SetConnectionId(info.load_timing.socket_log_id)
           .SetSecurityState(securityState(url, info.cert_status))
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.cc b/content/browser/media/capture/frame_sink_video_capture_device.cc
index 75b46d6..29ef0de 100644
--- a/content/browser/media/capture/frame_sink_video_capture_device.cc
+++ b/content/browser/media/capture/frame_sink_video_capture_device.cc
@@ -186,6 +186,11 @@
     return false;
   }
 
+  // SwiftShader does not support copying directly to NV12.
+  if (gpu_data_manager->GetGPUInfo().UsesSwiftShader()) {
+    return false;
+  }
+
   // We only support NV12 if GL_EXT_texture_rg extension is available. GPU
   // capabilities need to be present in order to determine that.
   if (!gpu_capabilities_) {
diff --git a/content/browser/network/shared_dictionary_browsertest.cc b/content/browser/network/shared_dictionary_browsertest.cc
index e494280b..b9ad858 100644
--- a/content/browser/network/shared_dictionary_browsertest.cc
+++ b/content/browser/network/shared_dictionary_browsertest.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 <tuple>
+
 #include "base/base_paths.h"
 #include "base/files/file_util.h"
 #include "base/metrics/statistics_recorder.h"
@@ -48,6 +50,7 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/test_data_directory.h"
 #include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/shared_dictionary_encoding_names.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/shared_dictionary_access_observer.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -203,13 +206,46 @@
   return true;
 }
 
+std::string ToString(
+    network::features::CompressionDictionaryTransportBackendVersion version) {
+  switch (version) {
+    case network::features::CompressionDictionaryTransportBackendVersion::kV1:
+      return "V1";
+    case network::features::CompressionDictionaryTransportBackendVersion::kV2:
+      return "V2";
+  }
+}
+
 enum class FeatureState {
   kDisabled,
   kBackendOnly,
   kFullyEnabled,
   kFullyEnabledWithZstd
 };
+
+std::string ToString(FeatureState state) {
+  switch (state) {
+    case FeatureState::kDisabled:
+      return "Disabled";
+    case FeatureState::kBackendOnly:
+      return "BackendOnly";
+    case FeatureState::kFullyEnabled:
+      return "FullyEnabled";
+    case FeatureState::kFullyEnabledWithZstd:
+      return "FullyEnabledWithZstd";
+  }
+}
+
 enum class BrowserType { kNormal, kOffTheRecord };
+std::string ToString(BrowserType browser_type) {
+  switch (browser_type) {
+    case BrowserType::kNormal:
+      return "Normal";
+    case BrowserType::kOffTheRecord:
+      return "OffTheRecord";
+  }
+}
+
 enum class FetchType {
   kLinkRelDictionary,
   kLinkRelDictionaryDocumentHeader,
@@ -374,16 +410,29 @@
 }
 
 bool HasSharedDictionaryAcceptEncoding(
-    const net::test_server::HttpRequest::HeaderMap& headers) {
+    const net::test_server::HttpRequest::HeaderMap& headers,
+    network::features::CompressionDictionaryTransportBackendVersion version) {
   auto it = headers.find(net::HttpRequestHeaders::kAcceptEncoding);
   if (it == headers.end()) {
     return false;
   }
-  if (base::FeatureList::IsEnabled(network::features::kSharedZstd)) {
-    return it->second == "sbr, zstd-d" ||
-           base::EndsWith(it->second, ", sbr, zstd-d");
-  } else {
-    return it->second == "sbr" || base::EndsWith(it->second, ", sbr");
+  switch (version) {
+    case network::features::CompressionDictionaryTransportBackendVersion::kV1: {
+      if (base::FeatureList::IsEnabled(network::features::kSharedZstd)) {
+        return it->second == "sbr, zstd-d" ||
+               base::EndsWith(it->second, ", sbr, zstd-d");
+      } else {
+        return it->second == "sbr" || base::EndsWith(it->second, ", sbr");
+      }
+    }
+    case network::features::CompressionDictionaryTransportBackendVersion::kV2: {
+      if (base::FeatureList::IsEnabled(network::features::kSharedZstd)) {
+        return it->second == "br-d, zstd-d" ||
+               base::EndsWith(it->second, ", br-d, zstd-d");
+      } else {
+        return it->second == "br-d" || base::EndsWith(it->second, ", br-d");
+      }
+    }
   }
 }
 
@@ -527,7 +576,10 @@
 
 class SharedDictionaryBrowserTestBase : public ContentBrowserTest {
  public:
-  SharedDictionaryBrowserTestBase() = default;
+  explicit SharedDictionaryBrowserTestBase(
+      const network::features::CompressionDictionaryTransportBackendVersion
+          version)
+      : version_(version) {}
 
   SharedDictionaryBrowserTestBase(const SharedDictionaryBrowserTestBase&) =
       delete;
@@ -719,12 +771,16 @@
         GetSecAvailableDictionary(request.headers);
     if (dict_hash) {
       if (*dict_hash == kExpectedDictionaryHash) {
-        if (HasSharedDictionaryAcceptEncoding(request.headers)) {
+        if (HasSharedDictionaryAcceptEncoding(request.headers, version_)) {
           if (base::FeatureList::IsEnabled(network::features::kSharedZstd)) {
-            response->AddCustomHeader("content-encoding", "zstd-d");
+            response->AddCustomHeader(
+                "content-encoding",
+                network::GetSharedZstdContentEncodingName());
             response->set_content(kZstdCompressedDataString);
           } else {
-            response->AddCustomHeader("content-encoding", "sbr");
+            response->AddCustomHeader(
+                "content-encoding",
+                network::GetSharedBrotliContentEncodingName());
             response->set_content(kBrotliCompressedDataString);
           }
         } else {
@@ -739,6 +795,9 @@
 
     return response;
   }
+
+  const network::features::CompressionDictionaryTransportBackendVersion
+      version_;
 };
 
 // Tests end to end functionality of "compression dictionary transport" feature
@@ -746,10 +805,13 @@
 // TODO(crbug.com/1413922): Remove this when we fully launch this feature.
 class SharedDictionaryFeatureStateBrowserTest
     : public SharedDictionaryBrowserTestBase,
-      public ::testing::WithParamInterface<FeatureState> {
+      public ::testing::WithParamInterface<std::tuple<
+          FeatureState,
+          network::features::CompressionDictionaryTransportBackendVersion>> {
  public:
-  SharedDictionaryFeatureStateBrowserTest() {
-    std::vector<base::test::FeatureRef> enabled_features;
+  SharedDictionaryFeatureStateBrowserTest()
+      : SharedDictionaryBrowserTestBase(GetVersion()) {
+    std::vector<base::test::FeatureRefAndParams> enabled_features;
     std::vector<base::test::FeatureRef> disabled_features;
     switch (GetFeatureState()) {
       case FeatureState::kDisabled:
@@ -760,28 +822,42 @@
         disabled_features.emplace_back(network::features::kSharedZstd);
         break;
       case FeatureState::kBackendOnly:
-        enabled_features.emplace_back(
-            network::features::kCompressionDictionaryTransportBackend);
+        enabled_features.emplace_back(base::test::FeatureRefAndParams(
+            network::features::kCompressionDictionaryTransportBackend,
+            {{network::features::kCompressionDictionaryTransportBackendVersion
+                  .name,
+              network::features::kCompressionDictionaryTransportBackendVersion
+                  .GetName(GetVersion())}}));
         disabled_features.emplace_back(
             network::features::kCompressionDictionaryTransport);
         disabled_features.emplace_back(network::features::kSharedZstd);
         break;
       case FeatureState::kFullyEnabled:
-        enabled_features.emplace_back(
-            network::features::kCompressionDictionaryTransportBackend);
-        enabled_features.emplace_back(
-            network::features::kCompressionDictionaryTransport);
+        enabled_features.emplace_back(base::test::FeatureRefAndParams(
+            network::features::kCompressionDictionaryTransportBackend,
+            {{network::features::kCompressionDictionaryTransportBackendVersion
+                  .name,
+              network::features::kCompressionDictionaryTransportBackendVersion
+                  .GetName(GetVersion())}}));
+        enabled_features.emplace_back(base::test::FeatureRefAndParams(
+            network::features::kCompressionDictionaryTransport, {}));
         disabled_features.emplace_back(network::features::kSharedZstd);
         break;
       case FeatureState::kFullyEnabledWithZstd:
-        enabled_features.emplace_back(
-            network::features::kCompressionDictionaryTransportBackend);
-        enabled_features.emplace_back(
-            network::features::kCompressionDictionaryTransport);
-        enabled_features.emplace_back(network::features::kSharedZstd);
+        enabled_features.emplace_back(base::test::FeatureRefAndParams(
+            network::features::kCompressionDictionaryTransportBackend,
+            {{network::features::kCompressionDictionaryTransportBackendVersion
+                  .name,
+              network::features::kCompressionDictionaryTransportBackendVersion
+                  .GetName(GetVersion())}}));
+        enabled_features.emplace_back(base::test::FeatureRefAndParams(
+            network::features::kCompressionDictionaryTransport, {}));
+        enabled_features.emplace_back(base::test::FeatureRefAndParams(
+            network::features::kSharedZstd, {}));
         break;
     }
-    scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
+    scoped_feature_list_.InitWithFeaturesAndParameters(enabled_features,
+                                                       disabled_features);
   }
   SharedDictionaryFeatureStateBrowserTest(
       const SharedDictionaryFeatureStateBrowserTest&) = delete;
@@ -807,7 +883,11 @@
   void TearDownOnMainThread() override { url_loader_interceptor_.reset(); }
 
  protected:
-  FeatureState GetFeatureState() const { return GetParam(); }
+  FeatureState GetFeatureState() const { return std::get<0>(GetParam()); }
+  network::features::CompressionDictionaryTransportBackendVersion GetVersion()
+      const {
+    return std::get<1>(GetParam());
+  }
   net::EmbeddedTestServer* https_server() { return https_server_.get(); }
 
   bool FeatureIsFullyEnabled() const {
@@ -920,24 +1000,25 @@
   std::optional<URLLoaderInterceptor> url_loader_interceptor_;
 };
 
-INSTANTIATE_TEST_SUITE_P(All,
-                         SharedDictionaryFeatureStateBrowserTest,
-                         testing::Values(FeatureState::kDisabled,
-                                         FeatureState::kBackendOnly,
-                                         FeatureState::kFullyEnabled,
-                                         FeatureState::kFullyEnabledWithZstd),
-                         [](const testing::TestParamInfo<FeatureState>& info) {
-                           switch (info.param) {
-                             case FeatureState::kDisabled:
-                               return "Disabled";
-                             case FeatureState::kBackendOnly:
-                               return "BackendOnly";
-                             case FeatureState::kFullyEnabled:
-                               return "FullyEnabled";
-                             case FeatureState::kFullyEnabledWithZstd:
-                               return "FullyEnabledWithZstd";
-                           }
-                         });
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    SharedDictionaryFeatureStateBrowserTest,
+    ::testing::Combine(
+        testing::Values(FeatureState::kDisabled,
+                        FeatureState::kBackendOnly,
+                        FeatureState::kFullyEnabled,
+                        FeatureState::kFullyEnabledWithZstd),
+        testing::Values(network::features::
+                            CompressionDictionaryTransportBackendVersion::kV1,
+                        network::features::
+                            CompressionDictionaryTransportBackendVersion::kV2)),
+    [](const testing::TestParamInfo<std::tuple<
+           FeatureState,
+           network::features::CompressionDictionaryTransportBackendVersion>>&
+           info) {
+      return ToString(std::get<0>(info.param)) + "_" +
+             ToString(std::get<1>(info.param));
+    });
 
 IN_PROC_BROWSER_TEST_P(SharedDictionaryFeatureStateBrowserTest,
                        LinkRelDictionary) {
@@ -1144,14 +1225,23 @@
 // with fully enabled features.
 class SharedDictionaryBrowserTest
     : public SharedDictionaryBrowserTestBase,
-      public ::testing::WithParamInterface<BrowserType> {
+      public ::testing::WithParamInterface<std::tuple<
+          BrowserType,
+          network::features::CompressionDictionaryTransportBackendVersion>> {
  public:
-  SharedDictionaryBrowserTest() {
-    scoped_feature_list_.InitWithFeatures(
+  SharedDictionaryBrowserTest()
+      : SharedDictionaryBrowserTestBase(GetVersion()) {
+    scoped_feature_list_.InitWithFeaturesAndParameters(
         /*enabled_features=*/
-        {network::features::kCompressionDictionaryTransportBackend,
-         network::features::kCompressionDictionaryTransport,
-         network::features::kSharedZstd},
+        {base::test::FeatureRefAndParams(
+             network::features::kCompressionDictionaryTransportBackend,
+             {{network::features::kCompressionDictionaryTransportBackendVersion
+                   .name,
+               network::features::kCompressionDictionaryTransportBackendVersion
+                   .GetName(GetVersion())}}),
+         base::test::FeatureRefAndParams(
+             network::features::kCompressionDictionaryTransport, {}),
+         base::test::FeatureRefAndParams(network::features::kSharedZstd, {})},
         /*disabled_features=*/{});
   }
   SharedDictionaryBrowserTest(const SharedDictionaryBrowserTest&) = delete;
@@ -1249,7 +1339,11 @@
   }
 
  protected:
-  BrowserType GetBrowserType() const { return GetParam(); }
+  BrowserType GetBrowserType() const { return std::get<0>(GetParam()); }
+  network::features::CompressionDictionaryTransportBackendVersion GetVersion()
+      const {
+    return std::get<1>(GetParam());
+  }
   net::EmbeddedTestServer* cross_origin_server() const {
     return cross_origin_server_.get();
   }
@@ -1365,8 +1459,18 @@
           GetSecAvailableDictionary(request.headers);
       if (dict_hash) {
         if (*dict_hash == kExpectedDictionaryHash) {
-          if (HasSharedDictionaryAcceptEncoding(request.headers)) {
-            response->AddCustomHeader("content-encoding", "sbr");
+          if (HasSharedDictionaryAcceptEncoding(request.headers,
+                                                GetVersion())) {
+            switch (GetVersion()) {
+              case network::features::
+                  CompressionDictionaryTransportBackendVersion::kV1:
+                response->AddCustomHeader("content-encoding", "sbr");
+                break;
+              case network::features::
+                  CompressionDictionaryTransportBackendVersion::kV2:
+                response->AddCustomHeader("content-encoding", "br-d");
+                break;
+            }
             response->set_content(kBrotliCompressedDataString);
           } else {
             response->set_content(kErrorNoSharedDictionaryAcceptEncodingString);
@@ -1390,18 +1494,22 @@
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-INSTANTIATE_TEST_SUITE_P(All,
-                         SharedDictionaryBrowserTest,
-                         testing::Values(BrowserType::kNormal,
-                                         BrowserType::kOffTheRecord),
-                         [](const testing::TestParamInfo<BrowserType>& info) {
-                           switch (info.param) {
-                             case BrowserType::kNormal:
-                               return "Normal";
-                             case BrowserType::kOffTheRecord:
-                               return "OffTheRecord";
-                           }
-                         });
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    SharedDictionaryBrowserTest,
+    ::testing::Combine(
+        testing::Values(BrowserType::kNormal, BrowserType::kOffTheRecord),
+        testing::Values(network::features::
+                            CompressionDictionaryTransportBackendVersion::kV1,
+                        network::features::
+                            CompressionDictionaryTransportBackendVersion::kV2)),
+    [](const testing::TestParamInfo<std::tuple<
+           BrowserType,
+           network::features::CompressionDictionaryTransportBackendVersion>>&
+           info) {
+      return ToString(std::get<0>(info.param)) + "_" +
+             ToString(std::get<1>(info.param));
+    });
 
 IN_PROC_BROWSER_TEST_P(SharedDictionaryBrowserTest,
                        LinkRelDictionarySecureContext) {
diff --git a/content/browser/preloading/prerender/prerender_host_registry.cc b/content/browser/preloading/prerender/prerender_host_registry.cc
index dc1c98d..fbab6ed 100644
--- a/content/browser/preloading/prerender/prerender_host_registry.cc
+++ b/content/browser/preloading/prerender/prerender_host_registry.cc
@@ -1639,6 +1639,11 @@
 
   // Asynchronously delete the prerender host.
   to_be_deleted_hosts_.push_back(std::move(prerender_host));
+
+  // A task has already been scheduled to delete the abandoned hosts.
+  if (to_be_deleted_hosts_.size() > 1) {
+    return;
+  }
   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
       FROM_HERE, base::BindOnce(&PrerenderHostRegistry::DeleteAbandonedHosts,
                                 weak_factory_.GetWeakPtr()));
diff --git a/content/browser/preloading/prerender/prerender_host_registry_unittest.cc b/content/browser/preloading/prerender/prerender_host_registry_unittest.cc
index f884d16..1080a95 100644
--- a/content/browser/preloading/prerender/prerender_host_registry_unittest.cc
+++ b/content/browser/preloading/prerender/prerender_host_registry_unittest.cc
@@ -13,6 +13,7 @@
 #include "content/browser/preloading/prerender/prerender_features.h"
 #include "content/browser/preloading/prerender/prerender_final_status.h"
 #include "content/browser/preloading/prerender/prerender_host.h"
+#include "content/browser/preloading/prerender/prerender_metrics.h"
 #include "content/browser/preloading/speculation_rules/speculation_host_impl.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/browser/site_instance_impl.h"
@@ -1300,6 +1301,41 @@
 
 // End replication state matching tests ------------
 
+TEST_F(PrerenderHostRegistryTest, OneTaskToDeleteAllHosts) {
+  std::vector<int> frame_tree_node_ids;
+  std::vector<std::unique_ptr<test::PrerenderHostObserver>>
+      prerender_host_observers;
+
+  for (int i = 0; i < 2; i++) {
+    const GURL prerendering_url("https://example.com/next" +
+                                base::NumberToString(i));
+    int frame_tree_node_id =
+        registry().CreateAndStartHost(GeneratePrerenderAttributes(
+            prerendering_url, PreloadingTriggerType::kSpeculationRule, "",
+            blink::mojom::SpeculationEagerness::kEager,
+            contents()->GetPrimaryMainFrame()));
+
+    prerender_host_observers.emplace_back(
+        std::make_unique<test::PrerenderHostObserver>(*contents(),
+                                                      frame_tree_node_id));
+    frame_tree_node_ids.push_back(frame_tree_node_id);
+  }
+  int pending_task_before_posting_abandon_task =
+      task_environment()->GetPendingMainThreadTaskCount();
+  registry().CancelHosts(
+      frame_tree_node_ids,
+      PrerenderCancellationReason(PrerenderFinalStatus::kDestroyed));
+  int pending_task_after_posting_abandon_task =
+      task_environment()->GetPendingMainThreadTaskCount();
+  // Only one task was posted.
+  EXPECT_EQ(pending_task_before_posting_abandon_task + 1,
+            pending_task_after_posting_abandon_task);
+  for (auto& observer : prerender_host_observers) {
+    // All PrerenderHosts were deleted, so it should not timeout.
+    observer->WaitForDestroyed();
+  }
+}
+
 TEST_F(PrerenderHostRegistryTest, DisallowPageHavingEffectiveUrl_TriggerUrl) {
   const GURL original_url = contents()->GetLastCommittedURL();
   const GURL kModifiedSiteUrl("custom-scheme://custom");
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 0d2fe83..ba44394 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -248,6 +248,8 @@
 const char kSecSharedStorageWritableRequestHeaderKey[] =
     "Sec-Shared-Storage-Writable";
 
+constexpr char kNavigationRequestScope[] = "NavigationRequestScope";
+
 // Denotes the type of user agent string value sent in the User-Agent request
 // header.
 //
@@ -1606,6 +1608,10 @@
               : std::nullopt),
       embedder_shared_storage_context_(embedder_shared_storage_context),
       has_ad_auction_headers_attribute_(frame_tree_node->ad_auction_headers()) {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::NavigationRequest",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_OUT);
   CHECK(!common_params_->initiator_base_url ||
         !common_params_->initiator_base_url->is_empty());
   DCHECK(!blink::IsRendererDebugURL(common_params_->url));
@@ -2029,6 +2035,10 @@
 }
 
 NavigationRequest::~NavigationRequest() {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::~NavigationRequest",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN);
 #if DCHECK_IS_ON()
   // If |is_safe_to_delete_| is false, it means |this| is being deleted at an
   // unexpected time, more specifically a time that is likely to lead to
@@ -2184,6 +2194,10 @@
 }
 
 void NavigationRequest::BeginNavigation() {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::BeginNavigation",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   EnterChildTraceEvent("BeginNavigation", this);
   DCHECK(!loader_);
   DCHECK(!HasRenderFrameHost());
@@ -2323,6 +2337,11 @@
 void NavigationRequest::OnPrerenderingActivationChecksComplete(
     CommitDeferringCondition::NavigationType navigation_type,
     std::optional<int> candidate_prerender_frame_tree_node_id) {
+  TRACE_EVENT_WITH_FLOW0(
+      "navigation", "NavigationRequest::OnPrerenderingActivationChecksComplete",
+      TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                          TRACE_ID_LOCAL(navigation_id_)),
+      TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   // Prerendered page activation must run CommitDeferringConditions before
   // StartRequest().
   DCHECK_LT(state_, WILL_START_NAVIGATION);
@@ -2401,6 +2420,11 @@
 
 void NavigationRequest::OnFencedFrameURLMappingComplete(
     const std::optional<FencedFrameProperties>& properties) {
+  TRACE_EVENT_WITH_FLOW0("navigation",
+                         "NavigationRequest::OnFencedFrameURLMappingComplete",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   is_deferred_on_fenced_frame_url_mapping_ = false;
 
   // The URL mapping might have failed (e.g. because the urn is invalid):
@@ -2468,6 +2492,10 @@
 }
 
 void NavigationRequest::BeginNavigationImpl() {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::BeginNavigationImpl",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   base::ElapsedTimer timer;
   SetState(WILL_START_NAVIGATION);
 #if BUILDFLAG(IS_ANDROID)
@@ -2748,6 +2776,10 @@
 }
 
 void NavigationRequest::StartNavigation() {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::StartNavigation",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   DCHECK(frame_tree_node_->navigation_request() == this ||
          is_synchronous_renderer_commit_);
   FrameTreeNode* frame_tree_node = frame_tree_node_;
@@ -3110,6 +3142,10 @@
     const net::RedirectInfo& redirect_info,
     const net::NetworkAnonymizationKey& network_anonymization_key,
     network::mojom::URLResponseHeadPtr response_head) {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::OnRequestRedirected",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   ScopedCrashKeys crash_keys(*this);
 
   // Sanity check - this can only be set at commit time.
@@ -4031,6 +4067,10 @@
     net::NetworkAnonymizationKey network_anonymization_key,
     std::optional<SubresourceLoaderParams> subresource_loader_params,
     EarlyHints early_hints) {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::OnResponseStarted",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   ScopedCrashKeys crash_keys(*this);
 
   // The |loader_|'s job is finished. It must not call the NavigationRequest
@@ -4290,6 +4330,11 @@
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
     bool is_download,
     std::optional<SubresourceLoaderParams> subresource_loader_params) {
+  TRACE_EVENT_WITH_FLOW0(
+      "navigation", "NavigationRequest::SelectFrameHostForOnResponseStarted",
+      TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                          TRACE_ID_LOCAL(navigation_id_)),
+      TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   CHECK(!HasRenderFrameHost())
       << "`render_frame_host_` should not be set before the "
          "`NavigationRequest` starts to select the RFH.";
@@ -4587,6 +4632,12 @@
 std::optional<NavigationEarlyHintsManagerParams>
 NavigationRequest::CreateNavigationEarlyHintsManagerParams(
     const network::mojom::EarlyHints& early_hints) {
+  TRACE_EVENT_WITH_FLOW0(
+      "navigation",
+      "NavigationRequest::CreateNavigationEarlyHintsManagerParams",
+      TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                          TRACE_ID_LOCAL(navigation_id_)),
+      TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   // Early Hints preloads should happen only before the final response is
   // received, and limited only in the main frame for now.
   CHECK(!HasRenderFrameHost());
@@ -4668,6 +4719,11 @@
     bool skip_throttles,
     const std::optional<std::string>& error_page_content,
     bool collapse_frame) {
+  TRACE_EVENT_WITH_FLOW0("navigation",
+                         "NavigationRequest::OnRequestFailedInternal",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   CheckStateTransition(WILL_FAIL_REQUEST);
   DCHECK(!(status.error_code == net::ERR_ABORTED &&
            error_page_content.has_value()));
@@ -4879,6 +4935,11 @@
 
 void NavigationRequest::OnStartChecksComplete(
     NavigationThrottle::ThrottleCheckResult result) {
+  TRACE_EVENT_WITH_FLOW0("navigation",
+                         "NavigationRequest::OnStartChecksComplete",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   DCHECK(result.action() != NavigationThrottle::DEFER);
   DCHECK(result.action() != NavigationThrottle::BLOCK_RESPONSE);
 
@@ -5151,6 +5212,11 @@
 
 void NavigationRequest::OnRedirectChecksComplete(
     NavigationThrottle::ThrottleCheckResult result) {
+  TRACE_EVENT_WITH_FLOW0("navigation",
+                         "NavigationRequest::OnRedirectChecksComplete",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   DCHECK(result.action() != NavigationThrottle::DEFER);
   DCHECK(result.action() != NavigationThrottle::BLOCK_RESPONSE);
   DCHECK(!IsPageActivation());
@@ -5340,6 +5406,11 @@
 
 void NavigationRequest::OnFailureChecksComplete(
     NavigationThrottle::ThrottleCheckResult result) {
+  TRACE_EVENT_WITH_FLOW0("navigation",
+                         "NavigationRequest::OnFailureChecksComplete",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   // This method is called as a result of getting to the end of
   // OnRequestFailedInternal(), which calls WillFailRequest(), which
   // runs the throttles, which eventually call back to this method.
@@ -5658,6 +5729,10 @@
 }
 
 void NavigationRequest::CommitNavigation() {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::CommitNavigation",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   // A navigation request should only commit once the response has been
   // processed.
   DCHECK_GE(state_, WILL_PROCESS_RESPONSE);
@@ -5909,6 +5984,11 @@
 }
 
 void NavigationRequest::CommitPageActivation() {
+  TRACE_EVENT_WITH_FLOW0("navigation",
+                         "NavigationRequest::CommitPageActivation",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   // An activation is either for the back-forward cache or prerendering. They
   // are mutually exclusive.
   DCHECK_NE(IsServedFromBackForwardCache(), IsPrerenderedPageActivation());
@@ -6947,6 +7027,10 @@
 }
 
 void NavigationRequest::WillStartRequest() {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::WillStartRequest",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   EnterChildTraceEvent("WillStartRequest", this);
   DCHECK_EQ(state_, WILL_START_REQUEST);
   will_start_request_time_ = base::TimeTicks::Now();
@@ -6989,6 +7073,10 @@
 void NavigationRequest::WillRedirectRequest(
     const GURL& new_referrer_url,
     RenderProcessHost* post_redirect_process) {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::WillRedirectRequest",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   EnterChildTraceEvent("WillRedirectRequest", this, "url",
                        common_params_->url.possibly_invalid_spec());
   UpdateStateFollowingRedirect(new_referrer_url);
@@ -7029,6 +7117,10 @@
 }
 
 void NavigationRequest::WillProcessResponse() {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::WillProcessResponse",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   EnterChildTraceEvent("WillProcessResponse", this);
   DCHECK_EQ(state_, WILL_PROCESS_RESPONSE);
 
@@ -7050,6 +7142,11 @@
 }
 
 void NavigationRequest::WillCommitWithoutUrlLoader() {
+  TRACE_EVENT_WITH_FLOW0("navigation",
+                         "NavigationRequest::WillCommitWithoutUrlLoader",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   EnterChildTraceEvent("WillCommitWithoutUrlLoader", this);
 
   throttle_runner_->RegisterNavigationThrottlesForCommitWithoutUrlLoader();
@@ -7101,6 +7198,10 @@
     bool navigation_entry_committed,
     bool did_replace_entry,
     const GURL& previous_main_frame_url) {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::DidCommitNavigation",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   common_params_->url = params.url;
   did_replace_entry_ = did_replace_entry;
   should_update_history_ = params.should_update_history;
@@ -7377,6 +7478,11 @@
 }
 
 void NavigationRequest::ReadyToCommitNavigation(bool is_error) {
+  TRACE_EVENT_WITH_FLOW0("navigation",
+                         "NavigationRequest::ReadyToCommitNavigation",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   EnterChildTraceEvent("ReadyToCommitNavigation", this);
 
   // We may come back to here asynchronously, and the renderer may be destroyed
@@ -8952,6 +9058,10 @@
 
 void NavigationRequest::OnCookiesAccessed(
     std::vector<network::mojom::CookieAccessDetailsPtr> details_vector) {
+  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationRequest::OnCookiesAccessed",
+                         TRACE_ID_WITH_SCOPE(kNavigationRequestScope,
+                                             TRACE_ID_LOCAL(navigation_id_)),
+                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
   for (auto& details : details_vector) {
     // TODO(721329): We should not send information to the current frame about
     // (potentially unrelated) ongoing navigation, but at the moment we don't
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index aac4683..24a65fb 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -505,6 +505,15 @@
     return;
   }
 
+  warm_up_on_stopped_ = false;
+  if (status_ == blink::EmbeddedWorkerStatus::kRunning && context_ &&
+      base::FeatureList::IsEnabled(
+          blink::features::kSpeculativeServiceWorkerWarmUp) &&
+      blink::features::kSpeculativeServiceWorkerWarmUpOnStopped.Get() &&
+      owner_version_->scope().SchemeIsHTTPOrHTTPS()) {
+    warm_up_on_stopped_ = true;
+  }
+
   client_->StopWorker();
   status_ = blink::EmbeddedWorkerStatus::kStopping;
   for (auto& observer : listener_list_)
@@ -730,6 +739,23 @@
 }
 
 void EmbeddedWorkerInstance::OnStopped() {
+  if (warm_up_on_stopped_) {
+    // We need to wait for the complete stop before warming up the service
+    // worker otherwise WarmUpServiceWorker() keeps the service worker running.
+    // Also, we need to post a task before ReleaseProcess(). Hence we are
+    // posting a task here.
+    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            [](base::WeakPtr<ServiceWorkerContextCore> context,
+               const GURL scope, const blink::StorageKey key) {
+              if (context) {
+                context->wrapper()->WarmUpServiceWorker(scope, key,
+                                                        base::DoNothing());
+              }
+            },
+            context_, owner_version_->scope(), owner_version_->key()));
+  }
   blink::EmbeddedWorkerStatus old_status = status_;
   ReleaseProcess();
   for (auto& observer : listener_list_)
@@ -1026,6 +1052,7 @@
   // re-added at this stage.
   status_ = blink::EmbeddedWorkerStatus::kStopping;
   pause_initializing_global_scope_ = false;
+  warm_up_on_stopped_ = false;
   NotifyForegroundServiceWorkerRemoved();
 
   instance_host_receiver_.reset();
diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h
index bd778cf..0827c26 100644
--- a/content/browser/service_worker/embedded_worker_instance.h
+++ b/content/browser/service_worker/embedded_worker_instance.h
@@ -354,6 +354,10 @@
   // (https://crbug.com/1431792).
   bool pause_initializing_global_scope_ = false;
 
+  // If true, warms up service worker after service worker is stopped.
+  // (https://crbug.com/1431792).
+  bool warm_up_on_stopped_ = false;
+
   // Current running information.
   std::unique_ptr<EmbeddedWorkerInstance::WorkerProcessHandle> process_handle_;
   int thread_id_;
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index dda40934..c76729ea 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -4684,6 +4684,58 @@
   }
 }
 
+class ServiceWorkerWarmUpBrowserOnStoppedTest
+    : public ServiceWorkerWarmUpBrowserTestBase {
+ public:
+  ServiceWorkerWarmUpBrowserOnStoppedTest() {
+    feature_list_.InitWithFeaturesAndParameters(
+        {{blink::features::kSpeculativeServiceWorkerWarmUp,
+          {{blink::features::kSpeculativeServiceWorkerWarmUpOnStopped.name,
+            "true"}}}},
+        {features::kSpeculativeServiceWorkerStartup});
+  }
+  ~ServiceWorkerWarmUpBrowserOnStoppedTest() override = default;
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerWarmUpBrowserOnStoppedTest,
+                       WarmUpOnStopped) {
+  base::HistogramTester histogram_tester;
+  const GURL create_service_worker_url(embedded_test_server()->GetURL(
+      "/service_worker/create_service_worker.html"));
+  const GURL out_scope_url(embedded_test_server()->GetURL("/empty.html"));
+  const GURL in_scope_url(
+      embedded_test_server()->GetURL("/service_worker/empty.html"));
+
+  // Register a service worker.
+  WorkerRunningStatusObserver observer1(public_context());
+  EXPECT_TRUE(NavigateToURL(shell(), create_service_worker_url));
+  EXPECT_EQ("DONE", EvalJs(shell()->web_contents()->GetPrimaryMainFrame(),
+                           "register('fetch_event_respond_with_fetch.js');"));
+  observer1.WaitUntilRunning();
+
+  scoped_refptr<ServiceWorkerVersion> version =
+      wrapper()->GetLiveVersion(observer1.version_id());
+  EXPECT_EQ(blink::EmbeddedWorkerStatus::kRunning, version->running_status());
+  EXPECT_EQ(1, version->embedded_worker()->restart_count());
+
+  // Stop the current running service worker.
+  StopServiceWorker(version.get());
+  EXPECT_EQ(blink::EmbeddedWorkerStatus::kStopped, version->running_status());
+
+  // Automatically warm-up service worker.
+  base::RunLoop run_loop;
+  while (!version->IsWarmedUp()) {
+    run_loop.RunUntilIdle();
+  }
+  EXPECT_EQ(blink::EmbeddedWorkerStatus::kStarting, version->running_status());
+  EXPECT_EQ(EmbeddedWorkerInstance::StartingPhase::SCRIPT_LOADED,
+            version->embedded_worker()->starting_phase());
+  EXPECT_TRUE(version->embedded_worker()->pause_initializing_global_scope());
+}
+
 // Pointer triggered ServiceWorkerWarmUp is not currently available on Android.
 #if !BUILDFLAG(IS_ANDROID)
 
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc
index 86978cf..c0ece46d 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -934,6 +934,12 @@
     return;
   }
 
+  // Only warm-up http or https URLs. Do not warm-up extensions and others.
+  if (!document_url.SchemeIsHTTPOrHTTPS()) {
+    std::move(callback).Run();
+    return;
+  }
+
   context_core_->AddWarmUpRequest(document_url, key, std::move(callback));
 
   // If a service worker warm-up process is already running, do not call
diff --git a/content/browser/webid/webid_browsertest.cc b/content/browser/webid/webid_browsertest.cc
index 513f9b6..965e4780 100644
--- a/content/browser/webid/webid_browsertest.cc
+++ b/content/browser/webid/webid_browsertest.cc
@@ -719,6 +719,104 @@
   EXPECT_FALSE(*value);
 }
 
+// Verify that IDP sign-in/out headers work in fetch from worker.
+IN_PROC_BROWSER_TEST_F(WebIdIdpSigninStatusBrowserTest,
+                       IdpSigninAndOutFetchFromWorker) {
+  static constexpr char script[] = R"(
+    (async () => {
+      const script =
+        '(async () => { return (await fetch("/header/sign%s")).status; })()'
+      return new Promise(resolve => {
+        const channel = new MessageChannel();
+        channel.port1.addEventListener('message', (e) => {
+          resolve(e.data);
+        });
+        channel.port1.start();
+        const worker = new Worker('/fedcm/eval_worker.js');
+        worker.postMessage(
+          {
+            nested: false,
+            script: script,
+          },
+          [channel.port2]
+        );
+      });
+    }) ();
+  )";
+
+  GURL url_for_origin = https_server().GetURL(kRpHostName, "/header/");
+  url::Origin origin = url::Origin::Create(url_for_origin);
+  EXPECT_FALSE(sharing_context()->GetIdpSigninStatus(origin).has_value());
+  {
+    base::RunLoop run_loop;
+    sharing_context()->SetIdpStatusClosureForTesting(run_loop.QuitClosure());
+    EXPECT_EQ(200, EvalJs(shell(), base::StringPrintf(script, "in")));
+    run_loop.Run();
+  }
+  auto value = sharing_context()->GetIdpSigninStatus(origin);
+  ASSERT_TRUE(value.has_value());
+  EXPECT_TRUE(*value);
+
+  {
+    base::RunLoop run_loop;
+    sharing_context()->SetIdpStatusClosureForTesting(run_loop.QuitClosure());
+    EXPECT_EQ(200, EvalJs(shell(), base::StringPrintf(script, "out")));
+    run_loop.Run();
+  }
+  value = sharing_context()->GetIdpSigninStatus(origin);
+  ASSERT_TRUE(value.has_value());
+  EXPECT_FALSE(*value);
+}
+
+// Verify that IDP sign-in/out headers work in fetch from nested worker.
+IN_PROC_BROWSER_TEST_F(WebIdIdpSigninStatusBrowserTest,
+                       IdpSigninAndOutFetchFromNestedWorker) {
+  static constexpr char script[] = R"(
+    (async () => {
+      const script =
+        '(async () => { return (await fetch("/header/sign%s")).status; })()'
+      return new Promise(resolve => {
+        const channel = new MessageChannel();
+        channel.port1.addEventListener('message', (e) => {
+          resolve(e.data);
+        });
+        channel.port1.start();
+        const worker = new Worker('/fedcm/eval_worker.js');
+        worker.postMessage(
+          {
+            nested: true,
+            script: script,
+          },
+          [channel.port2]
+        );
+      });
+    }) ();
+  )";
+
+  GURL url_for_origin = https_server().GetURL(kRpHostName, "/header/");
+  url::Origin origin = url::Origin::Create(url_for_origin);
+  EXPECT_FALSE(sharing_context()->GetIdpSigninStatus(origin).has_value());
+  {
+    base::RunLoop run_loop;
+    sharing_context()->SetIdpStatusClosureForTesting(run_loop.QuitClosure());
+    EXPECT_EQ(200, EvalJs(shell(), base::StringPrintf(script, "in")));
+    run_loop.Run();
+  }
+  auto value = sharing_context()->GetIdpSigninStatus(origin);
+  ASSERT_TRUE(value.has_value());
+  EXPECT_TRUE(*value);
+
+  {
+    base::RunLoop run_loop;
+    sharing_context()->SetIdpStatusClosureForTesting(run_loop.QuitClosure());
+    EXPECT_EQ(200, EvalJs(shell(), base::StringPrintf(script, "out")));
+    run_loop.Run();
+  }
+  value = sharing_context()->GetIdpSigninStatus(origin);
+  ASSERT_TRUE(value.has_value());
+  EXPECT_FALSE(*value);
+}
+
 // Verify that an IdP can call close to close modal dialog views.
 IN_PROC_BROWSER_TEST_F(WebIdIdpSigninStatusBrowserTest, IdPClose) {
   GURL configURL = GURL(BaseIdpUrl());
diff --git a/content/public/test/prerender_test_util.cc b/content/public/test/prerender_test_util.cc
index eecba90..8880b3b 100644
--- a/content/public/test/prerender_test_util.cc
+++ b/content/public/test/prerender_test_util.cc
@@ -554,15 +554,9 @@
       content::TestNavigationObserver::WaitEvent::kLoadStopped);
   // Ignore the result of ExecJs().
   //
-  // Depending on timing, activation could destroy the current WebContents
-  // before ExecJs() gets a result from the frame that executed scripts. This
-  // results in execution failure even when the execution succeeded. See
-  // https://crbug.com/1156141 for details.
-  //
-  // This part will drastically be modified by the MPArch, so we take the
-  // approach just to ignore it instead of fixing the timing issue. When
-  // ExecJs() actually fails, the remaining test steps should fail, so it
-  // should be safe to ignore it.
+  // Depending on timing, activation could destroy a navigating frame before
+  // ExecJs() gets a result from the frame. This results in execution failure
+  // even when the navigation succeeded.
   std::ignore = ExecJs(web_contents.GetPrimaryMainFrame(),
                        JsReplace("location = $1", gurl));
   observer.Wait();
diff --git a/content/public/test/prerender_test_util.h b/content/public/test/prerender_test_util.h
index 80708fa..87389e6c 100644
--- a/content/public/test/prerender_test_util.h
+++ b/content/public/test/prerender_test_util.h
@@ -181,13 +181,9 @@
   // Navigates the primary page to the URL and waits until the completion of
   // the navigation.
   //
-  // Navigations that could activate a prerendered page on the multiple
-  // WebContents architecture (not multiple-pages architecture known as
-  // MPArch) should use this function instead of the NavigateToURL() test
-  // helper. This is because the test helper accesses the predecessor
-  // WebContents to be destroyed during activation and results in crashes.
-  // See https://crbug.com/1154501 for the MPArch migration.
-  // TODO(crbug.com/1198960): remove this once the migration is complete.
+  // Navigations that could activate a prerendered page should use this function
+  // instead of the NavigateToURL() test helper. This is because the test helper
+  // could access a navigating frame being destroyed during activation and fail.
   static void NavigatePrimaryPage(WebContents& web_contents, const GURL& gurl);
   void NavigatePrimaryPage(const GURL& gurl);
 
diff --git a/content/renderer/background_resource_fetch_assets.cc b/content/renderer/background_resource_fetch_assets.cc
index 2b0638d..6b0e6ff 100644
--- a/content/renderer/background_resource_fetch_assets.cc
+++ b/content/renderer/background_resource_fetch_assets.cc
@@ -14,9 +14,13 @@
 BackgroundResourceFetchAssets::BackgroundResourceFetchAssets(
     std::unique_ptr<network::PendingSharedURLLoaderFactory>
         pending_loader_factory,
-    scoped_refptr<base::SequencedTaskRunner> background_task_runner)
+    std::unique_ptr<blink::URLLoaderThrottleProvider> throttle_provider,
+    scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+    const blink::LocalFrameToken& local_frame_token)
     : pending_loader_factory_(std::move(pending_loader_factory)),
-      background_task_runner_(std::move(background_task_runner)) {}
+      throttle_provider_(std::move(throttle_provider)),
+      background_task_runner_(std::move(background_task_runner)),
+      local_frame_token_(local_frame_token) {}
 
 const scoped_refptr<base::SequencedTaskRunner>&
 BackgroundResourceFetchAssets::GetTaskRunner() {
@@ -35,8 +39,19 @@
   return loader_factory_;
 }
 
+blink::URLLoaderThrottleProvider*
+BackgroundResourceFetchAssets::GetThrottleProvider() {
+  return throttle_provider_.get();
+}
+
+const blink::LocalFrameToken&
+BackgroundResourceFetchAssets::GetLocalFrameToken() {
+  return local_frame_token_;
+}
+
 BackgroundResourceFetchAssets::~BackgroundResourceFetchAssets() {
   background_task_runner_->ReleaseSoon(FROM_HERE, std::move(loader_factory_));
+  background_task_runner_->DeleteSoon(FROM_HERE, std::move(throttle_provider_));
 }
 
 }  // namespace content
diff --git a/content/renderer/background_resource_fetch_assets.h b/content/renderer/background_resource_fetch_assets.h
index 73dff43..096389b1d 100644
--- a/content/renderer/background_resource_fetch_assets.h
+++ b/content/renderer/background_resource_fetch_assets.h
@@ -5,8 +5,9 @@
 #ifndef CONTENT_RENDERER_BACKGROUND_RESOURCE_FETCH_ASSETS_H_
 #define CONTENT_RENDERER_BACKGROUND_RESOURCE_FETCH_ASSETS_H_
 
-#include "third_party/blink/public/platform/web_background_resource_fetch_assets.h"
+#include <memory>
 
+#include "third_party/blink/public/platform/web_background_resource_fetch_assets.h"
 namespace network {
 class PendingSharedURLLoaderFactory;
 }  // namespace network
@@ -20,7 +21,9 @@
   BackgroundResourceFetchAssets(
       std::unique_ptr<network::PendingSharedURLLoaderFactory>
           pending_loader_factory,
-      scoped_refptr<base::SequencedTaskRunner> background_task_runner);
+      std::unique_ptr<blink::URLLoaderThrottleProvider> throttle_provider,
+      scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+      const blink::LocalFrameToken& local_frame_token);
 
   BackgroundResourceFetchAssets(const BackgroundResourceFetchAssets&) = delete;
   BackgroundResourceFetchAssets& operator=(
@@ -28,6 +31,8 @@
 
   const scoped_refptr<base::SequencedTaskRunner>& GetTaskRunner() override;
   scoped_refptr<network::SharedURLLoaderFactory> GetLoaderFactory() override;
+  blink::URLLoaderThrottleProvider* GetThrottleProvider() override;
+  const blink::LocalFrameToken& GetLocalFrameToken() override;
 
  private:
   ~BackgroundResourceFetchAssets() override;
@@ -37,7 +42,11 @@
 
   scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
 
+  std::unique_ptr<blink::URLLoaderThrottleProvider> throttle_provider_;
+
   scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
+
+  const blink::LocalFrameToken local_frame_token_;
 };
 
 }  // namespace content
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index d876494..c0e3277 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -6237,7 +6237,11 @@
     background_resource_fetch_context_ =
         base::MakeRefCounted<BackgroundResourceFetchAssets>(
             GetLoaderFactoryBundle()->Clone(),
-            background_resource_fetch_task_runner_);
+            GetURLLoaderThrottleProvider()
+                ? GetURLLoaderThrottleProvider()->Clone()
+                : nullptr,
+            background_resource_fetch_task_runner_,
+            frame_->GetLocalFrameToken());
   }
   return background_resource_fetch_context_;
 }
diff --git a/content/shell/renderer/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc
index 9d29678..4c661522 100644
--- a/content/shell/renderer/shell_content_renderer_client.cc
+++ b/content/shell/renderer/shell_content_renderer_client.cc
@@ -12,7 +12,9 @@
 #include "base/functional/bind.h"
 #include "base/notreached.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/task/sequenced_task_runner.h"
 #include "base/task/single_thread_task_runner.h"
+#include "base/types/pass_key.h"
 #include "components/cdm/renderer/external_clear_key_key_system_info.h"
 #include "components/network_hints/renderer/web_prescient_networking_impl.h"
 #include "components/web_cache/renderer/web_cache_impl.h"
@@ -150,25 +152,48 @@
 class ShellContentRendererUrlLoaderThrottleProvider
     : public blink::URLLoaderThrottleProvider {
  public:
+  ShellContentRendererUrlLoaderThrottleProvider()
+      : main_thread_task_runner_(
+            content::RenderThread::IsMainThread()
+                ? base::SequencedTaskRunner::GetCurrentDefault()
+                : nullptr) {}
+
+  // This constructor works in conjunction with Clone().
+  ShellContentRendererUrlLoaderThrottleProvider(
+      const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner,
+      base::PassKey<ShellContentRendererUrlLoaderThrottleProvider>)
+      : main_thread_task_runner_(std::move(main_thread_task_runner)) {}
+
   std::unique_ptr<URLLoaderThrottleProvider> Clone() override {
-    return std::make_unique<ShellContentRendererUrlLoaderThrottleProvider>();
+    return std::make_unique<ShellContentRendererUrlLoaderThrottleProvider>(
+        main_thread_task_runner_,
+        base::PassKey<ShellContentRendererUrlLoaderThrottleProvider>());
   }
 
   blink::WebVector<std::unique_ptr<blink::URLLoaderThrottle>> CreateThrottles(
       base::optional_ref<const blink::LocalFrameToken> local_frame_token,
       const network::ResourceRequest& request) override {
     blink::WebVector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
-    // Workers can call us on a background thread. We don't care about such
-    // requests because we purposefully only look at resources from frames
-    // that the user can interact with.`
-    blink::WebLocalFrame* frame = nullptr;
-    if (content::RenderThread::IsMainThread() &&
-        local_frame_token.has_value()) {
-      frame = blink::WebLocalFrame::FromFrameToken(local_frame_token.value());
-    }
-    if (frame) {
-      auto throttle = content::MaybeCreateIdentityUrlLoaderThrottle(
-          base::BindRepeating(blink::SetIdpSigninStatus, frame));
+    if (local_frame_token.has_value()) {
+      auto throttle =
+          content::MaybeCreateIdentityUrlLoaderThrottle(base::BindRepeating(
+              [](const blink::LocalFrameToken& local_frame_token,
+                 const scoped_refptr<base::SequencedTaskRunner>
+                     main_thread_task_runner,
+                 const url::Origin& origin,
+                 blink::mojom::IdpSigninStatus status) {
+                if (content::RenderThread::IsMainThread()) {
+                  blink::SetIdpSigninStatus(local_frame_token, origin, status);
+                  return;
+                }
+                if (main_thread_task_runner) {
+                  main_thread_task_runner->PostTask(
+                      FROM_HERE,
+                      base::BindOnce(&blink::SetIdpSigninStatus,
+                                     local_frame_token, origin, status));
+                }
+              },
+              local_frame_token.value(), main_thread_task_runner_));
       if (throttle)
         throttles.push_back(std::move(throttle));
     }
@@ -177,6 +202,11 @@
   }
 
   void SetOnline(bool is_online) override {}
+
+ private:
+  // Set only when `this` was created on the main thread, or cloned from a
+  // provider which was created on the main thread.
+  scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_;
 };
 
 void CreateRendererTestService(
diff --git a/content/test/content_test_bundle_data.filelist b/content/test/content_test_bundle_data.filelist
index d555851e..251df18 100644
--- a/content/test/content_test_bundle_data.filelist
+++ b/content/test/content_test_bundle_data.filelist
@@ -5959,6 +5959,7 @@
 data/event-latency-animation.html
 data/fedcm/accounts_endpoint.json
 data/fedcm/client_metadata_endpoint.json
+data/fedcm/eval_worker.js
 data/fedcm/id_assertion_endpoint.json
 data/fenced_frames/ad_that_leaves_interest_group.html
 data/fenced_frames/ad_that_leaves_interest_group.html.mock-http-headers
diff --git a/content/test/data/fedcm/eval_worker.js b/content/test/data/fedcm/eval_worker.js
new file mode 100644
index 0000000..1b456c5
--- /dev/null
+++ b/content/test/data/fedcm/eval_worker.js
@@ -0,0 +1,18 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+self.addEventListener('message', async (e) => {
+  if (!e.data.nested) {
+    e.ports[0].postMessage(await eval(e.data.script));
+    return;
+  }
+  const worker = new Worker('./eval_worker.js');
+  worker.postMessage(
+    {
+      nested: false,
+      script: e.data.script,
+    },
+    [e.ports[0]]
+  );
+});
diff --git a/device/vr/openxr/windows/openxr_graphics_binding_d3d11.cc b/device/vr/openxr/windows/openxr_graphics_binding_d3d11.cc
index f08c819..79d9216 100644
--- a/device/vr/openxr/windows/openxr_graphics_binding_d3d11.cc
+++ b/device/vr/openxr/windows/openxr_graphics_binding_d3d11.cc
@@ -181,6 +181,10 @@
     // cause errors in rendering.
     gfx::Size buffer_size =
         gfx::Size(texture2d_desc.Width, texture2d_desc.Height);
+
+    // The SharedImages created here will eventually be transferred to other
+    // processes to have their contents written by WebGL and read via GL by
+    // OpenXR.
     const uint32_t shared_image_usage = gpu::SHARED_IMAGE_USAGE_SCANOUT |
                                         gpu::SHARED_IMAGE_USAGE_DISPLAY_READ |
                                         gpu::SHARED_IMAGE_USAGE_GLES2_READ |
diff --git a/docs/experiments/compression-dictionary-transport.md b/docs/experiments/compression-dictionary-transport.md
index 6384d7e..5724dd66 100644
--- a/docs/experiments/compression-dictionary-transport.md
+++ b/docs/experiments/compression-dictionary-transport.md
@@ -199,7 +199,7 @@
 construction to catch up the following spec changes:
 
 - Change Content-Encoding name "br-d" "zstd-d"
-  - Stauts: Not yet implemented.
+  - Stauts: Implemented by https://crrev.com/c/5185977.
 - Changed match to use URLPattern
   - Stauts: Not yet implemented.
 - Added support for a server-provided dictionary id
diff --git a/docs/website b/docs/website
index d887829..2c6ad70 160000
--- a/docs/website
+++ b/docs/website
@@ -1 +1 @@
-Subproject commit d8878295ced9193396fc47c4c67d9569c6240234
+Subproject commit 2c6ad70aba273dc83f20250b635c11ac9770caaf
diff --git a/infra/config/generated/builders/gn_args_locations.json b/infra/config/generated/builders/gn_args_locations.json
index 7cc70ba..16a3b0b 100644
--- a/infra/config/generated/builders/gn_args_locations.json
+++ b/infra/config/generated/builders/gn_args_locations.json
@@ -335,22 +335,16 @@
   "chromium.goma": {
     "Chromium Linux Goma RBE Staging": "goma/Chromium Linux Goma RBE Staging/gn-args.json",
     "Chromium Linux Goma RBE Staging (dbg)": "goma/Chromium Linux Goma RBE Staging (dbg)/gn-args.json",
-    "Chromium Mac Goma RBE Staging": "goma/Chromium Mac Goma RBE Staging/gn-args.json",
-    "Chromium Mac Goma RBE Staging (dbg)": "goma/Chromium Mac Goma RBE Staging (dbg)/gn-args.json",
     "Chromium Win Goma RBE Staging": "goma/Chromium Win Goma RBE Staging/gn-args.json",
     "chromeos-amd64-generic-rel-goma-rbe-staging": "goma/chromeos-amd64-generic-rel-goma-rbe-staging/gn-args.json"
   },
   "chromium.goma.fyi": {
     "Linux Builder Goma RBE Canary": "goma/Linux Builder Goma RBE Canary/gn-args.json",
-    "Mac Builder (dbg) Goma RBE Canary (clobber)": "goma/Mac Builder (dbg) Goma RBE Canary (clobber)/gn-args.json",
-    "Mac M1 Builder (dbg) Goma RBE Canary (clobber)": "goma/Mac M1 Builder (dbg) Goma RBE Canary (clobber)/gn-args.json",
     "Win Builder (dbg) Goma RBE Canary": "goma/Win Builder (dbg) Goma RBE Canary/gn-args.json",
     "Win Builder Goma RBE Canary": "goma/Win Builder Goma RBE Canary/gn-args.json",
     "chromeos-amd64-generic-rel-goma-rbe-canary": "goma/chromeos-amd64-generic-rel-goma-rbe-canary/gn-args.json",
-    "ios-device-goma-rbe-canary-clobber": "goma/ios-device-goma-rbe-canary-clobber/gn-args.json",
     "linux-archive-rel-goma-rbe-ats-canary": "goma/linux-archive-rel-goma-rbe-ats-canary/gn-args.json",
-    "linux-archive-rel-goma-rbe-canary": "goma/linux-archive-rel-goma-rbe-canary/gn-args.json",
-    "mac-archive-rel-goma-rbe-canary": "goma/mac-archive-rel-goma-rbe-canary/gn-args.json"
+    "linux-archive-rel-goma-rbe-canary": "goma/linux-archive-rel-goma-rbe-canary/gn-args.json"
   },
   "chromium.gpu": {
     "Android Release (Nexus 5X)": "ci/Android Release (Nexus 5X)/gn-args.json",
diff --git "a/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging \050dbg\051/gn-args.json" "b/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging \050dbg\051/gn-args.json"
deleted file mode 100644
index 0c0a7a7..0000000
--- "a/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging \050dbg\051/gn-args.json"
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "gn_args": {
-    "is_component_build": true,
-    "is_debug": true,
-    "symbol_level": 1,
-    "use_goma": true
-  }
-}
\ No newline at end of file
diff --git "a/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging \050dbg\051/properties.json" "b/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging \050dbg\051/properties.json"
deleted file mode 100644
index ea004ac..0000000
--- "a/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging \050dbg\051/properties.json"
+++ /dev/null
@@ -1,56 +0,0 @@
-{
-  "$build/chromium_tests_builder_config": {
-    "builder_config": {
-      "additional_exclusions": [
-        "infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging (dbg)/gn-args.json"
-      ],
-      "builder_db": {
-        "entries": [
-          {
-            "builder_id": {
-              "bucket": "goma",
-              "builder": "Chromium Mac Goma RBE Staging (dbg)",
-              "project": "chromium"
-            },
-            "builder_spec": {
-              "builder_group": "chromium.goma",
-              "execution_mode": "COMPILE_AND_TEST",
-              "legacy_chromium_config": {
-                "apply_configs": [
-                  "mb",
-                  "goma_failfast"
-                ],
-                "config": "chromium",
-                "target_bits": 64
-              },
-              "legacy_gclient_config": {
-                "config": "chromium"
-              }
-            }
-          }
-        ]
-      },
-      "builder_ids": [
-        {
-          "bucket": "goma",
-          "builder": "Chromium Mac Goma RBE Staging (dbg)",
-          "project": "chromium"
-        }
-      ]
-    }
-  },
-  "$build/goma": {
-    "jobs": 80,
-    "rpc_extra_params": "?staging",
-    "server_host": "staging-goma.chromium.org"
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "chromium.goma",
-  "recipe": "chromium"
-}
\ No newline at end of file
diff --git a/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging/gn-args.json b/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging/gn-args.json
deleted file mode 100644
index a4d9fbdb..0000000
--- a/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging/gn-args.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "gn_args": {
-    "dcheck_always_on": false,
-    "is_component_build": false,
-    "is_debug": false,
-    "use_goma": true
-  }
-}
\ No newline at end of file
diff --git a/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging/properties.json b/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging/properties.json
deleted file mode 100644
index 947d780..0000000
--- a/infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging/properties.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
-  "$build/chromium_tests_builder_config": {
-    "builder_config": {
-      "additional_exclusions": [
-        "infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging/gn-args.json"
-      ],
-      "builder_db": {
-        "entries": [
-          {
-            "builder_id": {
-              "bucket": "goma",
-              "builder": "Chromium Mac Goma RBE Staging",
-              "project": "chromium"
-            },
-            "builder_spec": {
-              "builder_group": "chromium.goma",
-              "execution_mode": "COMPILE_AND_TEST",
-              "legacy_chromium_config": {
-                "apply_configs": [
-                  "mb",
-                  "goma_failfast"
-                ],
-                "config": "chromium",
-                "target_bits": 64
-              },
-              "legacy_gclient_config": {
-                "config": "chromium"
-              }
-            }
-          }
-        ]
-      },
-      "builder_ids": [
-        {
-          "bucket": "goma",
-          "builder": "Chromium Mac Goma RBE Staging",
-          "project": "chromium"
-        }
-      ]
-    }
-  },
-  "$build/goma": {
-    "jobs": 80,
-    "rpc_extra_params": "?staging",
-    "server_host": "staging-goma.chromium.org"
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "chromium.goma",
-  "recipe": "chromium"
-}
\ No newline at end of file
diff --git "a/infra/config/generated/builders/goma/Mac Builder \050dbg\051 Goma RBE Canary \050clobber\051/gn-args.json" "b/infra/config/generated/builders/goma/Mac Builder \050dbg\051 Goma RBE Canary \050clobber\051/gn-args.json"
deleted file mode 100644
index b427f022..0000000
--- "a/infra/config/generated/builders/goma/Mac Builder \050dbg\051 Goma RBE Canary \050clobber\051/gn-args.json"
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "gn_args": {
-    "ffmpeg_branding": "Chrome",
-    "is_component_build": true,
-    "is_debug": true,
-    "proprietary_codecs": true,
-    "symbol_level": 1,
-    "use_goma": true
-  }
-}
\ No newline at end of file
diff --git "a/infra/config/generated/builders/goma/Mac Builder \050dbg\051 Goma RBE Canary \050clobber\051/properties.json" "b/infra/config/generated/builders/goma/Mac Builder \050dbg\051 Goma RBE Canary \050clobber\051/properties.json"
deleted file mode 100644
index 966b8da..0000000
--- "a/infra/config/generated/builders/goma/Mac Builder \050dbg\051 Goma RBE Canary \050clobber\051/properties.json"
+++ /dev/null
@@ -1,61 +0,0 @@
-{
-  "$build/chromium_tests_builder_config": {
-    "builder_config": {
-      "additional_exclusions": [
-        "infra/config/generated/builders/goma/Mac Builder (dbg) Goma RBE Canary (clobber)/gn-args.json"
-      ],
-      "builder_db": {
-        "entries": [
-          {
-            "builder_id": {
-              "bucket": "goma",
-              "builder": "Mac Builder (dbg) Goma RBE Canary (clobber)",
-              "project": "chromium"
-            },
-            "builder_spec": {
-              "build_gs_bucket": "chromium-fyi-archive",
-              "builder_group": "chromium.goma.fyi",
-              "execution_mode": "COMPILE_AND_TEST",
-              "legacy_chromium_config": {
-                "apply_configs": [
-                  "mb",
-                  "goma_canary",
-                  "clobber"
-                ],
-                "build_config": "Debug",
-                "config": "chromium",
-                "target_arch": "intel",
-                "target_bits": 64,
-                "target_platform": "mac"
-              },
-              "legacy_gclient_config": {
-                "config": "chromium"
-              }
-            }
-          }
-        ]
-      },
-      "builder_ids": [
-        {
-          "bucket": "goma",
-          "builder": "Mac Builder (dbg) Goma RBE Canary (clobber)",
-          "project": "chromium"
-        }
-      ]
-    }
-  },
-  "$build/goma": {
-    "jobs": 80,
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org"
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "chromium.goma.fyi",
-  "recipe": "chromium"
-}
\ No newline at end of file
diff --git "a/infra/config/generated/builders/goma/Mac M1 Builder \050dbg\051 Goma RBE Canary \050clobber\051/gn-args.json" "b/infra/config/generated/builders/goma/Mac M1 Builder \050dbg\051 Goma RBE Canary \050clobber\051/gn-args.json"
deleted file mode 100644
index 3fa40789..0000000
--- "a/infra/config/generated/builders/goma/Mac M1 Builder \050dbg\051 Goma RBE Canary \050clobber\051/gn-args.json"
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "gn_args": {
-    "ffmpeg_branding": "Chrome",
-    "is_component_build": true,
-    "is_debug": true,
-    "proprietary_codecs": true,
-    "symbol_level": 1,
-    "target_cpu": "arm64",
-    "use_goma": true
-  }
-}
\ No newline at end of file
diff --git "a/infra/config/generated/builders/goma/Mac M1 Builder \050dbg\051 Goma RBE Canary \050clobber\051/properties.json" "b/infra/config/generated/builders/goma/Mac M1 Builder \050dbg\051 Goma RBE Canary \050clobber\051/properties.json"
deleted file mode 100644
index 0dcccde..0000000
--- "a/infra/config/generated/builders/goma/Mac M1 Builder \050dbg\051 Goma RBE Canary \050clobber\051/properties.json"
+++ /dev/null
@@ -1,61 +0,0 @@
-{
-  "$build/chromium_tests_builder_config": {
-    "builder_config": {
-      "additional_exclusions": [
-        "infra/config/generated/builders/goma/Mac M1 Builder (dbg) Goma RBE Canary (clobber)/gn-args.json"
-      ],
-      "builder_db": {
-        "entries": [
-          {
-            "builder_id": {
-              "bucket": "goma",
-              "builder": "Mac M1 Builder (dbg) Goma RBE Canary (clobber)",
-              "project": "chromium"
-            },
-            "builder_spec": {
-              "build_gs_bucket": "chromium-fyi-archive",
-              "builder_group": "chromium.goma.fyi",
-              "execution_mode": "COMPILE_AND_TEST",
-              "legacy_chromium_config": {
-                "apply_configs": [
-                  "mb",
-                  "goma_canary",
-                  "clobber"
-                ],
-                "build_config": "Debug",
-                "config": "chromium",
-                "target_arch": "intel",
-                "target_bits": 64,
-                "target_platform": "mac"
-              },
-              "legacy_gclient_config": {
-                "config": "chromium"
-              }
-            }
-          }
-        ]
-      },
-      "builder_ids": [
-        {
-          "bucket": "goma",
-          "builder": "Mac M1 Builder (dbg) Goma RBE Canary (clobber)",
-          "project": "chromium"
-        }
-      ]
-    }
-  },
-  "$build/goma": {
-    "jobs": 80,
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org"
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "chromium.goma.fyi",
-  "recipe": "chromium"
-}
\ No newline at end of file
diff --git a/infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/gn-args.json b/infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/gn-args.json
deleted file mode 100644
index dcea2c7f..0000000
--- a/infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/gn-args.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "gn_args": {
-    "dcheck_always_on": false,
-    "ios_code_signing_identity_description": "Apple Development",
-    "ios_enable_code_signing": false,
-    "is_component_build": false,
-    "is_debug": false,
-    "symbol_level": 0,
-    "target_cpu": "arm64",
-    "target_environment": "device",
-    "target_os": "ios",
-    "use_goma": true
-  }
-}
\ No newline at end of file
diff --git a/infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/properties.json b/infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/properties.json
deleted file mode 100644
index 767d3d2..0000000
--- a/infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/properties.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
-  "$build/chromium_tests_builder_config": {
-    "builder_config": {
-      "additional_exclusions": [
-        "infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/gn-args.json"
-      ],
-      "builder_db": {
-        "entries": [
-          {
-            "builder_id": {
-              "bucket": "goma",
-              "builder": "ios-device-goma-rbe-canary-clobber",
-              "project": "chromium"
-            },
-            "builder_spec": {
-              "build_gs_bucket": "chromium-fyi-archive",
-              "builder_group": "chromium.goma.fyi",
-              "execution_mode": "COMPILE_AND_TEST",
-              "legacy_chromium_config": {
-                "apply_configs": [
-                  "mb",
-                  "mac_toolchain",
-                  "goma_canary",
-                  "clobber"
-                ],
-                "build_config": "Release",
-                "config": "chromium",
-                "target_bits": 64,
-                "target_platform": "ios"
-              },
-              "legacy_gclient_config": {
-                "config": "ios"
-              }
-            }
-          }
-        ]
-      },
-      "builder_ids": [
-        {
-          "bucket": "goma",
-          "builder": "ios-device-goma-rbe-canary-clobber",
-          "project": "chromium"
-        }
-      ]
-    }
-  },
-  "$build/goma": {
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org"
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "chromium.goma.fyi",
-  "recipe": "chromium",
-  "xcode_build_version": "15a507"
-}
\ No newline at end of file
diff --git a/infra/config/generated/builders/goma/mac-archive-rel-goma-rbe-canary/gn-args.json b/infra/config/generated/builders/goma/mac-archive-rel-goma-rbe-canary/gn-args.json
deleted file mode 100644
index 5097fb76..0000000
--- a/infra/config/generated/builders/goma/mac-archive-rel-goma-rbe-canary/gn-args.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "gn_args": {
-    "dcheck_always_on": false,
-    "is_component_build": false,
-    "is_debug": false,
-    "symbol_level": 1,
-    "use_goma": true
-  }
-}
\ No newline at end of file
diff --git a/infra/config/generated/builders/goma/mac-archive-rel-goma-rbe-canary/properties.json b/infra/config/generated/builders/goma/mac-archive-rel-goma-rbe-canary/properties.json
deleted file mode 100644
index 67b62b2..0000000
--- a/infra/config/generated/builders/goma/mac-archive-rel-goma-rbe-canary/properties.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
-  "$build/chromium_tests_builder_config": {
-    "builder_config": {
-      "additional_exclusions": [
-        "infra/config/generated/builders/goma/mac-archive-rel-goma-rbe-canary/gn-args.json"
-      ],
-      "builder_db": {
-        "entries": [
-          {
-            "builder_id": {
-              "bucket": "goma",
-              "builder": "mac-archive-rel-goma-rbe-canary",
-              "project": "chromium"
-            },
-            "builder_spec": {
-              "build_gs_bucket": "chromium-fyi-archive",
-              "builder_group": "chromium.goma.fyi",
-              "execution_mode": "COMPILE_AND_TEST",
-              "legacy_chromium_config": {
-                "apply_configs": [
-                  "clobber",
-                  "mb",
-                  "goma_canary"
-                ],
-                "build_config": "Release",
-                "config": "chromium",
-                "target_bits": 64
-              },
-              "legacy_gclient_config": {
-                "config": "chromium"
-              }
-            }
-          }
-        ]
-      },
-      "builder_ids": [
-        {
-          "bucket": "goma",
-          "builder": "mac-archive-rel-goma-rbe-canary",
-          "project": "chromium"
-        }
-      ]
-    }
-  },
-  "$build/goma": {
-    "jobs": 80,
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org"
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "chromium.goma.fyi",
-  "recipe": "chromium"
-}
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-10-arm64-rel/gn-args.json b/infra/config/generated/builders/try/android-10-arm64-rel/gn-args.json
index 59be6bd..e49de325 100644
--- a/infra/config/generated/builders/try/android-10-arm64-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-10-arm64-rel/gn-args.json
@@ -12,6 +12,7 @@
     "system_webview_package_name": "com.google.android.webview.debug",
     "target_cpu": "arm64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-10-arm64-rel/properties.json b/infra/config/generated/builders/try/android-10-arm64-rel/properties.json
index 860dda0c..150ff3c 100644
--- a/infra/config/generated/builders/try/android-10-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-10-arm64-rel/properties.json
@@ -55,6 +55,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-11-x86-rel/gn-args.json b/infra/config/generated/builders/try/android-11-x86-rel/gn-args.json
index 35c22216..2cda03d 100644
--- a/infra/config/generated/builders/try/android-11-x86-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-11-x86-rel/gn-args.json
@@ -13,6 +13,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x86",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-11-x86-rel/properties.json b/infra/config/generated/builders/try/android-11-x86-rel/properties.json
index 4153e3a..07ba6ca 100644
--- a/infra/config/generated/builders/try/android-11-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-11-x86-rel/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-12-x64-dbg/gn-args.json b/infra/config/generated/builders/try/android-12-x64-dbg/gn-args.json
index 70a253a5..20e0f876 100644
--- a/infra/config/generated/builders/try/android-12-x64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-12-x64-dbg/gn-args.json
@@ -10,6 +10,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-12-x64-dbg/properties.json b/infra/config/generated/builders/try/android-12-x64-dbg/properties.json
index c8d1088..9a4e02b 100644
--- a/infra/config/generated/builders/try/android-12-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-12-x64-dbg/properties.json
@@ -89,6 +89,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-12l-x64-dbg/gn-args.json b/infra/config/generated/builders/try/android-12l-x64-dbg/gn-args.json
index 70a253a5..20e0f876 100644
--- a/infra/config/generated/builders/try/android-12l-x64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-12l-x64-dbg/gn-args.json
@@ -10,6 +10,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-12l-x64-dbg/properties.json b/infra/config/generated/builders/try/android-12l-x64-dbg/properties.json
index 170d12f..8fb0aad1 100644
--- a/infra/config/generated/builders/try/android-12l-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-12l-x64-dbg/properties.json
@@ -92,6 +92,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-13-x64-rel/gn-args.json b/infra/config/generated/builders/try/android-13-x64-rel/gn-args.json
index 639e78b..5ffa0953 100644
--- a/infra/config/generated/builders/try/android-13-x64-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-13-x64-rel/gn-args.json
@@ -14,6 +14,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-13-x64-rel/properties.json b/infra/config/generated/builders/try/android-13-x64-rel/properties.json
index ebf8749..96bda73 100644
--- a/infra/config/generated/builders/try/android-13-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-13-x64-rel/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-14-x64-rel/gn-args.json b/infra/config/generated/builders/try/android-14-x64-rel/gn-args.json
index 639e78b..5ffa0953 100644
--- a/infra/config/generated/builders/try/android-14-x64-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-14-x64-rel/gn-args.json
@@ -14,6 +14,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-14-x64-rel/properties.json b/infra/config/generated/builders/try/android-14-x64-rel/properties.json
index e36c8d9e..94a53967 100644
--- a/infra/config/generated/builders/try/android-14-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-14-x64-rel/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-arm-compile-dbg/gn-args.json b/infra/config/generated/builders/try/android-arm-compile-dbg/gn-args.json
index 9e39d5e..93e4f18b 100644
--- a/infra/config/generated/builders/try/android-arm-compile-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-arm-compile-dbg/gn-args.json
@@ -5,6 +5,7 @@
     "is_debug": true,
     "symbol_level": 1,
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-arm-compile-dbg/properties.json b/infra/config/generated/builders/try/android-arm-compile-dbg/properties.json
index 048483a7..d169258 100644
--- a/infra/config/generated/builders/try/android-arm-compile-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-arm-compile-dbg/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-arm64-all-targets-dbg/gn-args.json b/infra/config/generated/builders/try/android-arm64-all-targets-dbg/gn-args.json
index 15fe162..35e0d01 100644
--- a/infra/config/generated/builders/try/android-arm64-all-targets-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-arm64-all-targets-dbg/gn-args.json
@@ -9,6 +9,7 @@
     "symbol_level": 0,
     "target_cpu": "arm64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-arm64-all-targets-dbg/properties.json b/infra/config/generated/builders/try/android-arm64-all-targets-dbg/properties.json
index b263ab13..863563d 100644
--- a/infra/config/generated/builders/try/android-arm64-all-targets-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-arm64-all-targets-dbg/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-asan-compile-dbg/gn-args.json b/infra/config/generated/builders/try/android-asan-compile-dbg/gn-args.json
index 26f90d0..a617e63 100644
--- a/infra/config/generated/builders/try/android-asan-compile-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-asan-compile-dbg/gn-args.json
@@ -10,6 +10,7 @@
     "strip_debug_info": true,
     "symbol_level": 0,
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-asan-compile-dbg/properties.json b/infra/config/generated/builders/try/android-asan-compile-dbg/properties.json
index 0ed3290..e27fed4 100644
--- a/infra/config/generated/builders/try/android-asan-compile-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-asan-compile-dbg/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-bfcache-rel/gn-args.json b/infra/config/generated/builders/try/android-bfcache-rel/gn-args.json
index 80d4ec23..f55c7e7 100644
--- a/infra/config/generated/builders/try/android-bfcache-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-bfcache-rel/gn-args.json
@@ -13,6 +13,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x86",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-bfcache-rel/properties.json b/infra/config/generated/builders/try/android-bfcache-rel/properties.json
index 36be61a..85bb457f 100644
--- a/infra/config/generated/builders/try/android-bfcache-rel/properties.json
+++ b/infra/config/generated/builders/try/android-bfcache-rel/properties.json
@@ -50,6 +50,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-android-specific/gn-args.json b/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-android-specific/gn-args.json
index 80d4ec23..f55c7e7 100644
--- a/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-android-specific/gn-args.json
+++ b/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-android-specific/gn-args.json
@@ -13,6 +13,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x86",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-android-specific/properties.json b/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-android-specific/properties.json
index cac6043..50269a38 100644
--- a/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-android-specific/properties.json
+++ b/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-android-specific/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/gn-args.json b/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/gn-args.json
index 80d4ec23..f55c7e7 100644
--- a/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/gn-args.json
@@ -13,6 +13,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x86",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/properties.json b/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/properties.json
index d839dcc6..9424fc14 100644
--- a/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-clobber-rel/gn-args.json b/infra/config/generated/builders/try/android-clobber-rel/gn-args.json
index 8eefc7c..da57487 100644
--- a/infra/config/generated/builders/try/android-clobber-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-clobber-rel/gn-args.json
@@ -9,6 +9,7 @@
     "strip_debug_info": true,
     "symbol_level": 0,
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-clobber-rel/properties.json b/infra/config/generated/builders/try/android-clobber-rel/properties.json
index b664105e..ad34e17 100644
--- a/infra/config/generated/builders/try/android-clobber-rel/properties.json
+++ b/infra/config/generated/builders/try/android-clobber-rel/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-code-coverage-native/gn-args.json b/infra/config/generated/builders/try/android-code-coverage-native/gn-args.json
index a5c3e83f..a83ae98 100644
--- a/infra/config/generated/builders/try/android-code-coverage-native/gn-args.json
+++ b/infra/config/generated/builders/try/android-code-coverage-native/gn-args.json
@@ -14,6 +14,7 @@
     "target_os": "android",
     "use_clang_coverage": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_static_angle": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-code-coverage-native/properties.json b/infra/config/generated/builders/try/android-code-coverage-native/properties.json
index 8b9f5eda..6a601ed 100644
--- a/infra/config/generated/builders/try/android-code-coverage-native/properties.json
+++ b/infra/config/generated/builders/try/android-code-coverage-native/properties.json
@@ -55,6 +55,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-code-coverage/gn-args.json b/infra/config/generated/builders/try/android-code-coverage/gn-args.json
index 454eb70..b5501cd 100644
--- a/infra/config/generated/builders/try/android-code-coverage/gn-args.json
+++ b/infra/config/generated/builders/try/android-code-coverage/gn-args.json
@@ -15,6 +15,7 @@
     "target_os": "android",
     "use_jacoco_coverage": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_static_angle": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-code-coverage/properties.json b/infra/config/generated/builders/try/android-code-coverage/properties.json
index c235edd..049707d 100644
--- a/infra/config/generated/builders/try/android-code-coverage/properties.json
+++ b/infra/config/generated/builders/try/android-code-coverage/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-arm-dbg/gn-args.json b/infra/config/generated/builders/try/android-cronet-arm-dbg/gn-args.json
index 70e51ef..6aa22fd 100644
--- a/infra/config/generated/builders/try/android-cronet-arm-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-arm-dbg/gn-args.json
@@ -25,6 +25,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json
index f6dd10e..7ecd1bc0 100644
--- a/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json
@@ -58,6 +58,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-arm64-dbg/gn-args.json b/infra/config/generated/builders/try/android-cronet-arm64-dbg/gn-args.json
index e274161..ab0cc97 100644
--- a/infra/config/generated/builders/try/android-cronet-arm64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-arm64-dbg/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-arm64-dbg/properties.json
index 58f6aef2..82b4ab1 100644
--- a/infra/config/generated/builders/try/android-cronet-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-arm64-dbg/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-arm64-rel/gn-args.json b/infra/config/generated/builders/try/android-cronet-arm64-rel/gn-args.json
index 0015580c..1758a829 100644
--- a/infra/config/generated/builders/try/android-cronet-arm64-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-arm64-rel/gn-args.json
@@ -26,6 +26,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-arm64-rel/properties.json b/infra/config/generated/builders/try/android-cronet-arm64-rel/properties.json
index 4ce16d7..65e710a7d 100644
--- a/infra/config/generated/builders/try/android-cronet-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-arm64-rel/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-asan-arm-rel/gn-args.json b/infra/config/generated/builders/try/android-cronet-asan-arm-rel/gn-args.json
index b8159e5..b3fcf8b 100644
--- a/infra/config/generated/builders/try/android-cronet-asan-arm-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-asan-arm-rel/gn-args.json
@@ -28,6 +28,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-asan-arm-rel/properties.json b/infra/config/generated/builders/try/android-cronet-asan-arm-rel/properties.json
index 12560cf..7de6c587 100644
--- a/infra/config/generated/builders/try/android-cronet-asan-arm-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-asan-arm-rel/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/gn-args.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/gn-args.json
index e05343fe..8acae902ff 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/gn-args.json
@@ -26,6 +26,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/properties.json
index 4f1c6daa..654b831 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/gn-args.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/gn-args.json
index ed65b9c..4d3730f 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/gn-args.json
@@ -29,6 +29,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/properties.json
index 8bf15b8a..b9b1353 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/gn-args.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/gn-args.json
index 064ff94..95767ad9 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/gn-args.json
@@ -26,6 +26,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/properties.json
index 1ee646c..13592f1 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/gn-args.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/gn-args.json
index 6afbe717..76ae4c72 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/gn-args.json
@@ -29,6 +29,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/properties.json
index 9981c0c..99e9c8d 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/gn-args.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/gn-args.json
index 38c4ab7..7ca2ab2 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/gn-args.json
@@ -26,6 +26,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/properties.json
index 3597a9d..0cc4abda 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/gn-args.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/gn-args.json
index 1cf1f85129..563df2cd 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/gn-args.json
@@ -29,6 +29,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/properties.json
index 06438e7..10ca786 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-riscv64-dbg/gn-args.json b/infra/config/generated/builders/try/android-cronet-riscv64-dbg/gn-args.json
index 49fb8477..350b50c2 100644
--- a/infra/config/generated/builders/try/android-cronet-riscv64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-riscv64-dbg/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-riscv64-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-riscv64-dbg/properties.json
index ebd0d77..4b0be3a 100644
--- a/infra/config/generated/builders/try/android-cronet-riscv64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-riscv64-dbg/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-riscv64-rel/gn-args.json b/infra/config/generated/builders/try/android-cronet-riscv64-rel/gn-args.json
index f9fe7bf..4a942d7 100644
--- a/infra/config/generated/builders/try/android-cronet-riscv64-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-riscv64-rel/gn-args.json
@@ -26,6 +26,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-riscv64-rel/properties.json b/infra/config/generated/builders/try/android-cronet-riscv64-rel/properties.json
index b4ef1540..966754a 100644
--- a/infra/config/generated/builders/try/android-cronet-riscv64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-riscv64-rel/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/gn-args.json b/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/gn-args.json
index 5f0e083..6b524e8 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/properties.json
index c065fed..100fd98 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/properties.json
@@ -97,6 +97,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/gn-args.json b/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/gn-args.json
index 5f0e083..6b524e8 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/properties.json
index f439aee..de9824d 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/properties.json
@@ -97,6 +97,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/gn-args.json b/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/gn-args.json
index 5f0e083..6b524e8 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/properties.json
index 83e3372..225da31 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/properties.json
@@ -101,6 +101,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg/gn-args.json b/infra/config/generated/builders/try/android-cronet-x64-dbg/gn-args.json
index 5f0e083..6b524e8 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-x64-dbg/properties.json
index 32deff4..bf2b31e 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x64-rel/gn-args.json b/infra/config/generated/builders/try/android-cronet-x64-rel/gn-args.json
index c600dcf..92e3201 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-rel/gn-args.json
@@ -26,6 +26,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x64-rel/properties.json b/infra/config/generated/builders/try/android-cronet-x64-rel/properties.json
index 62596bb9..74815fa 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-rel/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/gn-args.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/gn-args.json
index b5d6ff72..20a36fe 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/properties.json
index 94ac5a6..6cb589f 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/properties.json
@@ -97,6 +97,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/gn-args.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/gn-args.json
index b5d6ff72..20a36fe 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/properties.json
index 4783488..5d2a5da 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/properties.json
@@ -97,6 +97,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-lollipop-tests/gn-args.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-lollipop-tests/gn-args.json
index b5d6ff72..20a36fe 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-lollipop-tests/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-lollipop-tests/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-lollipop-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-lollipop-tests/properties.json
index 685e840c..feaccd5c 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-lollipop-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-lollipop-tests/properties.json
@@ -101,6 +101,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/gn-args.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/gn-args.json
index b5d6ff72..20a36fe 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/properties.json
index cc5a6fc..10b0398 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/properties.json
@@ -97,6 +97,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/gn-args.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/gn-args.json
index b5d6ff72..20a36fe 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/properties.json
index d951271..a5438968 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/properties.json
@@ -97,6 +97,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/gn-args.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/gn-args.json
index b5d6ff72..20a36fe 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/properties.json
index 566ff8c..7ac3ea0 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/properties.json
@@ -97,6 +97,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/gn-args.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/gn-args.json
index b5d6ff72..20a36fe 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/properties.json
index 6250037..895dd52a 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/properties.json
@@ -97,6 +97,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg/gn-args.json b/infra/config/generated/builders/try/android-cronet-x86-dbg/gn-args.json
index b5d6ff72..20a36fe 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg/gn-args.json
@@ -23,6 +23,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg/properties.json
index 9465fa9..74f8c52 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-cronet-x86-rel/gn-args.json b/infra/config/generated/builders/try/android-cronet-x86-rel/gn-args.json
index eb91d625..a2af1c1 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-rel/gn-args.json
@@ -26,6 +26,7 @@
     "use_partition_alloc": false,
     "use_platform_icu_alternatives": true,
     "use_remoteexec": true,
+    "use_siso": true,
     "use_thin_lto": false
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-cronet-x86-rel/properties.json b/infra/config/generated/builders/try/android-cronet-x86-rel/properties.json
index 6665c195..b65ea42 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-rel/properties.json
@@ -54,6 +54,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-deterministic-dbg/gn-args.json b/infra/config/generated/builders/try/android-deterministic-dbg/gn-args.json
index 923b14c..14c6763 100644
--- a/infra/config/generated/builders/try/android-deterministic-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-deterministic-dbg/gn-args.json
@@ -7,6 +7,7 @@
     "proprietary_codecs": true,
     "symbol_level": 1,
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-deterministic-rel/gn-args.json b/infra/config/generated/builders/try/android-deterministic-rel/gn-args.json
index b5a2958a..10b8570 100644
--- a/infra/config/generated/builders/try/android-deterministic-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-deterministic-rel/gn-args.json
@@ -7,6 +7,7 @@
     "strip_debug_info": true,
     "symbol_level": 0,
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-fieldtrial-rel/gn-args.json b/infra/config/generated/builders/try/android-fieldtrial-rel/gn-args.json
index 639e78b..5ffa0953 100644
--- a/infra/config/generated/builders/try/android-fieldtrial-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-fieldtrial-rel/gn-args.json
@@ -14,6 +14,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-fieldtrial-rel/properties.json b/infra/config/generated/builders/try/android-fieldtrial-rel/properties.json
index 18d0db9..862d91ac 100644
--- a/infra/config/generated/builders/try/android-fieldtrial-rel/properties.json
+++ b/infra/config/generated/builders/try/android-fieldtrial-rel/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-oreo-arm64-dbg/gn-args.json b/infra/config/generated/builders/try/android-oreo-arm64-dbg/gn-args.json
index 24e6409..bc393d1 100644
--- a/infra/config/generated/builders/try/android-oreo-arm64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-oreo-arm64-dbg/gn-args.json
@@ -8,6 +8,7 @@
     "symbol_level": 1,
     "target_cpu": "arm64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json
index 3dacdfbd..8cdb601 100644
--- a/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json
@@ -95,6 +95,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-oreo-x86-rel/gn-args.json b/infra/config/generated/builders/try/android-oreo-x86-rel/gn-args.json
index 3f7ceee3..ed2fbef 100644
--- a/infra/config/generated/builders/try/android-oreo-x86-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-oreo-x86-rel/gn-args.json
@@ -15,6 +15,7 @@
     "target_cpu": "x86",
     "target_os": "android",
     "use_jacoco_coverage": true,
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-oreo-x86-rel/properties.json b/infra/config/generated/builders/try/android-oreo-x86-rel/properties.json
index 25739e4..7c36c074 100644
--- a/infra/config/generated/builders/try/android-oreo-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-oreo-x86-rel/properties.json
@@ -58,6 +58,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-perfetto-rel/gn-args.json b/infra/config/generated/builders/try/android-perfetto-rel/gn-args.json
index e46fbc2c..ab2ad99 100644
--- a/infra/config/generated/builders/try/android-perfetto-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-perfetto-rel/gn-args.json
@@ -10,6 +10,7 @@
     "target_cpu": "x64",
     "target_os": "android",
     "use_perfetto_client_library": true,
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-perfetto-rel/properties.json b/infra/config/generated/builders/try/android-perfetto-rel/properties.json
index d3f002b..b7a2f7c 100644
--- a/infra/config/generated/builders/try/android-perfetto-rel/properties.json
+++ b/infra/config/generated/builders/try/android-perfetto-rel/properties.json
@@ -52,6 +52,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-pie-arm64-dbg/gn-args.json b/infra/config/generated/builders/try/android-pie-arm64-dbg/gn-args.json
index 4bd2489..5c5d7ca 100644
--- a/infra/config/generated/builders/try/android-pie-arm64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-pie-arm64-dbg/gn-args.json
@@ -9,6 +9,7 @@
     "system_webview_package_name": "com.google.android.webview",
     "target_cpu": "arm64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json
index 1bda5fa..a2e529f 100644
--- a/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json
@@ -99,6 +99,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-pie-x86-rel/gn-args.json b/infra/config/generated/builders/try/android-pie-x86-rel/gn-args.json
index 80d4ec23..f55c7e7 100644
--- a/infra/config/generated/builders/try/android-pie-x86-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-pie-x86-rel/gn-args.json
@@ -13,6 +13,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x86",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-pie-x86-rel/properties.json b/infra/config/generated/builders/try/android-pie-x86-rel/properties.json
index 7223ecd8..efafdf87 100644
--- a/infra/config/generated/builders/try/android-pie-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-pie-x86-rel/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/gn-args.json b/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/gn-args.json
index 35c22216..2cda03d 100644
--- a/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/gn-args.json
+++ b/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/gn-args.json
@@ -13,6 +13,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x86",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/properties.json b/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/properties.json
index 998f7fc9a..428b1b8 100644
--- a/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/properties.json
+++ b/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/properties.json
@@ -89,6 +89,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-webview-12-x64-dbg/gn-args.json b/infra/config/generated/builders/try/android-webview-12-x64-dbg/gn-args.json
index 70a253a5..20e0f876 100644
--- a/infra/config/generated/builders/try/android-webview-12-x64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-webview-12-x64-dbg/gn-args.json
@@ -10,6 +10,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-webview-12-x64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-12-x64-dbg/properties.json
index 818b913..a5b340c 100644
--- a/infra/config/generated/builders/try/android-webview-12-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-webview-12-x64-dbg/properties.json
@@ -89,6 +89,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-webview-13-x64-dbg-hostside/gn-args.json b/infra/config/generated/builders/try/android-webview-13-x64-dbg-hostside/gn-args.json
index 70a253a5..20e0f876 100644
--- a/infra/config/generated/builders/try/android-webview-13-x64-dbg-hostside/gn-args.json
+++ b/infra/config/generated/builders/try/android-webview-13-x64-dbg-hostside/gn-args.json
@@ -10,6 +10,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-webview-13-x64-dbg-hostside/properties.json b/infra/config/generated/builders/try/android-webview-13-x64-dbg-hostside/properties.json
index 70b80c2b..34b3b2b 100644
--- a/infra/config/generated/builders/try/android-webview-13-x64-dbg-hostside/properties.json
+++ b/infra/config/generated/builders/try/android-webview-13-x64-dbg-hostside/properties.json
@@ -50,6 +50,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-webview-13-x64-dbg/gn-args.json b/infra/config/generated/builders/try/android-webview-13-x64-dbg/gn-args.json
index 70a253a5..20e0f876 100644
--- a/infra/config/generated/builders/try/android-webview-13-x64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-webview-13-x64-dbg/gn-args.json
@@ -10,6 +10,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-webview-13-x64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-13-x64-dbg/properties.json
index 14e7dd7..68786b8 100644
--- a/infra/config/generated/builders/try/android-webview-13-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-webview-13-x64-dbg/properties.json
@@ -89,6 +89,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/gn-args.json b/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/gn-args.json
index b240db29..ce47d80 100644
--- a/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/gn-args.json
@@ -11,6 +11,7 @@
     "system_webview_package_name": "com.google.android.apps.chrome",
     "target_cpu": "arm64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json
index ffb8891..53799b3 100644
--- a/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json
@@ -98,6 +98,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/gn-args.json b/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/gn-args.json
index b240db29..ce47d80 100644
--- a/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/gn-args.json
@@ -11,6 +11,7 @@
     "system_webview_package_name": "com.google.android.apps.chrome",
     "target_cpu": "arm64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json
index b73417a0..3b35295 100644
--- a/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json
@@ -98,6 +98,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/gn-args.json b/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/gn-args.json
index f423bd4..e421386a 100644
--- a/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/gn-args.json
+++ b/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/gn-args.json
@@ -13,6 +13,7 @@
     "system_webview_shell_package_name": "org.chromium.my_webview_shell",
     "target_cpu": "x86",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/properties.json b/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/properties.json
index c914c407..3d0b1ed19 100644
--- a/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android_arm64_dbg_recipe/gn-args.json b/infra/config/generated/builders/try/android_arm64_dbg_recipe/gn-args.json
index 15fe162..35e0d01 100644
--- a/infra/config/generated/builders/try/android_arm64_dbg_recipe/gn-args.json
+++ b/infra/config/generated/builders/try/android_arm64_dbg_recipe/gn-args.json
@@ -9,6 +9,7 @@
     "symbol_level": 0,
     "target_cpu": "arm64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json b/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json
index c7757331..94e730d8 100644
--- a/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json
+++ b/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json
@@ -222,6 +222,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android_blink_rel/gn-args.json b/infra/config/generated/builders/try/android_blink_rel/gn-args.json
index 9cf93ba..c0f334d 100644
--- a/infra/config/generated/builders/try/android_blink_rel/gn-args.json
+++ b/infra/config/generated/builders/try/android_blink_rel/gn-args.json
@@ -10,6 +10,7 @@
     "symbol_level": 0,
     "target_cpu": "x64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android_blink_rel/properties.json b/infra/config/generated/builders/try/android_blink_rel/properties.json
index 7e82ab0..3a25b639 100644
--- a/infra/config/generated/builders/try/android_blink_rel/properties.json
+++ b/infra/config/generated/builders/try/android_blink_rel/properties.json
@@ -52,6 +52,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android_compile_x64_dbg/gn-args.json b/infra/config/generated/builders/try/android_compile_x64_dbg/gn-args.json
index 00650fa..06eda99 100644
--- a/infra/config/generated/builders/try/android_compile_x64_dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android_compile_x64_dbg/gn-args.json
@@ -8,6 +8,7 @@
     "symbol_level": 0,
     "target_cpu": "x64",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android_compile_x64_dbg/properties.json b/infra/config/generated/builders/try/android_compile_x64_dbg/properties.json
index 6f9d38a..09541df 100644
--- a/infra/config/generated/builders/try/android_compile_x64_dbg/properties.json
+++ b/infra/config/generated/builders/try/android_compile_x64_dbg/properties.json
@@ -55,6 +55,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android_compile_x86_dbg/gn-args.json b/infra/config/generated/builders/try/android_compile_x86_dbg/gn-args.json
index 074c275..63c0c6a 100644
--- a/infra/config/generated/builders/try/android_compile_x86_dbg/gn-args.json
+++ b/infra/config/generated/builders/try/android_compile_x86_dbg/gn-args.json
@@ -8,6 +8,7 @@
     "symbol_level": 0,
     "target_cpu": "x86",
     "target_os": "android",
-    "use_remoteexec": true
+    "use_remoteexec": true,
+    "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android_compile_x86_dbg/properties.json b/infra/config/generated/builders/try/android_compile_x86_dbg/properties.json
index 32c013d7..75deb07f 100644
--- a/infra/config/generated/builders/try/android_compile_x86_dbg/properties.json
+++ b/infra/config/generated/builders/try/android_compile_x86_dbg/properties.json
@@ -55,6 +55,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/android_optional_gpu_tests_rel/gn-args.json b/infra/config/generated/builders/try/android_optional_gpu_tests_rel/gn-args.json
index 6b7ea53..50ef320 100644
--- a/infra/config/generated/builders/try/android_optional_gpu_tests_rel/gn-args.json
+++ b/infra/config/generated/builders/try/android_optional_gpu_tests_rel/gn-args.json
@@ -9,6 +9,7 @@
     "symbol_level": 1,
     "target_os": "android",
     "use_remoteexec": true,
+    "use_siso": true,
     "use_static_angle": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android_optional_gpu_tests_rel/properties.json b/infra/config/generated/builders/try/android_optional_gpu_tests_rel/properties.json
index 9f6b385e..e76f0be2 100644
--- a/infra/config/generated/builders/try/android_optional_gpu_tests_rel/properties.json
+++ b/infra/config/generated/builders/try/android_optional_gpu_tests_rel/properties.json
@@ -53,6 +53,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/gn-args.json b/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/gn-args.json
index 6017783..9132bbb3 100644
--- a/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/gn-args.json
+++ b/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/gn-args.json
@@ -10,6 +10,7 @@
     "target_cpu": "arm64",
     "target_os": "android",
     "use_remoteexec": true,
+    "use_siso": true,
     "use_static_angle": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/properties.json b/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/properties.json
index cb3344b..4fd903cd9 100644
--- a/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/properties.json
+++ b/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/properties.json
@@ -95,6 +95,15 @@
     "metrics_project": "chromium-reclient-metrics",
     "scandeps_server": true
   },
+  "$build/siso": {
+    "configs": [
+      "builder"
+    ],
+    "enable_cloud_profiler": true,
+    "enable_cloud_trace": true,
+    "experiments": [],
+    "project": "rbe-chromium-untrusted"
+  },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
     "grouping_keys": [
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 95d1b871..2b4cb52 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -57973,102 +57973,6 @@
       }
     }
     builders {
-      name: "Chromium Mac Goma RBE Staging"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:Chromium Mac Goma RBE Staging"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Mac-13"
-      dimensions: "pool:luci.chromium.ci"
-      exe {
-        cipd_package: "infra/chromium/bootstrapper/${platform}"
-        cipd_version: "latest"
-        cmd: "bootstrapper"
-      }
-      properties:
-        '{'
-        '  "$bootstrap/exe": {'
-        '    "exe": {'
-        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
-        '      "cipd_version": "refs/heads/main",'
-        '      "cmd": ['
-        '        "luciexe"'
-        '      ]'
-        '    }'
-        '  },'
-        '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging/properties.json",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "chromium.goma",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium"'
-        '}'
-      execution_timeout_secs: 10800
-      build_numbers: YES
-      service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      resultdb {
-        enable: true
-      }
-    }
-    builders {
-      name: "Chromium Mac Goma RBE Staging (dbg)"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:Chromium Mac Goma RBE Staging (dbg)"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Mac-13"
-      dimensions: "pool:luci.chromium.ci"
-      exe {
-        cipd_package: "infra/chromium/bootstrapper/${platform}"
-        cipd_version: "latest"
-        cmd: "bootstrapper"
-      }
-      properties:
-        '{'
-        '  "$bootstrap/exe": {'
-        '    "exe": {'
-        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
-        '      "cipd_version": "refs/heads/main",'
-        '      "cmd": ['
-        '        "luciexe"'
-        '      ]'
-        '    }'
-        '  },'
-        '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/goma/Chromium Mac Goma RBE Staging (dbg)/properties.json",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "chromium.goma",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium"'
-        '}'
-      execution_timeout_secs: 10800
-      build_numbers: YES
-      service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      resultdb {
-        enable: true
-      }
-    }
-    builders {
       name: "Chromium Win Goma RBE Staging"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:Chromium Win Goma RBE Staging"
@@ -58169,102 +58073,6 @@
       }
     }
     builders {
-      name: "Mac Builder (dbg) Goma RBE Canary (clobber)"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:Mac Builder (dbg) Goma RBE Canary (clobber)"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Mac-13"
-      dimensions: "pool:luci.chromium.ci"
-      exe {
-        cipd_package: "infra/chromium/bootstrapper/${platform}"
-        cipd_version: "latest"
-        cmd: "bootstrapper"
-      }
-      properties:
-        '{'
-        '  "$bootstrap/exe": {'
-        '    "exe": {'
-        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
-        '      "cipd_version": "refs/heads/main",'
-        '      "cmd": ['
-        '        "luciexe"'
-        '      ]'
-        '    }'
-        '  },'
-        '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/goma/Mac Builder (dbg) Goma RBE Canary (clobber)/properties.json",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "chromium.goma.fyi",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium"'
-        '}'
-      execution_timeout_secs: 36000
-      build_numbers: YES
-      service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      resultdb {
-        enable: true
-      }
-    }
-    builders {
-      name: "Mac M1 Builder (dbg) Goma RBE Canary (clobber)"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:Mac M1 Builder (dbg) Goma RBE Canary (clobber)"
-      dimensions: "cpu:arm64"
-      dimensions: "os:Mac-13"
-      dimensions: "pool:luci.chromium.ci"
-      exe {
-        cipd_package: "infra/chromium/bootstrapper/${platform}"
-        cipd_version: "latest"
-        cmd: "bootstrapper"
-      }
-      properties:
-        '{'
-        '  "$bootstrap/exe": {'
-        '    "exe": {'
-        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
-        '      "cipd_version": "refs/heads/main",'
-        '      "cmd": ['
-        '        "luciexe"'
-        '      ]'
-        '    }'
-        '  },'
-        '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/goma/Mac M1 Builder (dbg) Goma RBE Canary (clobber)/properties.json",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "chromium.goma.fyi",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium"'
-        '}'
-      execution_timeout_secs: 36000
-      build_numbers: YES
-      service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      resultdb {
-        enable: true
-      }
-    }
-    builders {
       name: "Win Builder (dbg) Goma RBE Canary"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:Win Builder (dbg) Goma RBE Canary"
@@ -58463,58 +58271,6 @@
       }
     }
     builders {
-      name: "ios-device-goma-rbe-canary-clobber"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:ios-device-goma-rbe-canary-clobber"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Mac-13"
-      dimensions: "pool:luci.chromium.ci"
-      exe {
-        cipd_package: "infra/chromium/bootstrapper/${platform}"
-        cipd_version: "latest"
-        cmd: "bootstrapper"
-      }
-      properties:
-        '{'
-        '  "$bootstrap/exe": {'
-        '    "exe": {'
-        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
-        '      "cipd_version": "refs/heads/main",'
-        '      "cmd": ['
-        '        "luciexe"'
-        '      ]'
-        '    }'
-        '  },'
-        '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/properties.json",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "chromium.goma.fyi",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium"'
-        '}'
-      execution_timeout_secs: 36000
-      caches {
-        name: "xcode_ios_15a507"
-        path: "xcode_ios_15a507.app"
-      }
-      build_numbers: YES
-      service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      resultdb {
-        enable: true
-      }
-    }
-    builders {
       name: "linux-archive-rel-goma-rbe-ats-canary"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
@@ -58616,54 +58372,6 @@
         enable: true
       }
     }
-    builders {
-      name: "mac-archive-rel-goma-rbe-canary"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:mac-archive-rel-goma-rbe-canary"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Mac-13"
-      dimensions: "pool:luci.chromium.ci"
-      exe {
-        cipd_package: "infra/chromium/bootstrapper/${platform}"
-        cipd_version: "latest"
-        cmd: "bootstrapper"
-      }
-      properties:
-        '{'
-        '  "$bootstrap/exe": {'
-        '    "exe": {'
-        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
-        '      "cipd_version": "refs/heads/main",'
-        '      "cmd": ['
-        '        "luciexe"'
-        '      ]'
-        '    }'
-        '  },'
-        '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/goma/mac-archive-rel-goma-rbe-canary/properties.json",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "chromium.goma.fyi",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium"'
-        '}'
-      execution_timeout_secs: 36000
-      build_numbers: YES
-      service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      resultdb {
-        enable: true
-      }
-    }
   }
 }
 buckets {
@@ -67450,6 +67158,15 @@
         '    "metrics_project": "chromium-reclient-metrics",'
         '    "scandeps_server": true'
         '  },'
+        '  "$build/siso": {'
+        '    "configs": ['
+        '      "builder"'
+        '    ],'
+        '    "enable_cloud_profiler": true,'
+        '    "enable_cloud_trace": true,'
+        '    "experiments": [],'
+        '    "project": "rbe-chromium-untrusted"'
+        '  },'
         '  "$recipe_engine/resultdb/test_presentation": {'
         '    "column_keys": [],'
         '    "grouping_keys": ['
@@ -67537,6 +67254,15 @@
         '    "metrics_project": "chromium-reclient-metrics",'
         '    "scandeps_server": true'
         '  },'
+        '  "$build/siso": {'
+        '    "configs": ['
+        '      "builder"'
+        '    ],'
+        '    "enable_cloud_profiler": true,'
+        '    "enable_cloud_trace": true,'
+        '    "experiments": [],'
+        '    "project": "rbe-chromium-untrusted"'
+        '  },'
         '  "$recipe_engine/resultdb/test_presentation": {'
         '    "column_keys": [],'
         '    "grouping_keys": ['
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index ea7983c..50bfe329 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -9860,14 +9860,6 @@
     category: "rbe|staging|linux|debug"
   }
   builders {
-    name: "buildbucket/luci.chromium.goma/Chromium Mac Goma RBE Staging"
-    category: "rbe|staging|mac|rel"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.goma/Chromium Mac Goma RBE Staging (dbg)"
-    category: "rbe|staging|mac|debug"
-  }
-  builders {
     name: "buildbucket/luci.chromium.goma/Chromium Win Goma RBE Staging"
     category: "rbe|staging|win|rel"
   }
@@ -10232,26 +10224,6 @@
     category: "rbe|cros|rel"
   }
   builders {
-    name: "buildbucket/luci.chromium.goma/mac-archive-rel-goma-rbe-canary"
-    category: "rbe|mac|rel"
-    short_name: "clb"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.goma/Mac Builder (dbg) Goma RBE Canary (clobber)"
-    category: "rbe|mac|dbg"
-    short_name: "clb"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.goma/Mac M1 Builder (dbg) Goma RBE Canary (clobber)"
-    category: "rbe|mac|dbg"
-    short_name: "m1"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.goma/ios-device-goma-rbe-canary-clobber"
-    category: "rbe|ios"
-    short_name: "clb"
-  }
-  builders {
     name: "buildbucket/luci.chromium.goma/Win Builder Goma RBE Canary"
     category: "rbe|win|rel"
   }
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg
index 1371a5d60..3cd42eb 100644
--- a/infra/config/generated/luci/luci-scheduler.cfg
+++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -379,24 +379,6 @@
   }
 }
 job {
-  id: "Chromium Mac Goma RBE Staging"
-  realm: "goma"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "goma"
-    builder: "Chromium Mac Goma RBE Staging"
-  }
-}
-job {
-  id: "Chromium Mac Goma RBE Staging (dbg)"
-  realm: "goma"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "goma"
-    builder: "Chromium Mac Goma RBE Staging (dbg)"
-  }
-}
-job {
   id: "Chromium Win Goma RBE Staging"
   realm: "goma"
   buildbucket {
@@ -1837,15 +1819,6 @@
   }
 }
 job {
-  id: "Mac Builder (dbg) Goma RBE Canary (clobber)"
-  realm: "goma"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "goma"
-    builder: "Mac Builder (dbg) Goma RBE Canary (clobber)"
-  }
-}
-job {
   id: "Mac Builder (reclient compare)"
   realm: "ci"
   schedule: "@daily"
@@ -2027,15 +2000,6 @@
   }
 }
 job {
-  id: "Mac M1 Builder (dbg) Goma RBE Canary (clobber)"
-  realm: "goma"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "goma"
-    builder: "Mac M1 Builder (dbg) Goma RBE Canary (clobber)"
-  }
-}
-job {
   id: "Mac Pro FYI Release (AMD)"
   realm: "ci"
   buildbucket {
@@ -4339,15 +4303,6 @@
   }
 }
 job {
-  id: "ios-device-goma-rbe-canary-clobber"
-  realm: "goma"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "goma"
-    builder: "ios-device-goma-rbe-canary-clobber"
-  }
-}
-job {
   id: "ios-fieldtrial-rel"
   realm: "ci"
   buildbucket {
@@ -5326,15 +5281,6 @@
   }
 }
 job {
-  id: "mac-archive-rel-goma-rbe-canary"
-  realm: "goma"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "goma"
-    builder: "mac-archive-rel-goma-rbe-canary"
-  }
-}
-job {
   id: "mac-arm64-archive-rel"
   realm: "ci"
   buildbucket {
@@ -6609,20 +6555,14 @@
   triggers: "win32-updater-builder-rel"
   triggers: "Chromium Linux Goma RBE Staging"
   triggers: "Chromium Linux Goma RBE Staging (dbg)"
-  triggers: "Chromium Mac Goma RBE Staging"
-  triggers: "Chromium Mac Goma RBE Staging (dbg)"
   triggers: "Chromium Win Goma RBE Staging"
   triggers: "Linux Builder Goma RBE Canary"
-  triggers: "Mac Builder (dbg) Goma RBE Canary (clobber)"
-  triggers: "Mac M1 Builder (dbg) Goma RBE Canary (clobber)"
   triggers: "Win Builder (dbg) Goma RBE Canary"
   triggers: "Win Builder Goma RBE Canary"
   triggers: "chromeos-amd64-generic-rel-goma-rbe-canary"
   triggers: "chromeos-amd64-generic-rel-goma-rbe-staging"
-  triggers: "ios-device-goma-rbe-canary-clobber"
   triggers: "linux-archive-rel-goma-rbe-ats-canary"
   triggers: "linux-archive-rel-goma-rbe-canary"
-  triggers: "mac-archive-rel-goma-rbe-canary"
   triggers: "Comparison Linux (reclient vs reclient remote links)"
   triggers: "Comparison Linux (reclient)"
   triggers: "Comparison Linux (reclient)(CQ)"
diff --git a/infra/config/generated/testing/test_suites.pyl b/infra/config/generated/testing/test_suites.pyl
index 0e41a229..2a61b6d 100644
--- a/infra/config/generated/testing/test_suites.pyl
+++ b/infra/config/generated/testing/test_suites.pyl
@@ -2327,25 +2327,6 @@
       'content_unittests': {},
     },
 
-    'goma_mac_gtests': {
-      'base_unittests': {
-        'swarming': {
-          'dimensions': {
-            'cpu': 'x86-64',
-            'os': 'Mac-13',
-          },
-        },
-      },
-      'content_unittests': {
-        'swarming': {
-          'dimensions': {
-            'cpu': 'x86-64',
-            'os': 'Mac-13',
-          },
-        },
-      },
-    },
-
     'gpu_angle_fuchsia_unittests_isolated_scripts': {
       'angle_unittests': {
         'mixins': [
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl
index 36a865d0..dab8280 100644
--- a/infra/config/generated/testing/variants.pyl
+++ b/infra/config/generated/testing/variants.pyl
@@ -323,16 +323,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 122.0.6248.0',
+    'description': 'Run with ash-chrome version 122.0.6249.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6248.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v122.0.6248.0',
-          'revision': 'version:122.0.6248.0',
+          'location': 'lacros_version_skew_tests_v122.0.6249.0',
+          'revision': 'version:122.0.6249.0',
         },
       ],
     },
diff --git a/infra/config/lib/builder_health_indicators.star b/infra/config/lib/builder_health_indicators.star
index 1fd0956..b74f521d 100644
--- a/infra/config/lib/builder_health_indicators.star
+++ b/infra/config/lib/builder_health_indicators.star
@@ -953,20 +953,14 @@
     "goma": [
         "Chromium Linux Goma RBE Staging (dbg)",
         "Chromium Linux Goma RBE Staging",
-        "Chromium Mac Goma RBE Staging (dbg)",
-        "Chromium Mac Goma RBE Staging",
         "Chromium Win Goma RBE Staging",
         "Linux Builder Goma RBE Canary",
-        "Mac Builder (dbg) Goma RBE Canary (clobber)",
-        "Mac M1 Builder (dbg) Goma RBE Canary (clobber)",
         "Win Builder (dbg) Goma RBE Canary",
         "Win Builder Goma RBE Canary",
         "chromeos-amd64-generic-rel-goma-rbe-canary",
         "chromeos-amd64-generic-rel-goma-rbe-staging",
-        "ios-device-goma-rbe-canary-clobber",
         "linux-archive-rel-goma-rbe-ats-canary",
         "linux-archive-rel-goma-rbe-canary",
-        "mac-archive-rel-goma-rbe-canary",
     ],
     "reclient": [
         "Comparison Linux (reclient vs reclient remote links)",
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
index ba6ff43b..ec486159 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
@@ -26,6 +26,7 @@
     siso_configs = ["builder"],
     siso_enable_cloud_profiler = True,
     siso_enable_cloud_trace = True,
+    siso_enabled = True,
     siso_project = siso.project.DEFAULT_UNTRUSTED,
 )
 
@@ -98,7 +99,6 @@
         "chromium.add_one_test_shard": 10,
     },
     main_list_view = "try",
-    siso_enabled = True,
     tryjob = try_.job(),
     # TODO(crbug.com/1372179): Use orchestrator pool once overloaded test pools
     # are addressed
@@ -111,7 +111,6 @@
     name = "android-12-x64-rel-compilator",
     branch_selector = branches.selector.ANDROID_BRANCHES,
     main_list_view = "try",
-    siso_enabled = True,
 )
 
 try_.builder(
@@ -193,7 +192,6 @@
         "chromium.compilator_can_outlive_parent": 100,
     },
     main_list_view = "try",
-    siso_enabled = True,
     tryjob = try_.job(),
     # TODO(crbug.com/1372179): Use orchestrator pool once overloaded test pools
     # are addressed
@@ -205,7 +203,6 @@
     name = "android-arm64-rel-compilator",
     branch_selector = branches.selector.ANDROID_BRANCHES,
     main_list_view = "try",
-    siso_enabled = True,
 )
 
 # TODO(crbug.com/1367523): Reenable this builder once the reboot issue is resolved.
@@ -277,7 +274,6 @@
             ],
         },
     },
-    siso_enabled = True,
     tryjob = try_.job(),
 )
 
@@ -886,7 +882,6 @@
         "chromium.add_one_test_shard": 10,
     },
     main_list_view = "try",
-    siso_enabled = True,
     tryjob = try_.job(),
     # TODO(crbug.com/1372179): Use orchestrator pool once overloaded test pools
     # are addressed
@@ -901,7 +896,6 @@
     cores = 64 if settings.is_main else 32,
     contact_team_email = "clank-engprod@google.com",
     main_list_view = "try",
-    siso_enabled = True,
 )
 
 try_.builder(
@@ -989,7 +983,6 @@
     ),
     builderless = not settings.is_main,
     main_list_view = "try",
-    siso_enabled = True,
     tryjob = try_.job(),
 )
 
@@ -1017,7 +1010,6 @@
     ssd = True,
     main_list_view = "try",
     reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ,
-    siso_enabled = True,
     tryjob = try_.job(),
 )
 
@@ -1130,7 +1122,6 @@
     builderless = not settings.is_main,
     contact_team_email = "cronet-team@google.com",
     main_list_view = "try",
-    siso_enabled = True,
     tryjob = try_.job(),
 )
 
diff --git a/infra/config/subprojects/goma/consoles/chromium.goma.fyi.star b/infra/config/subprojects/goma/consoles/chromium.goma.fyi.star
index cd768ea..04f64ee2 100644
--- a/infra/config/subprojects/goma/consoles/chromium.goma.fyi.star
+++ b/infra/config/subprojects/goma/consoles/chromium.goma.fyi.star
@@ -28,26 +28,6 @@
             category = "rbe|cros|rel",
         ),
         luci.console_view_entry(
-            builder = "goma/mac-archive-rel-goma-rbe-canary",
-            category = "rbe|mac|rel",
-            short_name = "clb",
-        ),
-        luci.console_view_entry(
-            builder = "goma/Mac Builder (dbg) Goma RBE Canary (clobber)",
-            category = "rbe|mac|dbg",
-            short_name = "clb",
-        ),
-        luci.console_view_entry(
-            builder = "goma/Mac M1 Builder (dbg) Goma RBE Canary (clobber)",
-            category = "rbe|mac|dbg",
-            short_name = "m1",
-        ),
-        luci.console_view_entry(
-            builder = "goma/ios-device-goma-rbe-canary-clobber",
-            category = "rbe|ios",
-            short_name = "clb",
-        ),
-        luci.console_view_entry(
             builder = "goma/Win Builder Goma RBE Canary",
             category = "rbe|win|rel",
         ),
diff --git a/infra/config/subprojects/goma/consoles/chromium.goma.star b/infra/config/subprojects/goma/consoles/chromium.goma.star
index 8d77beea..83d150b 100644
--- a/infra/config/subprojects/goma/consoles/chromium.goma.star
+++ b/infra/config/subprojects/goma/consoles/chromium.goma.star
@@ -18,14 +18,6 @@
             category = "rbe|staging|linux|debug",
         ),
         luci.console_view_entry(
-            builder = "goma/Chromium Mac Goma RBE Staging",
-            category = "rbe|staging|mac|rel",
-        ),
-        luci.console_view_entry(
-            builder = "goma/Chromium Mac Goma RBE Staging (dbg)",
-            category = "rbe|staging|mac|debug",
-        ),
-        luci.console_view_entry(
             builder = "goma/Chromium Win Goma RBE Staging",
             category = "rbe|staging|win|rel",
         ),
diff --git a/infra/config/subprojects/goma/goma.star b/infra/config/subprojects/goma/goma.star
index 85b28c1..f18eb9b 100644
--- a/infra/config/subprojects/goma/goma.star
+++ b/infra/config/subprojects/goma/goma.star
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 load("//lib/builder_config.star", "builder_config")
-load("//lib/builders.star", "builder", "builders", "cpu", "defaults", "goma", "os", "xcode")
+load("//lib/builders.star", "builder", "builders", "cpu", "defaults", "goma", "os")
 load("//lib/gn_args.star", "gn_args")
 load("//lib/structs.star", "structs")
 
@@ -90,64 +90,6 @@
 )
 
 fyi_goma_rbe_canary_builder(
-    name = "Mac Builder (dbg) Goma RBE Canary (clobber)",
-    builder_spec = builder_config.copy_from(
-        "ci/Mac Builder (dbg)",
-        lambda spec: structs.evolve(
-            spec,
-            chromium_config = structs.extend(
-                spec.chromium_config,
-                apply_configs = [
-                    "goma_canary",
-                    "clobber",
-                ],
-            ),
-            build_gs_bucket = "chromium-fyi-archive",
-        ),
-    ),
-    gn_args = gn_args.config(
-        configs = [
-            "gpu_tests",
-            "debug_builder",
-            "goma",
-        ],
-    ),
-    cores = None,
-    os = os.MAC_DEFAULT,
-    goma_jobs = goma.jobs.J80,
-)
-
-fyi_goma_rbe_canary_builder(
-    name = "Mac M1 Builder (dbg) Goma RBE Canary (clobber)",
-    builder_spec = builder_config.copy_from(
-        "ci/Mac Builder (dbg)",
-        lambda spec: structs.evolve(
-            spec,
-            chromium_config = structs.extend(
-                spec.chromium_config,
-                apply_configs = [
-                    "goma_canary",
-                    "clobber",
-                ],
-            ),
-            build_gs_bucket = "chromium-fyi-archive",
-        ),
-    ),
-    gn_args = gn_args.config(
-        configs = [
-            "gpu_tests",
-            "debug_builder",
-            "goma",
-            "arm64",
-        ],
-    ),
-    cores = None,
-    os = os.MAC_DEFAULT,
-    cpu = cpu.ARM64,
-    goma_jobs = goma.jobs.J80,
-)
-
-fyi_goma_rbe_canary_builder(
     name = "chromeos-amd64-generic-rel-goma-rbe-canary",
     builder_spec = builder_config.copy_from(
         "ci/chromeos-amd64-generic-rel-renamed",
@@ -176,38 +118,6 @@
 )
 
 fyi_goma_rbe_canary_builder(
-    name = "ios-device-goma-rbe-canary-clobber",
-    builder_spec = builder_config.copy_from(
-        "ci/ios-device",
-        lambda spec: structs.evolve(
-            spec,
-            chromium_config = structs.extend(
-                spec.chromium_config,
-                apply_configs = [
-                    "goma_canary",
-                    "clobber",
-                ],
-            ),
-            build_gs_bucket = "chromium-fyi-archive",
-        ),
-    ),
-    gn_args = gn_args.config(
-        configs = [
-            "compile_only",
-            "ios_device",
-            "arm64",
-            "ios_google_cert",
-            "ios_disable_code_signing",
-            "release_builder",
-            "goma",
-        ],
-    ),
-    cores = None,
-    os = os.MAC_DEFAULT,
-    xcode = xcode.xcode_default,
-)
-
-fyi_goma_rbe_canary_builder(
     name = "linux-archive-rel-goma-rbe-ats-canary",
     builder_spec = builder_config.copy_from(
         "ci/linux-archive-rel",
@@ -255,33 +165,6 @@
 )
 
 fyi_goma_rbe_canary_builder(
-    name = "mac-archive-rel-goma-rbe-canary",
-    builder_spec = builder_config.copy_from(
-        "ci/mac-archive-rel",
-        lambda spec: structs.evolve(
-            spec,
-            chromium_config = structs.extend(
-                spec.chromium_config,
-                apply_configs = [
-                    "goma_canary",
-                ],
-            ),
-            build_gs_bucket = "chromium-fyi-archive",
-        ),
-    ),
-    gn_args = gn_args.config(
-        configs = [
-            "release_builder",
-            "goma",
-            "minimal_symbols",
-        ],
-    ),
-    cores = None,
-    os = os.MAC_DEFAULT,
-    goma_jobs = goma.jobs.J80,
-)
-
-fyi_goma_rbe_canary_builder(
     name = "Win Builder (dbg) Goma RBE Canary",
     builder_spec = builder_config.copy_from(
         "ci/Win Builder (dbg)",
@@ -417,64 +300,6 @@
     goma_enable_ats = True,
 )
 
-def goma_mac_builder(
-        *,
-        name,
-        cores = None,
-        os = os.MAC_DEFAULT,
-        **kwargs):
-    return goma_builder(
-        name = name,
-        goma_jobs = goma.jobs.J80,
-        cores = cores,
-        os = os,
-        **kwargs
-    )
-
-goma_mac_builder(
-    name = "Chromium Mac Goma RBE Staging",
-    builder_spec = builder_config.builder_spec(
-        gclient_config = builder_config.gclient_config(config = "chromium"),
-        chromium_config = builder_config.chromium_config(
-            config = "chromium",
-            apply_configs = [
-                "mb",
-                "goma_failfast",
-            ],
-            target_bits = 64,
-        ),
-    ),
-    gn_args = gn_args.config(
-        configs = [
-            "release_builder",
-            "goma",
-        ],
-    ),
-    goma_backend = goma.backend.RBE_STAGING,
-)
-
-goma_mac_builder(
-    name = "Chromium Mac Goma RBE Staging (dbg)",
-    builder_spec = builder_config.builder_spec(
-        gclient_config = builder_config.gclient_config(config = "chromium"),
-        chromium_config = builder_config.chromium_config(
-            config = "chromium",
-            apply_configs = [
-                "mb",
-                "goma_failfast",
-            ],
-            target_bits = 64,
-        ),
-    ),
-    gn_args = gn_args.config(
-        configs = [
-            "debug_builder",
-            "goma",
-        ],
-    ),
-    goma_backend = goma.backend.RBE_STAGING,
-)
-
 def goma_windows_builder(
         *,
         name,
diff --git a/infra/config/targets/basic_suites.star b/infra/config/targets/basic_suites.star
index 5858a73..b812aca9 100644
--- a/infra/config/targets/basic_suites.star
+++ b/infra/config/targets/basic_suites.star
@@ -2106,28 +2106,6 @@
     },
 )
 
-targets.legacy_basic_suite(
-    name = "goma_mac_gtests",
-    tests = {
-        "base_unittests": targets.legacy_test_config(
-            swarming = targets.swarming(
-                dimensions = {
-                    "cpu": "x86-64",
-                    "os": "Mac-13",
-                },
-            ),
-        ),
-        "content_unittests": targets.legacy_test_config(
-            swarming = targets.swarming(
-                dimensions = {
-                    "cpu": "x86-64",
-                    "os": "Mac-13",
-                },
-            ),
-        ),
-    },
-)
-
 # BEGIN tests which run on the GPU bots
 
 targets.legacy_basic_suite(
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json
index aeadeb58..13553001 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_v122.0.6248.0/test_ash_chrome"
+      "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome"
     ],
-    "description": "Run with ash-chrome version 122.0.6248.0",
+    "description": "Run with ash-chrome version 122.0.6249.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_v122.0.6248.0",
-          "revision": "version:122.0.6248.0"
+          "location": "lacros_version_skew_tests_v122.0.6249.0",
+          "revision": "version:122.0.6249.0"
         }
       ]
     }
diff --git a/ios/chrome/browser/crash_report/model/crash_helper.mm b/ios/chrome/browser/crash_report/model/crash_helper.mm
index 3801eae..2981006 100644
--- a/ios/chrome/browser/crash_report/model/crash_helper.mm
+++ b/ios/chrome/browser/crash_report/model/crash_helper.mm
@@ -165,8 +165,11 @@
   key.Set("yes");
 #endif
 
-  // Don't start MTFD when prewarmed, the check thread will just get confused.
-  if (!base::ios::IsApplicationPreWarmed()) {
+  if (base::ios::IsApplicationPreWarmed()) {
+    static crash_reporter::CrashKeyString<4> prewarmed_key("is_prewarmed");
+    prewarmed_key.Set("yes");
+  } else {
+    // Don't start MTFD when prewarmed, the check thread will just get confused.
     [[MainThreadFreezeDetector sharedInstance] start];
   }
 }
diff --git a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
index e073da59..c8ff7cd6 100644
--- a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
+++ b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
@@ -1032,7 +1032,7 @@
   // scenarios.
   [sceneState addAgent:[[CredentialProviderPromoSceneAgent alloc]
                            initWithPromosManager:promosManager
-                                     prefService:browserState->GetPrefs()]];
+                                     prefService:prefService]];
 
   if (IsBottomOmniboxPromoFlagEnabled(BottomOmniboxPromoType::kAppLaunch)) {
     [sceneState addAgent:[[OmniboxPositionChoiceSceneAgent alloc]
@@ -1083,8 +1083,6 @@
 // Creates and displays the initial UI in `launchMode`, performing other
 // setup and configuration as needed.
 - (void)createInitialUI:(ApplicationMode)launchMode {
-  DCHECK(self.sceneState.appState.mainBrowserState);
-
   // Set the Scene application URL loader on the URL loading browser interface
   // for the regular and incognito interfaces. This will lazily instantiate the
   // incognito interface if it isn't already created.
@@ -1182,7 +1180,9 @@
 // Notifies the Feature Engagement Tracker that an eligibility criterion has
 // been met for the default browser blue dot promo.
 - (void)notifyFETAppOpenedViaFirstParty {
-  ChromeBrowserState* browserState = self.sceneState.appState.mainBrowserState;
+  ChromeBrowserState* browserState =
+      self.sceneState.browserProviderInterface.mainBrowserProvider.browser
+          ->GetBrowserState();
   if (!browserState || browserState->IsOffTheRecord()) {
     return;
   }
@@ -1358,7 +1358,8 @@
     return NO;
   }
   if (!signin::ShouldPresentUserSigninUpgrade(
-          self.sceneState.appState.mainBrowserState,
+          self.sceneState.browserProviderInterface.mainBrowserProvider.browser
+              ->GetBrowserState(),
           version_info::GetVersion())) {
     return NO;
   }
@@ -1435,7 +1436,8 @@
 - (BOOL)isSignedIn {
   AuthenticationService* authenticationService =
       AuthenticationServiceFactory::GetForBrowserState(
-          self.sceneState.appState.mainBrowserState);
+          self.sceneState.browserProviderInterface.mainBrowserProvider.browser
+              ->GetBrowserState());
   DCHECK(authenticationService);
   DCHECK(authenticationService->initialized());
 
@@ -3397,7 +3399,8 @@
   DCHECK(self.signinCoordinator);
   AuthenticationService* authenticationService =
       AuthenticationServiceFactory::GetForBrowserState(
-          self.sceneState.appState.mainBrowserState);
+          self.sceneState.browserProviderInterface.mainBrowserProvider.browser
+              ->GetBrowserState());
   AuthenticationService::ServiceStatus statusService =
       authenticationService->GetServiceStatus();
   switch (statusService) {
@@ -3622,10 +3625,12 @@
 // Clears incognito data that is specific to iOS and won't be cleared by
 // deleting the browser state.
 - (void)clearIOSSpecificIncognitoData {
-  DCHECK(self.sceneState.appState.mainBrowserState
+  DCHECK(self.sceneState.browserProviderInterface.mainBrowserProvider.browser
+             ->GetBrowserState()
              ->HasOffTheRecordChromeBrowserState());
   ChromeBrowserState* otrBrowserState =
-      self.sceneState.appState.mainBrowserState
+      self.sceneState.browserProviderInterface.mainBrowserProvider.browser
+          ->GetBrowserState()
           ->GetOffTheRecordChromeBrowserState();
   [self.browsingDataCommandsHandler
       removeBrowsingDataForBrowserState:otrBrowserState
@@ -3748,7 +3753,8 @@
 // BrowserState must not be destroyed).
 - (BOOL)shouldDestroyAndRebuildIncognitoBrowserState {
   ChromeBrowserState* mainBrowserState =
-      self.sceneState.appState.mainBrowserState;
+      self.sceneState.browserProviderInterface.mainBrowserProvider.browser
+          ->GetBrowserState();
   if (!mainBrowserState->HasOffTheRecordChromeBrowserState()) {
     return NO;
   }
@@ -3781,7 +3787,8 @@
   [self clearIOSSpecificIncognitoData];
 
   ChromeBrowserState* mainBrowserState =
-      self.sceneState.appState.mainBrowserState;
+      self.sceneState.browserProviderInterface.mainBrowserProvider.browser
+          ->GetBrowserState();
   DCHECK(mainBrowserState->HasOffTheRecordChromeBrowserState());
   ChromeBrowserState* otrBrowserState =
       mainBrowserState->GetOffTheRecordChromeBrowserState();
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm
index 6ac7dd25..4308a614 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm
@@ -323,6 +323,13 @@
   [self broadcastIncognitoContentVisibility];
 }
 
+#pragma mark - Accessibility
+
+- (BOOL)accessibilityPerformEscape {
+  [self doneButtonTapped:self];
+  return YES;
+}
+
 #pragma mark - UIScrollViewAccessibilityDelegate
 
 - (NSString*)accessibilityScrollStatusForScrollView:(UIScrollView*)scrollView {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/tab_grid_top_toolbar.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/tab_grid_top_toolbar.h
index e5034d95..abe466b 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/tab_grid_top_toolbar.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/tab_grid_top_toolbar.h
@@ -38,7 +38,7 @@
 // selection mode. It will be used to update the buttons to use the correct
 // title (singular or plural).
 @property(nonatomic, assign) int selectedTabsCount;
-// Delegate to call when a button is pushed.
+// Delegate to call when a button is tapped.
 @property(nonatomic, weak) id<TabGridToolbarsGridDelegate> buttonsDelegate;
 
 // Sets the delegate for the searchbar.
diff --git a/ios/web/session/hash_util.h b/ios/web/session/hash_util.h
index bfca94b..6c90118 100644
--- a/ios/web/session/hash_util.h
+++ b/ios/web/session/hash_util.h
@@ -8,6 +8,7 @@
 #include <functional>
 #include <tuple>
 
+#include "base/strings/string_piece.h"
 #include "net/base/hash_value.h"
 #include "net/cert/x509_certificate.h"
 
diff --git a/ios/web_view/internal/webui/web_view_web_ui_provider.mm b/ios/web_view/internal/webui/web_view_web_ui_provider.mm
index dd44a595..7c9fd67 100644
--- a/ios/web_view/internal/webui/web_view_web_ui_provider.mm
+++ b/ios/web_view/internal/webui/web_view_web_ui_provider.mm
@@ -10,8 +10,6 @@
 #include "ios/web_view/internal/sync/web_view_sync_service_factory.h"
 #include "ios/web_view/internal/web_view_browser_state.h"
 
-#include "ios/components/webui/web_ui_provider.h"
-
 namespace web_ui {
 
 syncer::SyncService* GetSyncServiceForWebUI(web::WebUIIOS* web_ui) {
diff --git a/ios_internal b/ios_internal
index e2a8fd4..d6d14a4 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit e2a8fd4b81ae3adb0741c97e42aabe11f664bd8a
+Subproject commit d6d14a40e59c5a580be24a0c0505f4791b26c9ba
diff --git a/net/base/proxy_chain.cc b/net/base/proxy_chain.cc
index a3e861e..aaaf35c 100644
--- a/net/base/proxy_chain.cc
+++ b/net/base/proxy_chain.cc
@@ -9,6 +9,7 @@
 
 #include "base/check.h"
 #include "base/no_destructor.h"
+#include "base/ranges/algorithm.h"
 #include "net/base/proxy_server.h"
 #include "net/base/proxy_string_util.h"
 
diff --git a/net/base/proxy_chain.h b/net/base/proxy_chain.h
index ab1d5dc..a1736842 100644
--- a/net/base/proxy_chain.h
+++ b/net/base/proxy_chain.h
@@ -7,8 +7,8 @@
 
 #include <stdint.h>
 
+#include <iosfwd>
 #include <optional>
-#include <ostream>
 #include <string>
 #include <string_view>
 #include <tuple>
diff --git a/net/cert/asn1_util.cc b/net/cert/asn1_util.cc
index bfe87b3c..26de465 100644
--- a/net/cert/asn1_util.cc
+++ b/net/cert/asn1_util.cc
@@ -4,6 +4,8 @@
 
 #include "net/cert/asn1_util.h"
 
+#include <string_view>
+
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/boringssl/src/pki/input.h"
 #include "third_party/boringssl/src/pki/parse_certificate.h"
@@ -157,7 +159,7 @@
 // successful. |*out_extension_present| will be true iff the extension was
 // found. In the case where it was found, |*out_extension| will describe the
 // extension, or is undefined on parse error or if the extension is missing.
-bool ExtractExtensionWithOID(base::StringPiece cert,
+bool ExtractExtensionWithOID(std::string_view cert,
                              bssl::der::Input extension_oid,
                              bool* out_extension_present,
                              bssl::ParsedExtension* out_extension) {
@@ -191,8 +193,8 @@
 
 }  // namespace
 
-bool ExtractSubjectFromDERCert(base::StringPiece cert,
-                               base::StringPiece* subject_out) {
+bool ExtractSubjectFromDERCert(std::string_view cert,
+                               std::string_view* subject_out) {
   bssl::der::Parser parser;
   if (!SeekToSubject(bssl::der::Input(cert), &parser)) {
     return false;
@@ -204,8 +206,7 @@
   return true;
 }
 
-bool ExtractSPKIFromDERCert(base::StringPiece cert,
-                            base::StringPiece* spki_out) {
+bool ExtractSPKIFromDERCert(std::string_view cert, std::string_view* spki_out) {
   bssl::der::Parser parser;
   if (!SeekToSPKI(bssl::der::Input(cert), &parser)) {
     return false;
@@ -217,8 +218,8 @@
   return true;
 }
 
-bool ExtractSubjectPublicKeyFromSPKI(base::StringPiece spki,
-                                     base::StringPiece* spk_out) {
+bool ExtractSubjectPublicKeyFromSPKI(std::string_view spki,
+                                     std::string_view* spk_out) {
   // From RFC 5280, Section 4.1
   //   SubjectPublicKeyInfo  ::=  SEQUENCE  {
   //     algorithm            AlgorithmIdentifier,
@@ -248,7 +249,7 @@
   return true;
 }
 
-bool HasCanSignHttpExchangesDraftExtension(base::StringPiece cert) {
+bool HasCanSignHttpExchangesDraftExtension(std::string_view cert) {
   // kCanSignHttpExchangesDraftOid is the DER encoding of the OID for
   // canSignHttpExchangesDraft defined in:
   // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html
@@ -270,9 +271,9 @@
 }
 
 bool ExtractSignatureAlgorithmsFromDERCert(
-    base::StringPiece cert,
-    base::StringPiece* cert_signature_algorithm_sequence,
-    base::StringPiece* tbs_signature_algorithm_sequence) {
+    std::string_view cert,
+    std::string_view* cert_signature_algorithm_sequence,
+    std::string_view* tbs_signature_algorithm_sequence) {
   // From RFC 5280, section 4.1
   //    Certificate  ::=  SEQUENCE  {
   //      tbsCertificate       TBSCertificate,
@@ -323,14 +324,14 @@
   return true;
 }
 
-bool ExtractExtensionFromDERCert(base::StringPiece cert,
-                                 base::StringPiece extension_oid,
+bool ExtractExtensionFromDERCert(std::string_view cert,
+                                 std::string_view extension_oid,
                                  bool* out_extension_present,
                                  bool* out_extension_critical,
-                                 base::StringPiece* out_contents) {
+                                 std::string_view* out_contents) {
   *out_extension_present = false;
   *out_extension_critical = false;
-  *out_contents = base::StringPiece();
+  *out_contents = std::string_view();
 
   bssl::ParsedExtension extension;
   if (!ExtractExtensionWithOID(cert, bssl::der::Input(extension_oid),
diff --git a/net/cert/asn1_util.h b/net/cert/asn1_util.h
index e1ca60f..18efab5c 100644
--- a/net/cert/asn1_util.h
+++ b/net/cert/asn1_util.h
@@ -5,7 +5,8 @@
 #ifndef NET_CERT_ASN1_UTIL_H_
 #define NET_CERT_ASN1_UTIL_H_
 
-#include "base/strings/string_piece.h"
+#include <string_view>
+
 #include "net/base/net_export.h"
 
 namespace net::asn1 {
@@ -14,28 +15,28 @@
 // extracts the bytes of the X.501 Subject. On successful return, |subject_out|
 // is set to contain the Subject, pointing into |cert|.
 NET_EXPORT_PRIVATE bool ExtractSubjectFromDERCert(
-    base::StringPiece cert,
-    base::StringPiece* subject_out);
+    std::string_view cert,
+    std::string_view* subject_out);
 
 // ExtractSPKIFromDERCert parses the DER encoded certificate in |cert| and
 // extracts the bytes of the SubjectPublicKeyInfo. On successful return,
 // |spki_out| is set to contain the SPKI, pointing into |cert|.
-NET_EXPORT bool ExtractSPKIFromDERCert(base::StringPiece cert,
-                                       base::StringPiece* spki_out);
+NET_EXPORT bool ExtractSPKIFromDERCert(std::string_view cert,
+                                       std::string_view* spki_out);
 
 // ExtractSubjectPublicKeyFromSPKI parses the DER encoded SubjectPublicKeyInfo
 // in |spki| and extracts the bytes of the SubjectPublicKey. On successful
 // return, |spk_out| is set to contain the public key, pointing into |spki|.
 NET_EXPORT_PRIVATE bool ExtractSubjectPublicKeyFromSPKI(
-    base::StringPiece spki,
-    base::StringPiece* spk_out);
+    std::string_view spki,
+    std::string_view* spk_out);
 
 // HasCanSignHttpExchangesDraftExtension parses the DER encoded certificate
 // in |cert| and extracts the canSignHttpExchangesDraft extension
 // (https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html)
 // if present. Returns true if the extension was present, and false if
 // the extension was not present or if there was a parsing failure.
-NET_EXPORT bool HasCanSignHttpExchangesDraftExtension(base::StringPiece cert);
+NET_EXPORT bool HasCanSignHttpExchangesDraftExtension(std::string_view cert);
 
 // Extracts the two (SEQUENCE) tag-length-values for the signature
 // AlgorithmIdentifiers in a DER encoded certificate. Does not use strict
@@ -50,9 +51,9 @@
 // * |tbs_signature_algorithm_sequence| points at the TLV for
 //   TBSCertificate.algorithm.
 NET_EXPORT_PRIVATE bool ExtractSignatureAlgorithmsFromDERCert(
-    base::StringPiece cert,
-    base::StringPiece* cert_signature_algorithm_sequence,
-    base::StringPiece* tbs_signature_algorithm_sequence);
+    std::string_view cert,
+    std::string_view* cert_signature_algorithm_sequence,
+    std::string_view* tbs_signature_algorithm_sequence);
 
 // Extracts the contents of the extension (if any) with OID |extension_oid| from
 // the DER-encoded, X.509 certificate in |cert|.
@@ -62,11 +63,11 @@
 // sets |*out_extension_critical| to match the extension's "critical" flag, and
 // sets |*out_contents| to the contents of the extension (after unwrapping the
 // OCTET STRING).
-NET_EXPORT bool ExtractExtensionFromDERCert(base::StringPiece cert,
-                                            base::StringPiece extension_oid,
+NET_EXPORT bool ExtractExtensionFromDERCert(std::string_view cert,
+                                            std::string_view extension_oid,
                                             bool* out_extension_present,
                                             bool* out_extension_critical,
-                                            base::StringPiece* out_contents);
+                                            std::string_view* out_contents);
 
 }  // namespace net::asn1
 
diff --git a/net/cert/cert_verifier.cc b/net/cert/cert_verifier.cc
index 1b54e54..d3e6924 100644
--- a/net/cert/cert_verifier.cc
+++ b/net/cert/cert_verifier.cc
@@ -5,6 +5,7 @@
 #include "net/cert/cert_verifier.h"
 
 #include <algorithm>
+#include <string_view>
 #include <utility>
 
 #include "base/strings/string_util.h"
@@ -74,10 +75,10 @@
 
 CertVerifier::RequestParams::RequestParams(
     scoped_refptr<X509Certificate> certificate,
-    base::StringPiece hostname,
+    std::string_view hostname,
     int flags,
-    base::StringPiece ocsp_response,
-    base::StringPiece sct_list)
+    std::string_view ocsp_response,
+    std::string_view sct_list)
     : certificate_(std::move(certificate)),
       hostname_(hostname),
       flags_(flags),
diff --git a/net/cert/cert_verifier.h b/net/cert/cert_verifier.h
index 96b47d0..7d7ae5e5c 100644
--- a/net/cert/cert_verifier.h
+++ b/net/cert/cert_verifier.h
@@ -7,11 +7,11 @@
 
 #include <memory>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/memory/scoped_refptr.h"
 #include "base/observer_list_types.h"
-#include "base/strings/string_piece.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/hash_value.h"
 #include "net/base/net_export.h"
@@ -120,10 +120,10 @@
    public:
     RequestParams();
     RequestParams(scoped_refptr<X509Certificate> certificate,
-                  base::StringPiece hostname,
+                  std::string_view hostname,
                   int flags,
-                  base::StringPiece ocsp_response,
-                  base::StringPiece sct_list);
+                  std::string_view ocsp_response,
+                  std::string_view sct_list);
     RequestParams(const RequestParams& other);
     ~RequestParams();
 
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc
index 1a3927b..2973634 100644
--- a/net/cert/cert_verify_proc.cc
+++ b/net/cert/cert_verify_proc.cc
@@ -7,6 +7,7 @@
 #include <stdint.h>
 
 #include <algorithm>
+#include <string_view>
 
 #include "base/containers/flat_set.h"
 #include "base/containers/span.h"
@@ -204,13 +205,13 @@
     return;
   }
 
-  base::StringPiece cert_der =
+  std::string_view cert_der =
       x509_util::CryptoBufferAsStringPiece(certificate.cert_buffer());
 
   // Try to get the certificate that signed |certificate|. This will run into
   // problems if the CertVerifyProc implementation doesn't return the ordered
   // certificates. If that happens the OCSP verification may be incorrect.
-  base::StringPiece issuer_der;
+  std::string_view issuer_der;
   if (certificate.intermediate_buffers().empty()) {
     if (X509Certificate::IsSelfSigned(certificate.cert_buffer())) {
       issuer_der = cert_der;
@@ -274,8 +275,8 @@
 [[nodiscard]] bool InspectSignatureAlgorithmForCert(
     const CRYPTO_BUFFER* cert,
     CertVerifyResult* verify_result) {
-  base::StringPiece cert_algorithm_sequence;
-  base::StringPiece tbs_algorithm_sequence;
+  std::string_view cert_algorithm_sequence;
+  std::string_view tbs_algorithm_sequence;
 
   // Extract the AlgorithmIdentifier SEQUENCEs
   if (!asn1::ExtractSignatureAlgorithmsFromDERCert(
@@ -509,7 +510,7 @@
     if (hash.tag() != HASH_VALUE_SHA256) {
       continue;
     }
-    if (!crl_set()->IsKnownInterceptionKey(base::StringPiece(
+    if (!crl_set()->IsKnownInterceptionKey(std::string_view(
             reinterpret_cast<const char*>(hash.data()), hash.size()))) {
       continue;
     }
@@ -672,7 +673,7 @@
 // CheckNameConstraints verifies that every name in |dns_names| is in one of
 // the domains specified by |domains|.
 static bool CheckNameConstraints(const std::vector<std::string>& dns_names,
-                                 base::span<const base::StringPiece> domains) {
+                                 base::span<const std::string_view> domains) {
   for (const auto& host : dns_names) {
     bool ok = false;
     url::CanonHostInfo host_info;
@@ -694,8 +695,8 @@
       DCHECK_EQ('.', domain[0]);
       if (dns_name.size() <= domain.size())
         continue;
-      base::StringPiece suffix =
-          base::StringPiece(dns_name).substr(dns_name.size() - domain.size());
+      std::string_view suffix =
+          std::string_view(dns_name).substr(dns_name.size() - domain.size());
       if (!base::EqualsCaseInsensitiveASCII(suffix, domain))
         continue;
       ok = true;
@@ -715,7 +716,7 @@
     const std::string& common_name,
     const std::vector<std::string>& dns_names,
     const std::vector<std::string>& ip_addrs) {
-  static constexpr base::StringPiece kDomainsANSSI[] = {
+  static constexpr std::string_view kDomainsANSSI[] = {
       ".fr",  // France
       ".gp",  // Guadeloupe
       ".gf",  // Guyane
@@ -731,7 +732,7 @@
       ".tf",  // Terres australes et antarctiques françaises
   };
 
-  static constexpr base::StringPiece kDomainsTest[] = {
+  static constexpr std::string_view kDomainsTest[] = {
       ".example.com",
   };
 
@@ -745,7 +746,7 @@
   //   openssl dgst -sha256 -binary | xxd -i
   static const struct PublicKeyDomainLimitation {
     SHA256HashValue public_key_hash;
-    base::span<const base::StringPiece> domains;
+    base::span<const std::string_view> domains;
   } kLimits[] = {
       // C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI,
       // CN=IGC/A/emailAddress=igca@sgdn.pm.gouv.fr
diff --git a/net/cert/cert_verify_proc_android.cc b/net/cert/cert_verify_proc_android.cc
index 8ac8541..9420f07 100644
--- a/net/cert/cert_verify_proc_android.cc
+++ b/net/cert/cert_verify_proc_android.cc
@@ -6,6 +6,7 @@
 
 #include <set>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/check_op.h"
@@ -13,7 +14,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
-#include "base/strings/string_piece.h"
 #include "crypto/sha2.h"
 #include "net/android/cert_verify_result_android.h"
 #include "net/android/network_library.h"
@@ -292,9 +292,9 @@
 
   // Save the verified chain.
   if (!verified_chain.empty()) {
-    std::vector<base::StringPiece> verified_chain_pieces(verified_chain.size());
+    std::vector<std::string_view> verified_chain_pieces(verified_chain.size());
     for (size_t i = 0; i < verified_chain.size(); i++) {
-      verified_chain_pieces[i] = base::StringPiece(verified_chain[i]);
+      verified_chain_pieces[i] = std::string_view(verified_chain[i]);
     }
     scoped_refptr<X509Certificate> verified_cert =
         X509Certificate::CreateFromDERCertChain(verified_chain_pieces);
@@ -308,7 +308,7 @@
   // roots. Walk from the end of the chain (root) to leaf, to optimize for
   // known root checks.
   for (const auto& cert : base::Reversed(verified_chain)) {
-    base::StringPiece spki_bytes;
+    std::string_view spki_bytes;
     if (!asn1::ExtractSPKIFromDERCert(cert, &spki_bytes)) {
       verify_result->cert_status |= CERT_STATUS_INVALID;
       continue;
diff --git a/net/cert/cert_verify_proc_builtin.cc b/net/cert/cert_verify_proc_builtin.cc
index 37673270..2549d4c 100644
--- a/net/cert/cert_verify_proc_builtin.cc
+++ b/net/cert/cert_verify_proc_builtin.cc
@@ -6,13 +6,13 @@
 
 #include <memory>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/memory/raw_ptr.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/strings/string_piece.h"
 #include "base/values.h"
 #include "crypto/sha2.h"
 #include "net/base/features.h"
@@ -266,8 +266,8 @@
       bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy,
       int flags,
       const CertVerifyProcTrustStore* trust_store,
-      base::StringPiece stapled_leaf_ocsp_response,
-      base::StringPiece sct_list_from_tls_extension,
+      std::string_view stapled_leaf_ocsp_response,
+      std::string_view sct_list_from_tls_extension,
       const EVRootCAMetadata* ev_metadata,
       bool* checked_revocation_for_some_path,
       base::TimeTicks deadline,
@@ -470,8 +470,8 @@
   const VerificationType verification_type_;
   const int flags_;
   raw_ptr<const CertVerifyProcTrustStore> trust_store_;
-  const base::StringPiece stapled_leaf_ocsp_response_;
-  const base::StringPiece sct_list_from_tls_extension_;
+  const std::string_view stapled_leaf_ocsp_response_;
+  const std::string_view sct_list_from_tls_extension_;
   raw_ptr<const EVRootCAMetadata> ev_metadata_;
   raw_ptr<bool> checked_revocation_for_some_path_;
   base::TimeTicks deadline_;
@@ -711,8 +711,8 @@
     VerificationType verification_type,
     bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy,
     int flags,
-    base::StringPiece ocsp_response,
-    base::StringPiece sct_list,
+    std::string_view ocsp_response,
+    std::string_view sct_list,
     const CRLSet* crl_set,
     CTVerifier* ct_verifier,
     const CTPolicyEnforcer* ct_policy_enforcer,
diff --git a/net/cert/cert_verify_proc_builtin_unittest.cc b/net/cert/cert_verify_proc_builtin_unittest.cc
index 6e5acfbf..9f51351 100644
--- a/net/cert/cert_verify_proc_builtin_unittest.cc
+++ b/net/cert/cert_verify_proc_builtin_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "net/cert/cert_verify_proc_builtin.h"
 
+#include <string_view>
+
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/numerics/safe_conversions.h"
@@ -97,7 +99,7 @@
   return base::HexEncode(rand_bytes.data(), rand_bytes.size());
 }
 
-static std::string MakeRandomPath(base::StringPiece suffix) {
+static std::string MakeRandomPath(std::string_view suffix) {
   return "/" + MakeRandomHexString(12) + std::string(suffix);
 }
 
@@ -167,8 +169,8 @@
  public:
   MOCK_CONST_METHOD5(Verify,
                      void(X509Certificate*,
-                          base::StringPiece,
-                          base::StringPiece,
+                          std::string_view,
+                          std::string_view,
                           SignedCertificateTimestampAndStatusList*,
                           const NetLogWithSource&));
 };
diff --git a/net/cert/cert_verify_proc_ios.cc b/net/cert/cert_verify_proc_ios.cc
index f4356c2..e788488 100644
--- a/net/cert/cert_verify_proc_ios.cc
+++ b/net/cert/cert_verify_proc_ios.cc
@@ -6,6 +6,8 @@
 
 #include <CommonCrypto/CommonDigest.h>
 
+#include <string_view>
+
 #include "base/apple/foundation_util.h"
 #include "base/apple/osstatus_logging.h"
 #include "base/apple/scoped_cftyperef.h"
@@ -249,9 +251,9 @@
       return;
     }
 
-    base::StringPiece spki_bytes;
+    std::string_view spki_bytes;
     if (!asn1::ExtractSPKIFromDERCert(
-            base::StringPiece(
+            std::string_view(
                 reinterpret_cast<const char*>(CFDataGetBytePtr(der_data.get())),
                 CFDataGetLength(der_data.get())),
             &spki_bytes)) {
@@ -422,7 +424,7 @@
   ScopedCFTypeRef<CFMutableArrayRef> sct_array_ref;
   if (!sct_list.empty()) {
     if (__builtin_available(iOS 12.1.1, *)) {
-      std::vector<base::StringPiece> decoded_sct_list;
+      std::vector<std::string_view> decoded_sct_list;
       if (ct::DecodeSCTList(sct_list, &decoded_sct_list)) {
         sct_array_ref.reset(CFArrayCreateMutable(kCFAllocatorDefault,
                                                  decoded_sct_list.size(),
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index 2c6f5350..27de8cf 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -5,6 +5,7 @@
 #include "net/cert/cert_verify_proc.h"
 
 #include <memory>
+#include <string_view>
 #include <vector>
 
 #include "base/files/file_path.h"
@@ -17,7 +18,6 @@
 #include "base/rand_util.h"
 #include "base/ranges/algorithm.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
@@ -532,7 +532,7 @@
   //
   // This way CRLSet coverage will be sufficient for EV revocation checking,
   // so this test does not depend on online revocation checking.
-  base::StringPiece spki;
+  std::string_view spki;
   ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(
       x509_util::CryptoBufferAsStringPiece(root->GetCertBuffer()), &spki));
   SHA256HashValue spki_sha256;
@@ -803,7 +803,7 @@
   base::FilePath certs_dir =
       GetTestNetDataDirectory().AppendASCII("parse_certificate_unittest");
   bssl::UniquePtr<CRYPTO_BUFFER> bad_cert =
-      x509_util::CreateCryptoBuffer(base::StringPiece("invalid"));
+      x509_util::CreateCryptoBuffer(std::string_view("invalid"));
   ASSERT_TRUE(bad_cert);
 
   scoped_refptr<X509Certificate> ok_cert(
@@ -1132,7 +1132,7 @@
   // |algorithm|. Note this violates the constness of StringPiece.
   [[nodiscard]] static bool SetAlgorithmSequence(
       bssl::DigestAlgorithm algorithm,
-      base::StringPiece* algorithm_sequence) {
+      std::string_view* algorithm_sequence) {
     // This string of bytes is the full SEQUENCE for an AlgorithmIdentifier.
     std::vector<uint8_t> replacement_sequence;
     switch (algorithm) {
@@ -1172,16 +1172,18 @@
 
   // Locate the serial number bytes.
   [[nodiscard]] static bool ExtractSerialNumberFromDERCert(
-      base::StringPiece der_cert,
-      base::StringPiece* serial_value) {
+      std::string_view der_cert,
+      std::string_view* serial_value) {
     bssl::der::Parser parser((bssl::der::Input(der_cert)));
     bssl::der::Parser certificate;
-    if (!parser.ReadSequence(&certificate))
+    if (!parser.ReadSequence(&certificate)) {
       return false;
+    }
 
     bssl::der::Parser tbs_certificate;
-    if (!certificate.ReadSequence(&tbs_certificate))
+    if (!certificate.ReadSequence(&tbs_certificate)) {
       return false;
+    }
 
     bool unused;
     if (!tbs_certificate.SkipOptionalTag(
@@ -1223,15 +1225,15 @@
 
     // Parse the certificate and identify the locations of interest within
     // |cert_der|.
-    base::StringPiece cert_algorithm_sequence;
-    base::StringPiece tbs_algorithm_sequence;
+    std::string_view cert_algorithm_sequence;
+    std::string_view tbs_algorithm_sequence;
     if (!asn1::ExtractSignatureAlgorithmsFromDERCert(
             cert_der, &cert_algorithm_sequence, &tbs_algorithm_sequence)) {
       ADD_FAILURE() << "Failed parsing certificate algorithms";
       return nullptr;
     }
 
-    base::StringPiece serial_value;
+    std::string_view serial_value;
     if (!ExtractSerialNumberFromDERCert(cert_der, &serial_value)) {
       ADD_FAILURE() << "Failed parsing certificate serial number";
       return nullptr;
@@ -2816,7 +2818,7 @@
   }
 
   // Returns a random URL path (starting with /) that has the given suffix.
-  static std::string MakeRandomPath(base::StringPiece suffix) {
+  static std::string MakeRandomPath(std::string_view suffix) {
     return "/" + MakeRandomHexString(12) + std::string(suffix);
   }
 
diff --git a/net/cert/crl_set.cc b/net/cert/crl_set.cc
index e84f6ed..e0c1e470 100644
--- a/net/cert/crl_set.cc
+++ b/net/cert/crl_set.cc
@@ -5,10 +5,10 @@
 #include "net/cert/crl_set.h"
 
 #include <algorithm>
+#include <string_view>
 
 #include "base/base64.h"
 #include "base/json/json_reader.h"
-#include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "crypto/sha2.h"
@@ -54,7 +54,7 @@
 // ReadHeader reads the header (including length prefix) from |data| and
 // updates |data| to remove the header on return. Caller takes ownership of the
 // returned pointer.
-absl::optional<base::Value> ReadHeader(base::StringPiece* data) {
+absl::optional<base::Value> ReadHeader(std::string_view* data) {
   uint16_t header_len;
   if (data->size() < sizeof(header_len)) {
     return absl::nullopt;
@@ -67,7 +67,7 @@
     return absl::nullopt;
   }
 
-  const base::StringPiece header_bytes = data->substr(0, header_len);
+  const std::string_view header_bytes = data->substr(0, header_len);
   data->remove_prefix(header_len);
 
   absl::optional<base::Value> header =
@@ -83,7 +83,7 @@
 // currently implement.
 static const int kCurrentFileVersion = 0;
 
-bool ReadCRL(base::StringPiece* data,
+bool ReadCRL(std::string_view* data,
              std::string* out_parent_spki_hash,
              std::vector<std::string>* out_serials) {
   if (data->size() < crypto::kSHA256Length)
@@ -203,7 +203,7 @@
 CRLSet::~CRLSet() = default;
 
 // static
-bool CRLSet::Parse(base::StringPiece data, scoped_refptr<CRLSet>* out_crl_set) {
+bool CRLSet::Parse(std::string_view data, scoped_refptr<CRLSet>* out_crl_set) {
   TRACE_EVENT0(NetTracingCategory(), "CRLSet::Parse");
 // Other parts of Chrome assume that we're little endian, so we don't lose
 // anything by doing this.
@@ -296,15 +296,15 @@
   return true;
 }
 
-CRLSet::Result CRLSet::CheckSPKI(base::StringPiece spki_hash) const {
+CRLSet::Result CRLSet::CheckSPKI(std::string_view spki_hash) const {
   if (std::binary_search(blocked_spkis_.begin(), blocked_spkis_.end(),
                          spki_hash))
     return REVOKED;
   return GOOD;
 }
 
-CRLSet::Result CRLSet::CheckSubject(base::StringPiece encoded_subject,
-                                    base::StringPiece spki_hash) const {
+CRLSet::Result CRLSet::CheckSubject(std::string_view encoded_subject,
+                                    std::string_view spki_hash) const {
   const std::string digest(crypto::SHA256HashString(encoded_subject));
   const auto i = limited_subjects_.find(digest);
   if (i == limited_subjects_.end()) {
@@ -320,9 +320,9 @@
   return REVOKED;
 }
 
-CRLSet::Result CRLSet::CheckSerial(base::StringPiece serial_number,
-                                   base::StringPiece issuer_spki_hash) const {
-  base::StringPiece serial(serial_number);
+CRLSet::Result CRLSet::CheckSerial(std::string_view serial_number,
+                                   std::string_view issuer_spki_hash) const {
+  std::string_view serial(serial_number);
 
   if (!serial.empty() && (serial[0] & 0x80) != 0) {
     // This serial number is negative but the process which generates CRL sets
@@ -346,7 +346,7 @@
   return GOOD;
 }
 
-bool CRLSet::IsKnownInterceptionKey(base::StringPiece spki_hash) const {
+bool CRLSet::IsKnownInterceptionKey(std::string_view spki_hash) const {
   return std::binary_search(known_interception_spkis_.begin(),
                             known_interception_spkis_.end(), spki_hash);
 }
@@ -391,8 +391,8 @@
 scoped_refptr<CRLSet> CRLSet::ForTesting(
     bool is_expired,
     const SHA256HashValue* issuer_spki,
-    base::StringPiece serial_number,
-    base::StringPiece utf8_common_name,
+    std::string_view serial_number,
+    std::string_view utf8_common_name,
     const std::vector<std::string>& acceptable_spki_hashes_for_cn) {
   std::string subject_hash;
   if (!utf8_common_name.empty()) {
@@ -419,7 +419,7 @@
     }
 
     subject_hash.assign(crypto::SHA256HashString(
-        base::StringPiece(reinterpret_cast<char*>(x501_data), x501_len)));
+        std::string_view(reinterpret_cast<char*>(x501_data), x501_len)));
     OPENSSL_free(x501_data);
   }
 
diff --git a/net/cert/crl_set.h b/net/cert/crl_set.h
index 134e773..40c4b3e 100644
--- a/net/cert/crl_set.h
+++ b/net/cert/crl_set.h
@@ -9,12 +9,12 @@
 #include <stdint.h>
 
 #include <string>
+#include <string_view>
 #include <unordered_map>
 #include <utility>
 #include <vector>
 
 #include "base/memory/ref_counted.h"
-#include "base/strings/string_piece.h"
 #include "net/base/hash_value.h"
 #include "net/base/net_export.h"
 
@@ -33,11 +33,11 @@
 
   // Parses the bytes in |data| and, on success, puts a new CRLSet in
   // |out_crl_set| and returns true.
-  static bool Parse(base::StringPiece data, scoped_refptr<CRLSet>* out_crl_set);
+  static bool Parse(std::string_view data, scoped_refptr<CRLSet>* out_crl_set);
 
   // CheckSPKI checks whether the given SPKI has been listed as blocked.
   //   spki_hash: the SHA256 of the SubjectPublicKeyInfo of the certificate.
-  Result CheckSPKI(base::StringPiece spki_hash) const;
+  Result CheckSPKI(std::string_view spki_hash) const;
 
   // CheckSerial returns the information contained in the set for a given
   // certificate:
@@ -45,19 +45,19 @@
   //       value
   //   issuer_spki_hash: the SHA256 of the SubjectPublicKeyInfo of the CRL
   //       signer
-  Result CheckSerial(base::StringPiece serial_number,
-                     base::StringPiece issuer_spki_hash) const;
+  Result CheckSerial(std::string_view serial_number,
+                     std::string_view issuer_spki_hash) const;
 
   // CheckSubject returns the information contained in the set for a given,
   // encoded subject name and SPKI SHA-256 hash. The subject name is encoded as
   // a DER X.501 Name (see https://tools.ietf.org/html/rfc5280#section-4.1.2.4).
-  Result CheckSubject(base::StringPiece asn1_subject,
-                      base::StringPiece spki_hash) const;
+  Result CheckSubject(std::string_view asn1_subject,
+                      std::string_view spki_hash) const;
 
   // Returns true if |spki_hash|, the SHA256 of the SubjectPublicKeyInfo,
   // is known to be used for interception by a party other than the device
   // or machine owner.
-  bool IsKnownInterceptionKey(base::StringPiece spki_hash) const;
+  bool IsKnownInterceptionKey(std::string_view spki_hash) const;
 
   // IsExpired returns true iff the current time is past the NotAfter time
   // specified in the CRLSet.
@@ -98,8 +98,8 @@
   static scoped_refptr<CRLSet> ForTesting(
       bool is_expired,
       const SHA256HashValue* issuer_spki,
-      base::StringPiece serial_number,
-      base::StringPiece utf8_common_name,
+      std::string_view serial_number,
+      std::string_view utf8_common_name,
       const std::vector<std::string>& acceptable_spki_hashes_for_cn);
 
  private:
diff --git a/net/cert/crl_set_unittest.cc b/net/cert/crl_set_unittest.cc
index 11c2067..27d2bd7 100644
--- a/net/cert/crl_set_unittest.cc
+++ b/net/cert/crl_set_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "net/cert/crl_set.h"
 
+#include <string_view>
+
 #include "base/files/file_util.h"
 #include "crypto/sha2.h"
 #include "net/cert/asn1_util.h"
@@ -78,8 +80,8 @@
 };
 
 TEST(CRLSetTest, Parse) {
-  base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet),
-                      sizeof(kGIACRLSet));
+  std::string_view s(reinterpret_cast<const char*>(kGIACRLSet),
+                     sizeof(kGIACRLSet));
   scoped_refptr<CRLSet> set;
   EXPECT_TRUE(CRLSet::Parse(s, &set));
   ASSERT_TRUE(set.get() != nullptr);
@@ -109,8 +111,8 @@
 }
 
 TEST(CRLSetTest, BlockedSPKIs) {
-  base::StringPiece s(reinterpret_cast<const char*>(kBlockedSPKICRLSet),
-                      sizeof(kBlockedSPKICRLSet));
+  std::string_view s(reinterpret_cast<const char*>(kBlockedSPKICRLSet),
+                     sizeof(kBlockedSPKICRLSet));
   scoped_refptr<CRLSet> set;
   EXPECT_TRUE(CRLSet::Parse(s, &set));
   ASSERT_TRUE(set.get() != nullptr);
@@ -131,8 +133,8 @@
   // include the block list.
   scoped_refptr<CRLSet> set1 = CRLSet::BuiltinCRLSet();
   ASSERT_TRUE(set1);
-  base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet),
-                      sizeof(kGIACRLSet));
+  std::string_view s(reinterpret_cast<const char*>(kGIACRLSet),
+                     sizeof(kGIACRLSet));
   scoped_refptr<CRLSet> set2;
   EXPECT_TRUE(CRLSet::Parse(s, &set2));
   ASSERT_TRUE(set2);
@@ -149,7 +151,7 @@
     scoped_refptr<X509Certificate> diginotar_cert =
         ImportCertFromFile(certs_dir, kDigiNotarFilenames[i]);
     ASSERT_TRUE(diginotar_cert);
-    base::StringPiece spki;
+    std::string_view spki;
     ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(
         x509_util::CryptoBufferAsStringPiece(diginotar_cert->cert_buffer()),
         &spki));
@@ -175,15 +177,15 @@
   scoped_refptr<X509Certificate> root = CreateCertificateChainFromFile(
       GetTestCertsDirectory(), "root_ca_cert.pem",
       X509Certificate::FORMAT_AUTO);
-  base::StringPiece root_der =
+  std::string_view root_der =
       net::x509_util::CryptoBufferAsStringPiece(root->cert_buffer());
 
-  base::StringPiece spki;
+  std::string_view spki;
   ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(root_der, &spki));
   SHA256HashValue spki_sha256;
   crypto::SHA256HashString(spki, spki_sha256.data, sizeof(spki_sha256.data));
 
-  base::StringPiece subject;
+  std::string_view subject;
   ASSERT_TRUE(asn1::ExtractSubjectFromDERCert(root_der, &subject));
 
   // Unrelated subjects are unaffected.
@@ -194,13 +196,13 @@
   EXPECT_EQ(CRLSet::REVOKED,
             set->CheckSubject(
                 subject,
-                base::StringPiece(reinterpret_cast<const char*>(kGIASPKISHA256),
-                                  sizeof(kGIASPKISHA256))));
+                std::string_view(reinterpret_cast<const char*>(kGIASPKISHA256),
+                                 sizeof(kGIASPKISHA256))));
 
   // When used with the correct hash, that subject should be accepted.
   EXPECT_EQ(CRLSet::GOOD,
             set->CheckSubject(
-                subject, base::StringPiece(
+                subject, std::string_view(
                              reinterpret_cast<const char*>(spki_sha256.data),
                              sizeof(spki_sha256.data))));
 }
@@ -208,8 +210,8 @@
 TEST(CRLSetTest, Expired) {
   // This CRLSet has an expiry value set to one second past midnight, 1st Jan,
   // 1970.
-  base::StringPiece s(reinterpret_cast<const char*>(kExpiredCRLSet),
-                      sizeof(kExpiredCRLSet));
+  std::string_view s(reinterpret_cast<const char*>(kExpiredCRLSet),
+                     sizeof(kExpiredCRLSet));
   scoped_refptr<CRLSet> set;
   EXPECT_TRUE(CRLSet::Parse(s, &set));
   ASSERT_TRUE(set.get() != nullptr);
diff --git a/net/cert/ct_log_response_parser.cc b/net/cert/ct_log_response_parser.cc
index 895738d4..7ffdd50 100644
--- a/net/cert/ct_log_response_parser.cc
+++ b/net/cert/ct_log_response_parser.cc
@@ -5,11 +5,11 @@
 #include "net/cert/ct_log_response_parser.h"
 
 #include <memory>
+#include <string_view>
 
 #include "base/base64.h"
 #include "base/json/json_value_converter.h"
 #include "base/logging.h"
-#include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "net/cert/ct_serialization.h"
@@ -31,17 +31,17 @@
       base::JSONValueConverter<JsonSignedTreeHead>* converted);
 };
 
-bool ConvertSHA256RootHash(base::StringPiece s, std::string* result) {
+bool ConvertSHA256RootHash(std::string_view s, std::string* result) {
   return base::Base64Decode(s, result) && result->size() == kSthRootHashLength;
 }
 
-bool ConvertTreeHeadSignature(base::StringPiece s, DigitallySigned* result) {
+bool ConvertTreeHeadSignature(std::string_view s, DigitallySigned* result) {
   std::string tree_head_signature;
   if (!base::Base64Decode(s, &tree_head_signature)) {
     return false;
   }
 
-  base::StringPiece sp(tree_head_signature);
+  std::string_view sp(tree_head_signature);
   return DecodeDigitallySigned(&sp, result);
 }
 
diff --git a/net/cert/ct_log_response_parser.h b/net/cert/ct_log_response_parser.h
index eb31c91..fde592f7 100644
--- a/net/cert/ct_log_response_parser.h
+++ b/net/cert/ct_log_response_parser.h
@@ -8,7 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 
 namespace base {
diff --git a/net/cert/ct_log_response_parser_unittest.cc b/net/cert/ct_log_response_parser_unittest.cc
index ee2f35fb..79ae4df 100644
--- a/net/cert/ct_log_response_parser_unittest.cc
+++ b/net/cert/ct_log_response_parser_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include <string>
+#include <string_view>
 
 #include "base/base64.h"
 #include "base/json/json_reader.h"
@@ -68,7 +69,7 @@
 
   std::string too_long_hash;
   base::Base64Decode(
-      base::StringPiece("/WHFMgXtI/umKKuACJIN0Bb73TcILm9WkeU6qszvoArK\n"),
+      std::string_view("/WHFMgXtI/umKKuACJIN0Bb73TcILm9WkeU6qszvoArK\n"),
       &too_long_hash);
   absl::optional<base::Value> too_long_hash_json =
       base::JSONReader::Read(CreateSignedTreeHeadJsonString(
@@ -78,7 +79,7 @@
 
   std::string too_short_hash;
   base::Base64Decode(
-      base::StringPiece("/WHFMgXtI/umKKuACJIN0Bb73TcILm9WkeU6qszvoA==\n"),
+      std::string_view("/WHFMgXtI/umKKuACJIN0Bb73TcILm9WkeU6qszvoA==\n"),
       &too_short_hash);
   absl::optional<base::Value> too_short_hash_json =
       base::JSONReader::Read(CreateSignedTreeHeadJsonString(
diff --git a/net/cert/ct_log_verifier.cc b/net/cert/ct_log_verifier.cc
index 9b41df2..365071c 100644
--- a/net/cert/ct_log_verifier.cc
+++ b/net/cert/ct_log_verifier.cc
@@ -7,11 +7,11 @@
 #include <string.h>
 
 #include <bit>
+#include <string_view>
 #include <vector>
 
 #include "base/logging.h"
 #include "base/notreached.h"
-#include "base/strings/string_piece.h"
 #include "crypto/openssl_util.h"
 #include "crypto/sha2.h"
 #include "net/cert/ct_log_verifier_util.h"
@@ -57,7 +57,7 @@
 
 // static
 scoped_refptr<const CTLogVerifier> CTLogVerifier::Create(
-    base::StringPiece public_key,
+    std::string_view public_key,
     std::string description) {
   auto result = base::WrapRefCounted(new CTLogVerifier(std::move(description)));
   if (!result->Init(public_key))
@@ -146,7 +146,7 @@
 
   // 1. If "first" is an exact power of 2, then prepend "first_hash" to the
   // "consistency_path" array.
-  base::StringPiece first_proof_node = old_tree_hash;
+  std::string_view first_proof_node = old_tree_hash;
   auto iter = proof.nodes.begin();
   if (!std::has_single_bit(proof.first_tree_size)) {
     if (iter == proof.nodes.end())
@@ -264,7 +264,7 @@
 
 CTLogVerifier::~CTLogVerifier() = default;
 
-bool CTLogVerifier::Init(base::StringPiece public_key) {
+bool CTLogVerifier::Init(std::string_view public_key) {
   crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
 
   CBS cbs;
@@ -301,8 +301,8 @@
   return true;
 }
 
-bool CTLogVerifier::VerifySignature(base::StringPiece data_to_sign,
-                                    base::StringPiece signature) const {
+bool CTLogVerifier::VerifySignature(std::string_view data_to_sign,
+                                    std::string_view signature) const {
   crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
 
   const EVP_MD* hash_alg = GetEvpAlg(hash_algorithm_);
diff --git a/net/cert/ct_log_verifier.h b/net/cert/ct_log_verifier.h
index 363cfb82..bd38684 100644
--- a/net/cert/ct_log_verifier.h
+++ b/net/cert/ct_log_verifier.h
@@ -6,10 +6,10 @@
 #define NET_CERT_CT_LOG_VERIFIER_H_
 
 #include <string>
+#include <string_view>
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 #include "net/cert/signed_certificate_timestamp.h"
 #include "third_party/boringssl/src/include/openssl/base.h"
@@ -35,7 +35,7 @@
   // using |public_key|, which is a DER-encoded SubjectPublicKeyInfo.
   // If |public_key| refers to an unsupported public key, returns NULL.
   // |description| is a textual description of the log.
-  static scoped_refptr<const CTLogVerifier> Create(base::StringPiece public_key,
+  static scoped_refptr<const CTLogVerifier> Create(std::string_view public_key,
                                                    std::string description);
 
   // Returns the log's key ID (RFC6962, Section 3.2)
@@ -75,13 +75,13 @@
   ~CTLogVerifier();
 
   // Performs crypto-library specific initialization.
-  bool Init(base::StringPiece public_key);
+  bool Init(std::string_view public_key);
 
   // Performs the underlying verification using the selected public key. Note
   // that |signature| contains the raw signature data (eg: without any
   // DigitallySigned struct encoding).
-  bool VerifySignature(base::StringPiece data_to_sign,
-                       base::StringPiece signature) const;
+  bool VerifySignature(std::string_view data_to_sign,
+                       std::string_view signature) const;
 
   // Returns true if the signature and hash algorithms in |signature|
   // match those of the log
diff --git a/net/cert/ct_objects_extractor.cc b/net/cert/ct_objects_extractor.cc
index d6aabe93..aae1f2f 100644
--- a/net/cert/ct_objects_extractor.cc
+++ b/net/cert/ct_objects_extractor.cc
@@ -6,9 +6,10 @@
 
 #include <string.h>
 
+#include <string_view>
+
 #include "base/hash/sha1.h"
 #include "base/logging.h"
-#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "crypto/sha2.h"
 #include "net/cert/asn1_util.h"
@@ -170,13 +171,13 @@
                                 const CRYPTO_BUFFER* issuer,
                                 const std::string& cert_serial_number,
                                 CBS* out_single_response) {
-  base::StringPiece issuer_spki;
+  std::string_view issuer_spki;
   if (!asn1::ExtractSPKIFromDERCert(
           x509_util::CryptoBufferAsStringPiece(issuer), &issuer_spki))
     return false;
 
   // In OCSP, only the key itself is under hash.
-  base::StringPiece issuer_spk;
+  std::string_view issuer_spk;
   if (!asn1::ExtractSubjectPublicKeyFromSPKI(issuer_spki, &issuer_spk))
     return false;
 
@@ -317,7 +318,7 @@
   bssl::UniquePtr<uint8_t> scoped_new_tbs_cert_der(new_tbs_cert_der);
 
   // Extract the issuer's public key.
-  base::StringPiece issuer_key;
+  std::string_view issuer_key;
   if (!asn1::ExtractSPKIFromDERCert(
           x509_util::CryptoBufferAsStringPiece(issuer), &issuer_key)) {
     return false;
@@ -345,7 +346,7 @@
 
 bool ExtractSCTListFromOCSPResponse(const CRYPTO_BUFFER* issuer,
                                     const std::string& cert_serial_number,
-                                    base::StringPiece ocsp_response,
+                                    std::string_view ocsp_response,
                                     std::string* sct_list) {
   // The input is an bssl::OCSPResponse. See RFC2560, section 4.2.1. The SCT
   // list is in the extensions field of the SingleResponse which matches the
diff --git a/net/cert/ct_objects_extractor.h b/net/cert/ct_objects_extractor.h
index 3ca4dbe..2da6953d 100644
--- a/net/cert/ct_objects_extractor.h
+++ b/net/cert/ct_objects_extractor.h
@@ -6,8 +6,8 @@
 #define NET_CERT_CT_OBJECTS_EXTRACTOR_H_
 
 #include <string>
+#include <string_view>
 
-#include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 #include "net/cert/x509_certificate.h"
 
@@ -57,7 +57,7 @@
 NET_EXPORT_PRIVATE bool ExtractSCTListFromOCSPResponse(
     const CRYPTO_BUFFER* issuer,
     const std::string& cert_serial_number,
-    base::StringPiece ocsp_response,
+    std::string_view ocsp_response,
     std::string* sct_list);
 
 }  // namespace net::ct
diff --git a/net/cert/ct_objects_extractor_unittest.cc b/net/cert/ct_objects_extractor_unittest.cc
index 2d67c15..f8a5bb4 100644
--- a/net/cert/ct_objects_extractor_unittest.cc
+++ b/net/cert/ct_objects_extractor_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "net/cert/ct_objects_extractor.h"
 
+#include <string_view>
+
 #include "base/files/file_path.h"
 #include "net/cert/ct_log_verifier.h"
 #include "net/cert/ct_serialization.h"
@@ -39,7 +41,7 @@
     std::string sct_list;
     ASSERT_TRUE(ExtractEmbeddedSCTList(cert->cert_buffer(), &sct_list));
 
-    std::vector<base::StringPiece> parsed_scts;
+    std::vector<std::string_view> parsed_scts;
     // Make sure the SCT list can be decoded properly
     ASSERT_TRUE(DecodeSCTList(sct_list, &parsed_scts));
     ASSERT_EQ(1u, parsed_scts.size());
diff --git a/net/cert/ct_serialization.cc b/net/cert/ct_serialization.cc
index 56fe9a9..3d198de 100644
--- a/net/cert/ct_serialization.cc
+++ b/net/cert/ct_serialization.cc
@@ -4,6 +4,8 @@
 
 #include "net/cert/ct_serialization.h"
 
+#include <string_view>
+
 #include "base/logging.h"
 #include "base/numerics/checked_math.h"
 #include "crypto/sha2.h"
@@ -28,8 +30,8 @@
 // |max_list_length| contains the overall length of the encoded list.
 // |max_item_length| contains the maximum length of a single item.
 // On success, returns true and updates |*out| with the encoded list.
-bool ReadSCTList(CBS* in, std::vector<base::StringPiece>* out) {
-  std::vector<base::StringPiece> result;
+bool ReadSCTList(CBS* in, std::vector<std::string_view>* out) {
+  std::vector<std::string_view> result;
 
   CBS sct_list_data;
 
@@ -175,7 +177,7 @@
   return true;
 }
 
-bool DecodeDigitallySigned(base::StringPiece* input, DigitallySigned* output) {
+bool DecodeDigitallySigned(std::string_view* input, DigitallySigned* output) {
   CBS input_cbs;
   CBS_init(&input_cbs, reinterpret_cast<const uint8_t*>(input->data()),
            input->size());
@@ -300,9 +302,9 @@
   return true;
 }
 
-bool DecodeSCTList(base::StringPiece input,
-                   std::vector<base::StringPiece>* output) {
-  std::vector<base::StringPiece> result;
+bool DecodeSCTList(std::string_view input,
+                   std::vector<std::string_view>* output) {
+  std::vector<std::string_view> result;
   CBS input_cbs;
   CBS_init(&input_cbs, reinterpret_cast<const uint8_t*>(input.data()),
            input.size());
@@ -316,7 +318,7 @@
 }
 
 bool DecodeSignedCertificateTimestamp(
-    base::StringPiece* input,
+    std::string_view* input,
     scoped_refptr<SignedCertificateTimestamp>* output) {
   auto result = base::MakeRefCounted<SignedCertificateTimestamp>();
   uint8_t version;
diff --git a/net/cert/ct_serialization.h b/net/cert/ct_serialization.h
index edfc8ef..fd43854 100644
--- a/net/cert/ct_serialization.h
+++ b/net/cert/ct_serialization.h
@@ -6,10 +6,10 @@
 #define NET_CERT_CT_SERIALIZATION_H_
 
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/memory/scoped_refptr.h"
-#include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "net/base/net_export.h"
 
@@ -31,7 +31,7 @@
 // Reads and decodes a DigitallySigned object from |input|.
 // The bytes read from |input| are discarded (i.e. |input|'s prefix removed)
 // Returns true and fills |output| if all fields can be read, false otherwise.
-NET_EXPORT_PRIVATE bool DecodeDigitallySigned(base::StringPiece* input,
+NET_EXPORT_PRIVATE bool DecodeDigitallySigned(std::string_view* input,
                                               DigitallySigned* output);
 
 // Encodes the |input| SignedEntryData to |output|. Returns true if the entry
@@ -75,14 +75,14 @@
 // Returns true if the list could be read and decoded successfully, false
 // otherwise (note that the validity of each individual SCT should be checked
 // separately).
-NET_EXPORT_PRIVATE bool DecodeSCTList(base::StringPiece input,
-                                      std::vector<base::StringPiece>* output);
+NET_EXPORT_PRIVATE bool DecodeSCTList(std::string_view input,
+                                      std::vector<std::string_view>* output);
 
 // Decodes a single SCT from |input| to |output|.
 // Returns true if all fields in the SCT could be read and decoded, false
 // otherwise.
 NET_EXPORT_PRIVATE bool DecodeSignedCertificateTimestamp(
-    base::StringPiece* input,
+    std::string_view* input,
     scoped_refptr<ct::SignedCertificateTimestamp>* output);
 
 // Serializes a Signed Certificate Timestamp (SCT) into |output|.
diff --git a/net/cert/ct_serialization_unittest.cc b/net/cert/ct_serialization_unittest.cc
index 7d4fde49..01f6ab9 100644
--- a/net/cert/ct_serialization_unittest.cc
+++ b/net/cert/ct_serialization_unittest.cc
@@ -5,6 +5,7 @@
 #include "net/cert/ct_serialization.h"
 
 #include <string>
+#include <string_view>
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -34,7 +35,7 @@
 };
 
 TEST_F(CtSerializationTest, DecodesDigitallySigned) {
-  base::StringPiece digitally_signed(test_digitally_signed_);
+  std::string_view digitally_signed(test_digitally_signed_);
   ct::DigitallySigned parsed;
 
   ASSERT_TRUE(ct::DecodeDigitallySigned(&digitally_signed, &parsed));
@@ -58,8 +59,8 @@
 
 
 TEST_F(CtSerializationTest, FailsToDecodePartialDigitallySigned) {
-  base::StringPiece digitally_signed(test_digitally_signed_);
-  base::StringPiece partial_digitally_signed(
+  std::string_view digitally_signed(test_digitally_signed_);
+  std::string_view partial_digitally_signed(
       digitally_signed.substr(0, test_digitally_signed_.size() - 5));
   ct::DigitallySigned parsed;
 
@@ -137,8 +138,8 @@
 
 TEST_F(CtSerializationTest, DecodesSCTList) {
   // Two items in the list: "abc", "def"
-  base::StringPiece encoded("\x0\xa\x0\x3\x61\x62\x63\x0\x3\x64\x65\x66", 12);
-  std::vector<base::StringPiece> decoded;
+  std::string_view encoded("\x0\xa\x0\x3\x61\x62\x63\x0\x3\x64\x65\x66", 12);
+  std::vector<std::string_view> decoded;
 
   ASSERT_TRUE(ct::DecodeSCTList(encoded, &decoded));
   ASSERT_STREQ("abc", decoded[0].data());
@@ -147,15 +148,15 @@
 
 TEST_F(CtSerializationTest, FailsDecodingInvalidSCTList) {
   // A list with one item that's too short
-  base::StringPiece encoded("\x0\xa\x0\x3\x61\x62\x63\x0\x5\x64\x65\x66", 12);
-  std::vector<base::StringPiece> decoded;
+  std::string_view encoded("\x0\xa\x0\x3\x61\x62\x63\x0\x5\x64\x65\x66", 12);
+  std::vector<std::string_view> decoded;
 
   ASSERT_FALSE(ct::DecodeSCTList(encoded, &decoded));
 }
 
 TEST_F(CtSerializationTest, EncodeSignedCertificateTimestamp) {
   std::string encoded_test_sct(ct::GetTestSignedCertificateTimestamp());
-  base::StringPiece encoded_sct(encoded_test_sct);
+  std::string_view encoded_sct(encoded_test_sct);
 
   scoped_refptr<ct::SignedCertificateTimestamp> sct;
   ASSERT_TRUE(ct::DecodeSignedCertificateTimestamp(&encoded_sct, &sct));
@@ -167,7 +168,7 @@
 
 TEST_F(CtSerializationTest, DecodesSignedCertificateTimestamp) {
   std::string encoded_test_sct(ct::GetTestSignedCertificateTimestamp());
-  base::StringPiece encoded_sct(encoded_test_sct);
+  std::string_view encoded_sct(encoded_test_sct);
 
   scoped_refptr<ct::SignedCertificateTimestamp> sct;
   ASSERT_TRUE(ct::DecodeSignedCertificateTimestamp(&encoded_sct, &sct));
@@ -184,14 +185,14 @@
 
 TEST_F(CtSerializationTest, FailsDecodingInvalidSignedCertificateTimestamp) {
   // Invalid version
-  base::StringPiece invalid_version_sct("\x2\x0", 2);
+  std::string_view invalid_version_sct("\x2\x0", 2);
   scoped_refptr<ct::SignedCertificateTimestamp> sct;
 
   ASSERT_FALSE(
       ct::DecodeSignedCertificateTimestamp(&invalid_version_sct, &sct));
 
   // Valid version, invalid length (missing data)
-  base::StringPiece invalid_length_sct("\x0\xa\xb\xc", 4);
+  std::string_view invalid_length_sct("\x0\xa\xb\xc", 4);
   ASSERT_FALSE(
       ct::DecodeSignedCertificateTimestamp(&invalid_length_sct, &sct));
 }
diff --git a/net/cert/ct_signed_certificate_timestamp_log_param.cc b/net/cert/ct_signed_certificate_timestamp_log_param.cc
index 5d3b3d4..1df166bd 100644
--- a/net/cert/ct_signed_certificate_timestamp_log_param.cc
+++ b/net/cert/ct_signed_certificate_timestamp_log_param.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <memory>
+#include <string_view>
 #include <utility>
 
 #include "base/base64.h"
@@ -21,7 +22,7 @@
 // Base64 encode the given |value| string and put it in |dict| with the
 // description |key|.
 void SetBinaryData(const char* key,
-                   base::StringPiece value,
+                   std::string_view value,
                    base::Value::Dict& dict) {
   std::string b64_value = base::Base64Encode(value);
 
@@ -80,9 +81,9 @@
 }
 
 base::Value::Dict NetLogRawSignedCertificateTimestampParams(
-    base::StringPiece embedded_scts,
-    base::StringPiece sct_list_from_ocsp,
-    base::StringPiece sct_list_from_tls_extension) {
+    std::string_view embedded_scts,
+    std::string_view sct_list_from_ocsp,
+    std::string_view sct_list_from_tls_extension) {
   base::Value::Dict dict;
 
   SetBinaryData("embedded_scts", embedded_scts, dict);
diff --git a/net/cert/ct_signed_certificate_timestamp_log_param.h b/net/cert/ct_signed_certificate_timestamp_log_param.h
index d8c814d..e149292 100644
--- a/net/cert/ct_signed_certificate_timestamp_log_param.h
+++ b/net/cert/ct_signed_certificate_timestamp_log_param.h
@@ -5,7 +5,8 @@
 #ifndef NET_CERT_CT_SIGNED_CERTIFICATE_TIMESTAMP_LOG_PARAM_H_
 #define NET_CERT_CT_SIGNED_CERTIFICATE_TIMESTAMP_LOG_PARAM_H_
 
-#include "base/strings/string_piece.h"
+#include <string_view>
+
 #include "base/values.h"
 #include "net/cert/signed_certificate_timestamp_and_status.h"
 
@@ -23,9 +24,9 @@
 // See the documentation for SIGNED_CERTIFICATE_TIMESTAMPS_RECEIVED
 // in net/log/net_log_event_type_list.h
 base::Value::Dict NetLogRawSignedCertificateTimestampParams(
-    base::StringPiece embedded_scts,
-    base::StringPiece sct_list_from_ocsp,
-    base::StringPiece sct_list_from_tls_extension);
+    std::string_view embedded_scts,
+    std::string_view sct_list_from_ocsp,
+    std::string_view sct_list_from_tls_extension);
 
 }  // namespace net
 
diff --git a/net/cert/ct_verifier.h b/net/cert/ct_verifier.h
index eaedf94..18035ed 100644
--- a/net/cert/ct_verifier.h
+++ b/net/cert/ct_verifier.h
@@ -5,7 +5,8 @@
 #ifndef NET_CERT_CT_VERIFIER_H_
 #define NET_CERT_CT_VERIFIER_H_
 
-#include "base/strings/string_piece.h"
+#include <string_view>
+
 #include "net/base/net_export.h"
 #include "net/cert/signed_certificate_timestamp_and_status.h"
 
@@ -30,8 +31,8 @@
   // empty string. |output_scts| will be cleared and filled with the SCTs
   // present, if any, along with their verification results.
   virtual void Verify(X509Certificate* cert,
-                      base::StringPiece stapled_ocsp_response,
-                      base::StringPiece sct_list_from_tls_extension,
+                      std::string_view stapled_ocsp_response,
+                      std::string_view sct_list_from_tls_extension,
                       SignedCertificateTimestampAndStatusList* output_scts,
                       const NetLogWithSource& net_log) const = 0;
 };
diff --git a/net/cert/decode_signed_certificate_timestamp_fuzzer.cc b/net/cert/decode_signed_certificate_timestamp_fuzzer.cc
index a222814..d647db96 100644
--- a/net/cert/decode_signed_certificate_timestamp_fuzzer.cc
+++ b/net/cert/decode_signed_certificate_timestamp_fuzzer.cc
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <string_view>
+
 #include "base/memory/scoped_refptr.h"
 #include "net/cert/ct_serialization.h"
 #include "net/cert/signed_certificate_timestamp.h"
@@ -14,7 +16,7 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   scoped_refptr<SignedCertificateTimestamp> sct;
-  base::StringPiece buffer(reinterpret_cast<const char*>(data), size);
+  std::string_view buffer(reinterpret_cast<const char*>(data), size);
   DecodeSignedCertificateTimestamp(&buffer, &sct);
   return 0;
 }
diff --git a/net/cert/do_nothing_ct_verifier.cc b/net/cert/do_nothing_ct_verifier.cc
index 8697172..95c49d9 100644
--- a/net/cert/do_nothing_ct_verifier.cc
+++ b/net/cert/do_nothing_ct_verifier.cc
@@ -4,6 +4,8 @@
 
 #include "net/cert/do_nothing_ct_verifier.h"
 
+#include <string_view>
+
 #include "net/base/net_errors.h"
 
 namespace net {
@@ -13,8 +15,8 @@
 
 void DoNothingCTVerifier::Verify(
     X509Certificate* cert,
-    base::StringPiece stapled_ocsp_response,
-    base::StringPiece sct_list_from_tls_extension,
+    std::string_view stapled_ocsp_response,
+    std::string_view sct_list_from_tls_extension,
     SignedCertificateTimestampAndStatusList* output_scts,
     const NetLogWithSource& net_log) const {
   output_scts->clear();
diff --git a/net/cert/do_nothing_ct_verifier.h b/net/cert/do_nothing_ct_verifier.h
index 3f62232..8c24a7ad 100644
--- a/net/cert/do_nothing_ct_verifier.h
+++ b/net/cert/do_nothing_ct_verifier.h
@@ -5,6 +5,8 @@
 #ifndef NET_CERT_DO_NOTHING_CT_VERIFIER_H_
 #define NET_CERT_DO_NOTHING_CT_VERIFIER_H_
 
+#include <string_view>
+
 #include "net/base/net_export.h"
 #include "net/cert/ct_verifier.h"
 
@@ -54,8 +56,8 @@
   ~DoNothingCTVerifier() override;
 
   void Verify(X509Certificate* cert,
-              base::StringPiece stapled_ocsp_response,
-              base::StringPiece sct_list_from_tls_extension,
+              std::string_view stapled_ocsp_response,
+              std::string_view sct_list_from_tls_extension,
               SignedCertificateTimestampAndStatusList* output_scts,
               const NetLogWithSource& net_log) const override;
 };
diff --git a/net/cert/ev_root_ca_metadata.cc b/net/cert/ev_root_ca_metadata.cc
index bcdc063..30a627f0 100644
--- a/net/cert/ev_root_ca_metadata.cc
+++ b/net/cert/ev_root_ca_metadata.cc
@@ -4,12 +4,12 @@
 
 #include "net/cert/ev_root_ca_metadata.h"
 
-#include "build/build_config.h"
+#include <string_view>
 
 #include "base/containers/contains.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
-#include "base/strings/string_piece.h"
+#include "build/build_config.h"
 #include "third_party/boringssl/src/pki/input.h"
 #if defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
 #include "third_party/boringssl/src/include/openssl/bytestring.h"
@@ -33,7 +33,7 @@
   SHA256HashValue fingerprint;
 
   // The EV policy OIDs of the root CA.
-  const base::StringPiece policy_oids[kMaxOIDsPerCA];
+  const std::string_view policy_oids[kMaxOIDsPerCA];
 };
 
 #include "net/data/ssl/chrome_root_store/chrome-ev-roots-inc.cc"
@@ -53,7 +53,7 @@
 
 namespace {
 
-std::string OIDStringToDER(base::StringPiece policy) {
+std::string OIDStringToDER(std::string_view policy) {
   uint8_t* der;
   size_t len;
   bssl::ScopedCBB cbb;
diff --git a/net/cert/internal/cert_issuer_source_aia.cc b/net/cert/internal/cert_issuer_source_aia.cc
index e3cbaf5..2a268e7 100644
--- a/net/cert/internal/cert_issuer_source_aia.cc
+++ b/net/cert/internal/cert_issuer_source_aia.cc
@@ -4,9 +4,10 @@
 
 #include "net/cert/internal/cert_issuer_source_aia.h"
 
+#include <string_view>
+
 #include "base/containers/span.h"
 #include "base/logging.h"
-#include "base/strings/string_piece.h"
 #include "net/cert/cert_net_fetcher.h"
 #include "net/cert/x509_util.h"
 #include "third_party/boringssl/src/pki/cert_errors.h"
@@ -70,7 +71,7 @@
 bool ParseCertFromPem(const uint8_t* data,
                       size_t length,
                       bssl::ParsedCertificateList* results) {
-  base::StringPiece data_strpiece(reinterpret_cast<const char*>(data), length);
+  std::string_view data_strpiece(reinterpret_cast<const char*>(data), length);
 
   bssl::PEMTokenizer pem_tokenizer(data_strpiece, {"CERTIFICATE"});
   if (!pem_tokenizer.GetNext())
diff --git a/net/cert/internal/cert_issuer_source_aia.h b/net/cert/internal/cert_issuer_source_aia.h
index 8853e67..a06b20e 100644
--- a/net/cert/internal/cert_issuer_source_aia.h
+++ b/net/cert/internal/cert_issuer_source_aia.h
@@ -6,7 +6,6 @@
 #define NET_CERT_INTERNAL_CERT_ISSUER_SOURCE_AIA_H_
 
 #include "base/memory/scoped_refptr.h"
-#include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 #include "third_party/boringssl/src/pki/cert_issuer_source.h"
 
diff --git a/net/cert/internal/revocation_checker.cc b/net/cert/internal/revocation_checker.cc
index 1af0d9a1..352a4c51 100644
--- a/net/cert/internal/revocation_checker.cc
+++ b/net/cert/internal/revocation_checker.cc
@@ -5,9 +5,9 @@
 #include "net/cert/internal/revocation_checker.h"
 
 #include <string>
+#include <string_view>
 
 #include "base/logging.h"
-#include "base/strings/string_piece.h"
 #include "crypto/sha2.h"
 #include "net/cert/cert_net_fetcher.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -38,7 +38,7 @@
                          size_t target_cert_index,
                          const RevocationPolicy& policy,
                          base::TimeTicks deadline,
-                         base::StringPiece stapled_ocsp_response,
+                         std::string_view stapled_ocsp_response,
                          absl::optional<int64_t> max_age_seconds,
                          CertNetFetcher* net_fetcher,
                          bssl::CertErrors* cert_errors,
@@ -284,7 +284,7 @@
     const bssl::ParsedCertificateList& certs,
     const RevocationPolicy& policy,
     base::TimeTicks deadline,
-    base::StringPiece stapled_leaf_ocsp_response,
+    std::string_view stapled_leaf_ocsp_response,
     CertNetFetcher* net_fetcher,
     bssl::CertPathErrors* errors,
     bssl::OCSPVerifyResult* stapled_ocsp_verify_result) {
@@ -305,8 +305,8 @@
       continue;
 
     // TODO(eroman): Plumb stapled OCSP for non-leaf certificates from TLS?
-    base::StringPiece stapled_ocsp =
-        (i == 0) ? stapled_leaf_ocsp_response : base::StringPiece();
+    std::string_view stapled_ocsp =
+        (i == 0) ? stapled_leaf_ocsp_response : std::string_view();
 
     absl::optional<int64_t> max_age_seconds;
     if (policy.enforce_baseline_requirements) {
diff --git a/net/cert/internal/revocation_checker.h b/net/cert/internal/revocation_checker.h
index b2ba715..71cffd2 100644
--- a/net/cert/internal/revocation_checker.h
+++ b/net/cert/internal/revocation_checker.h
@@ -5,7 +5,8 @@
 #ifndef NET_CERT_INTERNAL_REVOCATION_CHECKER_H_
 #define NET_CERT_INTERNAL_REVOCATION_CHECKER_H_
 
-#include "base/strings/string_piece.h"
+#include <string_view>
+
 #include "base/time/time.h"
 #include "net/base/net_export.h"
 #include "net/cert/crl_set.h"
@@ -114,7 +115,7 @@
     const bssl::ParsedCertificateList& certs,
     const RevocationPolicy& policy,
     base::TimeTicks deadline,
-    base::StringPiece stapled_leaf_ocsp_response,
+    std::string_view stapled_leaf_ocsp_response,
     CertNetFetcher* net_fetcher,
     bssl::CertPathErrors* errors,
     bssl::OCSPVerifyResult* stapled_ocsp_verify_result);
diff --git a/net/cert/internal/revocation_checker_unittest.cc b/net/cert/internal/revocation_checker_unittest.cc
index e491b5a..2dce8d9 100644
--- a/net/cert/internal/revocation_checker_unittest.cc
+++ b/net/cert/internal/revocation_checker_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "net/cert/internal/revocation_checker.h"
 
+#include <string_view>
+
 #include "base/time/time.h"
 #include "net/cert/mock_cert_net_fetcher.h"
 #include "net/test/cert_builder.h"
@@ -59,7 +61,7 @@
     bssl::CertPathErrors errors;
     CheckValidatedChainRevocation(
         chain, policy, /*deadline=*/base::TimeTicks(),
-        /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+        /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
         &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
     EXPECT_TRUE(errors.ContainsHighSeverityErrors());
@@ -77,7 +79,7 @@
     bssl::CertPathErrors errors;
     CheckValidatedChainRevocation(
         chain, policy, /*deadline=*/base::TimeTicks(),
-        /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+        /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
         &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
     EXPECT_FALSE(errors.ContainsHighSeverityErrors());
@@ -96,7 +98,7 @@
     bssl::CertPathErrors errors;
     CheckValidatedChainRevocation(
         chain, policy, /*deadline=*/base::TimeTicks(),
-        /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+        /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
         &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
     EXPECT_FALSE(errors.ContainsHighSeverityErrors());
@@ -134,7 +136,7 @@
     bssl::CertPathErrors errors;
     CheckValidatedChainRevocation(
         chain, policy, /*deadline=*/base::TimeTicks(),
-        /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+        /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
         &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
     EXPECT_FALSE(errors.ContainsHighSeverityErrors());
@@ -150,7 +152,7 @@
     bssl::CertPathErrors errors;
     CheckValidatedChainRevocation(
         chain, policy, /*deadline=*/base::TimeTicks(),
-        /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+        /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
         &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
     EXPECT_TRUE(errors.ContainsHighSeverityErrors());
@@ -168,7 +170,7 @@
     bssl::CertPathErrors errors;
     CheckValidatedChainRevocation(
         chain, policy, /*deadline=*/base::TimeTicks(),
-        /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+        /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
         &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
     EXPECT_TRUE(errors.ContainsHighSeverityErrors());
@@ -211,7 +213,7 @@
     bssl::CertPathErrors errors;
     CheckValidatedChainRevocation(
         chain, policy, /*deadline=*/base::TimeTicks(),
-        /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+        /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
         &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
     EXPECT_TRUE(errors.ContainsHighSeverityErrors());
@@ -230,7 +232,7 @@
     bssl::CertPathErrors errors;
     CheckValidatedChainRevocation(
         chain, policy, /*deadline=*/base::TimeTicks(),
-        /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+        /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
         &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
     EXPECT_TRUE(errors.ContainsHighSeverityErrors());
@@ -264,7 +266,7 @@
     bssl::CertPathErrors errors;
     CheckValidatedChainRevocation(
         chain, policy, /*deadline=*/base::TimeTicks(),
-        /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+        /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
         &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
     EXPECT_TRUE(errors.ContainsHighSeverityErrors());
@@ -284,7 +286,7 @@
     bssl::CertPathErrors errors;
     CheckValidatedChainRevocation(
         chain, policy, /*deadline=*/base::TimeTicks(),
-        /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+        /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
         &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
     EXPECT_TRUE(errors.ContainsHighSeverityErrors());
@@ -304,7 +306,7 @@
     bssl::CertPathErrors errors;
     CheckValidatedChainRevocation(
         chain, policy, /*deadline=*/base::TimeTicks(),
-        /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+        /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
         &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
     EXPECT_FALSE(errors.ContainsHighSeverityErrors());
@@ -333,7 +335,7 @@
   bssl::CertPathErrors errors;
   CheckValidatedChainRevocation(
       chain, policy, /*deadline=*/base::TimeTicks(),
-      /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+      /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
       &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
   EXPECT_TRUE(errors.ContainsHighSeverityErrors());
@@ -399,7 +401,7 @@
   bssl::CertPathErrors errors;
   CheckValidatedChainRevocation(
       chain, policy, /*deadline=*/base::TimeTicks(),
-      /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+      /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
       &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
   // Should fail since the entire cRLDistributionPoints extension was skipped
@@ -486,7 +488,7 @@
   bssl::CertPathErrors errors;
   CheckValidatedChainRevocation(
       chain, policy, /*deadline=*/base::TimeTicks(),
-      /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+      /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
       &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
   EXPECT_FALSE(errors.ContainsHighSeverityErrors());
@@ -555,7 +557,7 @@
   bssl::CertPathErrors errors;
   CheckValidatedChainRevocation(
       chain, policy, /*deadline=*/base::TimeTicks(),
-      /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+      /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
       &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
   EXPECT_FALSE(errors.ContainsHighSeverityErrors());
@@ -656,7 +658,7 @@
   bssl::CertPathErrors errors;
   CheckValidatedChainRevocation(
       chain, policy, /*deadline=*/base::TimeTicks(),
-      /*stapled_leaf_ocsp_response=*/base::StringPiece(), mock_fetcher.get(),
+      /*stapled_leaf_ocsp_response=*/std::string_view(), mock_fetcher.get(),
       &errors, /*stapled_ocsp_verify_result=*/nullptr);
 
   EXPECT_FALSE(errors.ContainsHighSeverityErrors());
diff --git a/net/cert/internal/trust_store_win.cc b/net/cert/internal/trust_store_win.cc
index c2270a6..0c61da3 100644
--- a/net/cert/internal/trust_store_win.cc
+++ b/net/cert/internal/trust_store_win.cc
@@ -4,6 +4,8 @@
 
 #include "net/cert/internal/trust_store_win.h"
 
+#include <string_view>
+
 #include "base/hash/sha1.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -72,7 +74,7 @@
     }
   }
   for (DWORD i = 0; i < usage->cUsageIdentifier; i++) {
-    base::StringPiece eku = base::StringPiece(usage->rgpszUsageIdentifier[i]);
+    std::string_view eku = std::string_view(usage->rgpszUsageIdentifier[i]);
     if ((eku == szOID_PKIX_KP_SERVER_AUTH) ||
         (eku == szOID_ANY_ENHANCED_KEY_USAGE)) {
       return true;
diff --git a/net/cert/internal/trust_store_win_unittest.cc b/net/cert/internal/trust_store_win_unittest.cc
index 001728d..2e8bfda 100644
--- a/net/cert/internal/trust_store_win_unittest.cc
+++ b/net/cert/internal/trust_store_win_unittest.cc
@@ -5,6 +5,7 @@
 #include "net/cert/internal/trust_store_win.h"
 
 #include <memory>
+#include <string_view>
 
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
@@ -34,7 +35,7 @@
 namespace {
 
 ::testing::AssertionResult ParseCertFromFile(
-    base::StringPiece file_name,
+    std::string_view file_name,
     std::shared_ptr<const bssl::ParsedCertificate>* out_cert) {
   const scoped_refptr<X509Certificate> cert =
       ImportCertFromFile(net::GetTestCertsDirectory(), file_name);
diff --git a/net/cert/multi_log_ct_verifier.cc b/net/cert/multi_log_ct_verifier.cc
index 67fa543..08f5753 100644
--- a/net/cert/multi_log_ct_verifier.cc
+++ b/net/cert/multi_log_ct_verifier.cc
@@ -4,6 +4,7 @@
 
 #include "net/cert/multi_log_ct_verifier.h"
 
+#include <string_view>
 #include <vector>
 
 #include "base/logging.h"
@@ -70,8 +71,8 @@
 
 void MultiLogCTVerifier::Verify(
     X509Certificate* cert,
-    base::StringPiece stapled_ocsp_response,
-    base::StringPiece sct_list_from_tls_extension,
+    std::string_view stapled_ocsp_response,
+    std::string_view sct_list_from_tls_extension,
     SignedCertificateTimestampAndStatusList* output_scts,
     const NetLogWithSource& net_log) const {
   DCHECK(cert);
@@ -125,7 +126,7 @@
 }
 
 void MultiLogCTVerifier::VerifySCTs(
-    base::StringPiece encoded_sct_list,
+    std::string_view encoded_sct_list,
     const ct::SignedEntryData& expected_entry,
     ct::SignedCertificateTimestamp::Origin origin,
     X509Certificate* cert,
@@ -133,14 +134,14 @@
   if (logs_.empty())
     return;
 
-  std::vector<base::StringPiece> sct_list;
+  std::vector<std::string_view> sct_list;
 
   if (!ct::DecodeSCTList(encoded_sct_list, &sct_list))
     return;
 
-  for (std::vector<base::StringPiece>::const_iterator it = sct_list.begin();
+  for (std::vector<std::string_view>::const_iterator it = sct_list.begin();
        it != sct_list.end(); ++it) {
-    base::StringPiece encoded_sct(*it);
+    std::string_view encoded_sct(*it);
     LogSCTOriginToUMA(origin);
 
     scoped_refptr<ct::SignedCertificateTimestamp> decoded_sct;
diff --git a/net/cert/multi_log_ct_verifier.h b/net/cert/multi_log_ct_verifier.h
index 66bbd3c..f5a4ec8 100644
--- a/net/cert/multi_log_ct_verifier.h
+++ b/net/cert/multi_log_ct_verifier.h
@@ -7,9 +7,9 @@
 
 #include <map>
 #include <string>
+#include <string_view>
 
 #include "base/memory/scoped_refptr.h"
-#include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 #include "net/cert/ct_verifier.h"
 #include "net/cert/signed_certificate_timestamp.h"
@@ -37,8 +37,8 @@
 
   // CTVerifier implementation:
   void Verify(X509Certificate* cert,
-              base::StringPiece stapled_ocsp_response,
-              base::StringPiece sct_list_from_tls_extension,
+              std::string_view stapled_ocsp_response,
+              std::string_view sct_list_from_tls_extension,
               SignedCertificateTimestampAndStatusList* output_scts,
               const NetLogWithSource& net_log) const override;
 
@@ -46,7 +46,7 @@
   // Verify a list of SCTs from |encoded_sct_list| over |expected_entry|,
   // placing the verification results in |output_scts|. The SCTs in the list
   // come from |origin| (as will be indicated in the origin field of each SCT).
-  void VerifySCTs(base::StringPiece encoded_sct_list,
+  void VerifySCTs(std::string_view encoded_sct_list,
                   const ct::SignedEntryData& expected_entry,
                   ct::SignedCertificateTimestamp::Origin origin,
                   X509Certificate* cert,
diff --git a/net/cert/multi_log_ct_verifier_unittest.cc b/net/cert/multi_log_ct_verifier_unittest.cc
index c6a1959..46505c4 100644
--- a/net/cert/multi_log_ct_verifier_unittest.cc
+++ b/net/cert/multi_log_ct_verifier_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include <string>
+#include <string_view>
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -100,7 +101,7 @@
   // successfully extracted.
   bool VerifySinglePrecertificateChain(scoped_refptr<X509Certificate> chain) {
     SignedCertificateTimestampAndStatusList scts;
-    verifier_->Verify(chain.get(), base::StringPiece(), base::StringPiece(),
+    verifier_->Verify(chain.get(), std::string_view(), std::string_view(),
                       &scts, NetLogWithSource());
     return !scts.empty();
   }
@@ -113,7 +114,7 @@
     RecordingNetLogObserver net_log_observer(NetLogCaptureMode::kDefault);
     NetLogWithSource net_log = NetLogWithSource::Make(
         NetLog::Get(), NetLogSourceType::SSL_CONNECT_JOB);
-    verifier_->Verify(chain.get(), base::StringPiece(), base::StringPiece(),
+    verifier_->Verify(chain.get(), std::string_view(), std::string_view(),
                       &scts, net_log);
     return ct::CheckForSingleVerifiedSCTInResult(scts, kLogDescription) &&
            ct::CheckForSCTOrigin(
@@ -188,7 +189,7 @@
   std::string sct_list = ct::GetSCTListForTesting();
 
   SignedCertificateTimestampAndStatusList scts;
-  verifier_->Verify(chain_.get(), base::StringPiece(), sct_list, &scts,
+  verifier_->Verify(chain_.get(), std::string_view(), sct_list, &scts,
                     NetLogWithSource());
   ASSERT_TRUE(ct::CheckForSingleVerifiedSCTInResult(scts, kLogDescription));
   ASSERT_TRUE(ct::CheckForSCTOrigin(
@@ -199,7 +200,7 @@
   std::string sct_list = ct::GetSCTListWithInvalidSCT();
   SignedCertificateTimestampAndStatusList scts;
 
-  verifier_->Verify(chain_.get(), base::StringPiece(), sct_list, &scts,
+  verifier_->Verify(chain_.get(), std::string_view(), sct_list, &scts,
                     NetLogWithSource());
   EXPECT_EQ(1U, scts.size());
   EXPECT_EQ("", scts[0].sct->log_description);
@@ -222,7 +223,7 @@
   int num_invalid_scts = GetValueFromHistogram(
       "Net.CertificateTransparency.SCTStatus", ct::SCT_STATUS_LOG_UNKNOWN);
 
-  verifier_->Verify(chain_.get(), base::StringPiece(), sct_list, &scts,
+  verifier_->Verify(chain_.get(), std::string_view(), sct_list, &scts,
                     NetLogWithSource());
 
   ASSERT_EQ(num_valid_scts, NumValidSCTsInStatusHistogram());
diff --git a/net/cert/nss_profile_filter_chromeos.cc b/net/cert/nss_profile_filter_chromeos.cc
index d9f35a3..42437de 100644
--- a/net/cert/nss_profile_filter_chromeos.cc
+++ b/net/cert/nss_profile_filter_chromeos.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "base/strings/string_piece.h"
 #include "net/cert/x509_certificate.h"
 
 namespace net {
diff --git a/net/cert/test_root_certs.cc b/net/cert/test_root_certs.cc
index 815de93a..28912c2 100644
--- a/net/cert/test_root_certs.cc
+++ b/net/cert/test_root_certs.cc
@@ -5,6 +5,7 @@
 #include "net/cert/test_root_certs.h"
 
 #include <string>
+#include <string_view>
 #include <utility>
 
 #include "net/cert/x509_certificate.h"
@@ -72,8 +73,8 @@
 
 bool TestRootCerts::IsKnownRoot(base::span<const uint8_t> der_cert) const {
   return test_known_roots_.find(
-             base::StringPiece(reinterpret_cast<const char*>(der_cert.data()),
-                               der_cert.size())) != test_known_roots_.end();
+             std::string_view(reinterpret_cast<const char*>(der_cert.data()),
+                              der_cert.size())) != test_known_roots_.end();
 }
 
 TestRootCerts::TestRootCerts() {
diff --git a/net/cert/time_conversions_unittest.cc b/net/cert/time_conversions_unittest.cc
index 53b9cb4..5142a015 100644
--- a/net/cert/time_conversions_unittest.cc
+++ b/net/cert/time_conversions_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "net/cert/time_conversions.h"
 
-#include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/boringssl/src/pki/parse_values.h"
diff --git a/net/cert/x509_certificate.cc b/net/cert/x509_certificate.cc
index ef5b2a8..30f5cd87 100644
--- a/net/cert/x509_certificate.cc
+++ b/net/cert/x509_certificate.cc
@@ -9,6 +9,7 @@
 
 #include <memory>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/containers/contains.h"
@@ -17,7 +18,6 @@
 #include "base/notreached.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/pickle.h"
-#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
 #include "crypto/openssl_util.h"
@@ -60,14 +60,14 @@
 // Utility to split |src| on the first occurrence of |c|, if any. |right| will
 // either be empty if |c| was not found, or will contain the remainder of the
 // string including the split character itself.
-void SplitOnChar(base::StringPiece src,
+void SplitOnChar(std::string_view src,
                  char c,
-                 base::StringPiece* left,
-                 base::StringPiece* right) {
+                 std::string_view* left,
+                 std::string_view* right) {
   size_t pos = src.find(c);
-  if (pos == base::StringPiece::npos) {
+  if (pos == std::string_view::npos) {
     *left = src;
-    *right = base::StringPiece();
+    *right = std::string_view();
   } else {
     *left = src.substr(0, pos);
     *right = src.substr(pos);
@@ -150,14 +150,14 @@
 
 // static
 scoped_refptr<X509Certificate> X509Certificate::CreateFromDERCertChain(
-    const std::vector<base::StringPiece>& der_certs) {
+    const std::vector<std::string_view>& der_certs) {
   return CreateFromDERCertChainUnsafeOptions(der_certs, {});
 }
 
 // static
 scoped_refptr<X509Certificate>
 X509Certificate::CreateFromDERCertChainUnsafeOptions(
-    const std::vector<base::StringPiece>& der_certs,
+    const std::vector<std::string_view>& der_certs,
     UnsafeCreateOptions options) {
   TRACE_EVENT0("io", "X509Certificate::CreateFromDERCertChain");
   if (der_certs.empty())
@@ -204,7 +204,7 @@
   if (!pickle_iter->ReadLength(&chain_length))
     return nullptr;
 
-  std::vector<base::StringPiece> cert_chain;
+  std::vector<std::string_view> cert_chain;
   const char* data = nullptr;
   size_t data_length = 0;
   for (size_t i = 0; i < chain_length; ++i) {
@@ -224,8 +224,8 @@
   // Check to see if it is in a PEM-encoded form. This check is performed
   // first, as both OS X and NSS will both try to convert if they detect
   // PEM encoding, except they don't do it consistently between the two.
-  base::StringPiece data_string(reinterpret_cast<const char*>(data.data()),
-                                data.size());
+  std::string_view data_string(reinterpret_cast<const char*>(data.data()),
+                               data.size());
   std::vector<std::string> pem_headers;
 
   // To maintain compatibility with NSS/Firefox, CERTIFICATE is a universally
@@ -464,7 +464,7 @@
 
   // Fully handle all cases where |hostname| contains an IP address.
   if (host_info.IsIPAddress()) {
-    base::StringPiece ip_addr_string(
+    std::string_view ip_addr_string(
         reinterpret_cast<const char*>(host_info.address),
         host_info.AddressLength());
     return base::Contains(cert_san_ip_addrs, ip_addr_string);
@@ -490,7 +490,7 @@
   // "www.f.com" -> ".f.com".
   // If there is no meaningful domain part to |host| (e.g. it contains no dots)
   // then |reference_domain| will be empty.
-  base::StringPiece reference_host, reference_domain;
+  std::string_view reference_host, reference_domain;
   SplitOnChar(reference_name, '.', &reference_host, &reference_domain);
   bool allow_wildcards = false;
   if (!reference_domain.empty()) {
@@ -546,7 +546,7 @@
     if (presented_name.length() > reference_name.length())
       continue;
 
-    base::StringPiece presented_host, presented_domain;
+    std::string_view presented_host, presented_domain;
     SplitOnChar(presented_name, '.', &presented_host, &presented_domain);
 
     if (presented_domain != reference_domain)
@@ -573,7 +573,7 @@
 }
 
 // static
-bool X509Certificate::GetPEMEncodedFromDER(base::StringPiece der_encoded,
+bool X509Certificate::GetPEMEncodedFromDER(std::string_view der_encoded,
                                            std::string* pem_encoded) {
   if (der_encoded.empty())
     return false;
@@ -612,9 +612,9 @@
   *type = kPublicKeyTypeUnknown;
   *size_bits = 0;
 
-  base::StringPiece spki;
+  std::string_view spki;
   if (!asn1::ExtractSPKIFromDERCert(
-          base::StringPiece(
+          std::string_view(
               reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert_buffer)),
               CRYPTO_BUFFER_len(cert_buffer)),
           &spki)) {
diff --git a/net/cert/x509_certificate.h b/net/cert/x509_certificate.h
index 5ef19cf..351bc87 100644
--- a/net/cert/x509_certificate.h
+++ b/net/cert/x509_certificate.h
@@ -9,12 +9,12 @@
 #include <string.h>
 
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/containers/span.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "net/base/hash_value.h"
 #include "net/base/net_export.h"
@@ -99,13 +99,13 @@
   // handle is returned. The other certificates in the chain are intermediate
   // certificates.
   static scoped_refptr<X509Certificate> CreateFromDERCertChain(
-      const std::vector<base::StringPiece>& der_certs);
+      const std::vector<std::string_view>& der_certs);
 
   // Create an X509Certificate from a chain of DER encoded certificates with
   // non-standard parsing options.
   // Do not use without consulting //net owners.
   static scoped_refptr<X509Certificate> CreateFromDERCertChainUnsafeOptions(
-      const std::vector<base::StringPiece>& der_certs,
+      const std::vector<std::string_view>& der_certs,
       UnsafeCreateOptions options);
 
   // Create an X509Certificate from the DER-encoded representation.
@@ -211,7 +211,7 @@
   // Returns the PEM encoded data from a DER encoded certificate. If the
   // return value is true, then the PEM encoded certificate is written to
   // |pem_encoded|.
-  static bool GetPEMEncodedFromDER(base::StringPiece der_encoded,
+  static bool GetPEMEncodedFromDER(std::string_view der_encoded,
                                    std::string* pem_encoded);
 
   // Returns the PEM encoded data from a CRYPTO_BUFFER. If the return value is
diff --git a/net/cert/x509_certificate_unittest.cc b/net/cert/x509_certificate_unittest.cc
index d8431cf..933673f 100644
--- a/net/cert/x509_certificate_unittest.cc
+++ b/net/cert/x509_certificate_unittest.cc
@@ -7,6 +7,7 @@
 #include <stdint.h>
 
 #include <memory>
+#include <string_view>
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -574,7 +575,7 @@
       ImportCertFromFile(certs_dir, "nist.der");
   ASSERT_NE(static_cast<X509Certificate*>(nullptr), cert.get());
 
-  base::StringPiece spkiBytes;
+  std::string_view spkiBytes;
   EXPECT_TRUE(asn1::ExtractSPKIFromDERCert(
       x509_util::CryptoBufferAsStringPiece(cert->cert_buffer()), &spkiBytes));
 
@@ -622,20 +623,20 @@
   ASSERT_TRUE(cert);
 
   bool present, critical;
-  base::StringPiece contents;
+  std::string_view contents;
   ASSERT_TRUE(asn1::ExtractExtensionFromDERCert(
       x509_util::CryptoBufferAsStringPiece(cert->cert_buffer()),
       bssl::der::Input(bssl::kBasicConstraintsOid).AsStringView(), &present,
       &critical, &contents));
   EXPECT_TRUE(present);
   EXPECT_TRUE(critical);
-  ASSERT_EQ(base::StringPiece("\x30\x00", 2), contents);
+  ASSERT_EQ(std::string_view("\x30\x00", 2), contents);
 
   static constexpr uint8_t kNonsenseOID[] = {0x56, 0x1d, 0x13};
   ASSERT_TRUE(asn1::ExtractExtensionFromDERCert(
       x509_util::CryptoBufferAsStringPiece(cert->cert_buffer()),
-      base::StringPiece(reinterpret_cast<const char*>(kNonsenseOID),
-                        sizeof(kNonsenseOID)),
+      std::string_view(reinterpret_cast<const char*>(kNonsenseOID),
+                       sizeof(kNonsenseOID)),
       &present, &critical, &contents));
   ASSERT_FALSE(present);
 
@@ -648,7 +649,7 @@
       &critical, &contents));
   EXPECT_TRUE(present);
   EXPECT_FALSE(critical);
-  ASSERT_EQ(base::StringPiece("\x30\x00", 2), contents);
+  ASSERT_EQ(std::string_view("\x30\x00", 2), contents);
 }
 
 // Tests CRYPTO_BUFFER deduping via X509Certificate::CreateFromBuffer.  We
@@ -1000,7 +1001,7 @@
 
   constexpr char invalid_cert_data[] = "this is not a certificate";
   bssl::UniquePtr<CRYPTO_BUFFER> invalid_cert_handle =
-      x509_util::CreateCryptoBuffer(base::StringPiece(invalid_cert_data));
+      x509_util::CreateCryptoBuffer(std::string_view(invalid_cert_data));
   ASSERT_TRUE(invalid_cert_handle);
   EXPECT_FALSE(X509Certificate::IsSelfSigned(invalid_cert_handle.get()));
 }
diff --git a/net/cert/x509_util.cc b/net/cert/x509_util.cc
index 44bec6d..a0c8086 100644
--- a/net/cert/x509_util.cc
+++ b/net/cert/x509_util.cc
@@ -5,8 +5,10 @@
 #include "net/cert/x509_util.h"
 
 #include <string.h>
+
 #include <map>
 #include <memory>
+#include <string_view>
 
 #include "base/lazy_instance.h"
 #include "base/logging.h"
@@ -99,7 +101,7 @@
 }  // namespace
 
 // Adds an X.509 Name with the specified distinguished name to |cbb|.
-bool AddName(CBB* cbb, base::StringPiece name) {
+bool AddName(CBB* cbb, std::string_view name) {
   // See RFC 4519.
   static const uint8_t kCommonName[] = {0x55, 0x04, 0x03};
   static const uint8_t kCountryName[] = {0x55, 0x04, 0x06};
@@ -209,7 +211,7 @@
                                         std::string* token) {
   static const char kChannelBindingPrefix[] = "tls-server-end-point:";
 
-  base::StringPiece der_encoded_certificate =
+  std::string_view der_encoded_certificate =
       x509_util::CryptoBufferAsStringPiece(certificate.cert_buffer());
 
   bssl::der::Input tbs_certificate_tlv;
@@ -408,7 +410,7 @@
       CRYPTO_BUFFER_new(data.data(), data.size(), GetBufferPool()));
 }
 
-bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(base::StringPiece data) {
+bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(std::string_view data) {
   return bssl::UniquePtr<CRYPTO_BUFFER>(
       CRYPTO_BUFFER_new(reinterpret_cast<const uint8_t*>(data.data()),
                         data.size(), GetBufferPool()));
@@ -430,8 +432,8 @@
                 CRYPTO_BUFFER_len(a)) == 0;
 }
 
-base::StringPiece CryptoBufferAsStringPiece(const CRYPTO_BUFFER* buffer) {
-  return base::StringPiece(
+std::string_view CryptoBufferAsStringPiece(const CRYPTO_BUFFER* buffer) {
+  return std::string_view(
       reinterpret_cast<const char*>(CRYPTO_BUFFER_data(buffer)),
       CRYPTO_BUFFER_len(buffer));
 }
@@ -488,7 +490,7 @@
 }
 
 bool CalculateSha256SpkiHash(const CRYPTO_BUFFER* buffer, HashValue* hash) {
-  base::StringPiece spki;
+  std::string_view spki;
   if (!asn1::ExtractSPKIFromDERCert(CryptoBufferAsStringPiece(buffer), &spki)) {
     return false;
   }
@@ -502,8 +504,7 @@
     crypto::SignatureVerifier::SignatureAlgorithm signature_algorithm,
     base::span<const uint8_t> signature,
     const CRYPTO_BUFFER* certificate) {
-  base::StringPiece cert_der =
-      x509_util::CryptoBufferAsStringPiece(certificate);
+  std::string_view cert_der = x509_util::CryptoBufferAsStringPiece(certificate);
 
   bssl::der::Input tbs_certificate_tlv;
   bssl::der::Input signature_algorithm_tlv;
diff --git a/net/cert/x509_util.h b/net/cert/x509_util.h
index 59bd98b..f0785d5f 100644
--- a/net/cert/x509_util.h
+++ b/net/cert/x509_util.h
@@ -9,11 +9,11 @@
 
 #include <memory>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/containers/span.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "crypto/signature_verifier.h"
 #include "net/base/hash_value.h"
@@ -50,7 +50,7 @@
 // distinguished names. It should only be used if |name| is a constant
 // value, rather than programmatically constructed. If programmatic support
 // is needed, this input should be replaced with a richer type.
-NET_EXPORT bool AddName(CBB* cbb, base::StringPiece name);
+NET_EXPORT bool AddName(CBB* cbb, std::string_view name);
 
 // Generate a 'tls-server-end-point' channel binding based on the specified
 // certificate. Channel bindings are based on RFC 5929.
@@ -116,7 +116,7 @@
 
 // Creates a CRYPTO_BUFFER in the same pool returned by GetBufferPool.
 NET_EXPORT bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(
-    base::StringPiece data);
+    std::string_view data);
 
 // Overload with no definition, to disallow creating a CRYPTO_BUFFER from a
 // char* due to StringPiece implicit ctor.
@@ -134,7 +134,7 @@
                                   const CRYPTO_BUFFER* b);
 
 // Returns a StringPiece pointing to the data in |buffer|.
-NET_EXPORT base::StringPiece CryptoBufferAsStringPiece(
+NET_EXPORT std::string_view CryptoBufferAsStringPiece(
     const CRYPTO_BUFFER* buffer);
 
 // Returns a span pointing to the data in |buffer|.
diff --git a/net/cert/x509_util_win.cc b/net/cert/x509_util_win.cc
index 8b87421..069986d 100644
--- a/net/cert/x509_util_win.cc
+++ b/net/cert/x509_util_win.cc
@@ -4,6 +4,8 @@
 
 #include "net/cert/x509_util_win.h"
 
+#include <string_view>
+
 #include "base/logging.h"
 #include "crypto/scoped_capi_types.h"
 #include "crypto/sha2.h"
@@ -98,8 +100,8 @@
   // * < Windows Vista does not have universal SHA-256 support.
   // * More efficient on Windows > Vista (less overhead since non-default CSP
   // is not needed).
-  base::StringPiece der_cert(reinterpret_cast<const char*>(cert->pbCertEncoded),
-                             cert->cbCertEncoded);
+  std::string_view der_cert(reinterpret_cast<const char*>(cert->pbCertEncoded),
+                            cert->cbCertEncoded);
   crypto::SHA256HashString(der_cert, sha256.data, sizeof(sha256.data));
   return sha256;
 }
diff --git a/net/third_party/quiche/src b/net/third_party/quiche/src
index 99be906..83a9e81 160000
--- a/net/third_party/quiche/src
+++ b/net/third_party/quiche/src
@@ -1 +1 @@
-Subproject commit 99be906332f369aaecc3fed7bb1943018d7c213b
+Subproject commit 83a9e81296b36898025bce1110db9f9c4f23afd3
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn
index 5ecedb37..1a92cd1 100644
--- a/services/network/public/cpp/BUILD.gn
+++ b/services/network/public/cpp/BUILD.gn
@@ -118,6 +118,8 @@
     "self_deleting_url_loader_factory.cc",
     "self_deleting_url_loader_factory.h",
     "session_cookie_delete_predicate.h",
+    "shared_dictionary_encoding_names.cc",
+    "shared_dictionary_encoding_names.h",
     "shared_url_loader_factory.cc",
     "shared_url_loader_factory.h",
     "simple_host_resolver.cc",
diff --git a/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc b/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
index 439178c..fd094235 100644
--- a/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
+++ b/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
@@ -103,7 +103,7 @@
     scheme_to_bypass_.push_back(scheme);
   }
 
-  bool SchemeShouldBypassCSP(const std::string_view& scheme) override {
+  bool SchemeShouldBypassCSP(std::string_view scheme) override {
     return base::Contains(scheme_to_bypass_, scheme);
   }
 
diff --git a/services/network/public/cpp/content_security_policy/csp_context.cc b/services/network/public/cpp/content_security_policy/csp_context.cc
index bb700d1..557d5e3 100644
--- a/services/network/public/cpp/content_security_policy/csp_context.cc
+++ b/services/network/public/cpp/content_security_policy/csp_context.cc
@@ -60,7 +60,7 @@
   return result;
 }
 
-bool CSPContext::SchemeShouldBypassCSP(const std::string_view& scheme) {
+bool CSPContext::SchemeShouldBypassCSP(std::string_view scheme) {
   // Blink uses its SchemeRegistry to check if a scheme should be bypassed.
   // It can't be used on the browser process. It is used for two things:
   // 1) Bypassing the "chrome-extension" scheme when chrome is built with the
diff --git a/services/network/public/cpp/content_security_policy/csp_context.h b/services/network/public/cpp/content_security_policy/csp_context.h
index 2cc75e8..5129fa3e 100644
--- a/services/network/public/cpp/content_security_policy/csp_context.h
+++ b/services/network/public/cpp/content_security_policy/csp_context.h
@@ -86,7 +86,7 @@
 
   // This is declared virtual only so that it can be overridden for unit
   // testing.
-  virtual bool SchemeShouldBypassCSP(const std::string_view& scheme);
+  virtual bool SchemeShouldBypassCSP(std::string_view scheme);
 };
 
 }  // namespace network
diff --git a/services/network/public/cpp/content_security_policy/csp_context_unittest.cc b/services/network/public/cpp/content_security_policy/csp_context_unittest.cc
index 2641124..de5010b 100644
--- a/services/network/public/cpp/content_security_policy/csp_context_unittest.cc
+++ b/services/network/public/cpp/content_security_policy/csp_context_unittest.cc
@@ -27,7 +27,7 @@
     scheme_to_bypass_.insert(scheme);
   }
 
-  bool SchemeShouldBypassCSP(const std::string_view& scheme) override {
+  bool SchemeShouldBypassCSP(std::string_view scheme) override {
     return scheme_to_bypass_.count(std::string(scheme));
   }
 
diff --git a/services/network/public/cpp/content_security_policy/csp_source.cc b/services/network/public/cpp/content_security_policy/csp_source.cc
index f4f28daf..23548bd 100644
--- a/services/network/public/cpp/content_security_policy/csp_source.cc
+++ b/services/network/public/cpp/content_security_policy/csp_source.cc
@@ -23,7 +23,7 @@
   return !source.host.empty() || source.is_host_wildcard;
 }
 
-bool DecodePath(const std::string_view& path, std::string* output) {
+bool DecodePath(std::string_view path, std::string* output) {
   url::RawCanonOutputT<char16_t> unescaped;
   url::DecodeURLEscapeSequences(path, url::DecodeURLMode::kUTF8OrIsomorphic,
                                 &unescaped);
diff --git a/services/network/public/cpp/corb/corb_impl.cc b/services/network/public/cpp/corb/corb_impl.cc
index 3ea864a..c820008d 100644
--- a/services/network/public/cpp/corb/corb_impl.cc
+++ b/services/network/public/cpp/corb/corb_impl.cc
@@ -112,8 +112,7 @@
   return CrossOriginReadBlocking::kNo;
 }
 
-size_t FindFirstJavascriptLineTerminator(const std::string_view& hay,
-                                         size_t pos) {
+size_t FindFirstJavascriptLineTerminator(std::string_view hay, size_t pos) {
   // https://www.ecma-international.org/ecma-262/8.0/index.html#prod-LineTerminator
   // defines LineTerminator ::= <LF> | <CR> | <LS> | <PS>.
   //
diff --git a/services/network/public/cpp/devtools_observer_util.cc b/services/network/public/cpp/devtools_observer_util.cc
index fcd1508..eabcfaa 100644
--- a/services/network/public/cpp/devtools_observer_util.cc
+++ b/services/network/public/cpp/devtools_observer_util.cc
@@ -13,11 +13,12 @@
 mojom::URLResponseHeadDevToolsInfoPtr ExtractDevToolsInfo(
     const mojom::URLResponseHead& head) {
   return network::mojom::URLResponseHeadDevToolsInfo::New(
-      head.response_time, head.headers, head.mime_type, head.load_timing,
-      head.cert_status, head.encoded_data_length, head.was_in_prefetch_cache,
-      head.was_fetched_via_service_worker, head.cache_storage_cache_name,
-      head.alpn_negotiated_protocol, head.alternate_protocol_usage,
-      head.was_fetched_via_spdy, head.service_worker_response_source,
+      head.response_time, head.headers, head.mime_type, head.charset,
+      head.load_timing, head.cert_status, head.encoded_data_length,
+      head.was_in_prefetch_cache, head.was_fetched_via_service_worker,
+      head.cache_storage_cache_name, head.alpn_negotiated_protocol,
+      head.alternate_protocol_usage, head.was_fetched_via_spdy,
+      head.service_worker_response_source,
       head.service_worker_router_info.Clone(), head.ssl_info,
       head.remote_endpoint, head.emitted_extra_info);
 }
diff --git a/services/network/public/cpp/header_util.cc b/services/network/public/cpp/header_util.cc
index d044083..2782c5e 100644
--- a/services/network/public/cpp/header_util.cc
+++ b/services/network/public/cpp/header_util.cc
@@ -73,8 +73,7 @@
 
 }  // namespace
 
-bool IsRequestHeaderSafe(const std::string_view& key,
-                         const std::string_view& value) {
+bool IsRequestHeaderSafe(std::string_view key, std::string_view value) {
   for (const auto* header : kUnsafeHeaders) {
     if (base::EqualsCaseInsensitiveASCII(header, key))
       return false;
diff --git a/services/network/public/cpp/header_util.h b/services/network/public/cpp/header_util.h
index e50b7a20..a6734cde 100644
--- a/services/network/public/cpp/header_util.h
+++ b/services/network/public/cpp/header_util.h
@@ -23,8 +23,7 @@
 
 // Checks if a single request header is safe to send.
 COMPONENT_EXPORT(NETWORK_CPP)
-bool IsRequestHeaderSafe(const std::string_view& key,
-                         const std::string_view& value);
+bool IsRequestHeaderSafe(std::string_view key, std::string_view value);
 
 // Checks if any single header in a set of request headers is not safe to send.
 // When adding sets of headers together, it's safe to call this on each set
diff --git a/services/network/public/cpp/server/web_socket_encoder.cc b/services/network/public/cpp/server/web_socket_encoder.cc
index 85f27c5..b6f36842 100644
--- a/services/network/public/cpp/server/web_socket_encoder.cc
+++ b/services/network/public/cpp/server/web_socket_encoder.cc
@@ -40,7 +40,7 @@
 const size_t kEightBytePayloadLengthField = 127;
 const size_t kMaskingKeyWidthInBytes = 4;
 
-WebSocket::ParseResult DecodeFrameHybi17(const std::string_view& frame,
+WebSocket::ParseResult DecodeFrameHybi17(std::string_view frame,
                                          bool client_frame,
                                          int* bytes_consumed,
                                          std::string* output,
@@ -293,10 +293,9 @@
 
 WebSocketEncoder::~WebSocketEncoder() = default;
 
-WebSocket::ParseResult WebSocketEncoder::DecodeFrame(
-    const std::string_view& frame,
-    int* bytes_consumed,
-    std::string* output) {
+WebSocket::ParseResult WebSocketEncoder::DecodeFrame(std::string_view frame,
+                                                     int* bytes_consumed,
+                                                     std::string* output) {
   bool compressed;
   std::string current_output;
   WebSocket::ParseResult result = DecodeFrameHybi17(
diff --git a/services/network/public/cpp/server/web_socket_encoder.h b/services/network/public/cpp/server/web_socket_encoder.h
index 36761549..23a4aa23 100644
--- a/services/network/public/cpp/server/web_socket_encoder.h
+++ b/services/network/public/cpp/server/web_socket_encoder.h
@@ -44,7 +44,7 @@
   static std::unique_ptr<WebSocketEncoder> CreateClient(
       const std::string& response_extensions);
 
-  WebSocket::ParseResult DecodeFrame(const std::string_view& frame,
+  WebSocket::ParseResult DecodeFrame(std::string_view frame,
                                      int* bytes_consumed,
                                      std::string* output);
   void EncodeTextFrame(std::string_view frame,
diff --git a/services/network/public/cpp/shared_dictionary_encoding_names.cc b/services/network/public/cpp/shared_dictionary_encoding_names.cc
new file mode 100644
index 0000000..4d9a176
--- /dev/null
+++ b/services/network/public/cpp/shared_dictionary_encoding_names.cc
@@ -0,0 +1,24 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/shared_dictionary_encoding_names.h"
+
+#include "services/network/public/cpp/features.h"
+
+namespace network {
+
+const char* GetSharedBrotliContentEncodingName() {
+  switch (features::kCompressionDictionaryTransportBackendVersion.Get()) {
+    case features::CompressionDictionaryTransportBackendVersion::kV1:
+      return "sbr";
+    case features::CompressionDictionaryTransportBackendVersion::kV2:
+      return "br-d";
+  }
+}
+
+const char* GetSharedZstdContentEncodingName() {
+  return "zstd-d";
+}
+
+}  // namespace network
diff --git a/services/network/public/cpp/shared_dictionary_encoding_names.h b/services/network/public/cpp/shared_dictionary_encoding_names.h
new file mode 100644
index 0000000..9c0d1ac
--- /dev/null
+++ b/services/network/public/cpp/shared_dictionary_encoding_names.h
@@ -0,0 +1,22 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_SHARED_DICTIONARY_ENCODING_NAMES_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_SHARED_DICTIONARY_ENCODING_NAMES_H_
+
+#include "base/component_export.h"
+
+namespace network {
+
+// Returns the content encoding name of Shared Brotli:
+//   "sbr": when CompressionDictionaryTransportBackendVersion is kV1.
+//   "br-d": when CompressionDictionaryTransportBackendVersion is kV2.
+COMPONENT_EXPORT(NETWORK_CPP) const char* GetSharedBrotliContentEncodingName();
+
+// Returns the content encoding name of Shared Zstd: "zstd-d".
+COMPONENT_EXPORT(NETWORK_CPP) const char* GetSharedZstdContentEncodingName();
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_PUBLIC_CPP_SHARED_DICTIONARY_ENCODING_NAMES_H_
diff --git a/services/network/public/cpp/web_sandbox_flags.cc b/services/network/public/cpp/web_sandbox_flags.cc
index 76befab2..fb63755 100644
--- a/services/network/public/cpp/web_sandbox_flags.cc
+++ b/services/network/public/cpp/web_sandbox_flags.cc
@@ -20,7 +20,7 @@
 // This is different from: base::kWhitespaceASCII.
 const char* kHtmlWhitespace = " \n\t\r\f";
 
-WebSandboxFlags ParseWebSandboxToken(const std::string_view& token) {
+WebSandboxFlags ParseWebSandboxToken(std::string_view token) {
   constexpr struct {
     const char* token;
     WebSandboxFlags flags;
@@ -61,7 +61,7 @@
 
 // See: http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox
 WebSandboxFlagsParsingResult ParseWebSandboxPolicy(
-    const std::string_view& input,
+    std::string_view input,
     WebSandboxFlags ignored_flags) {
   WebSandboxFlagsParsingResult out;
   out.flags = WebSandboxFlags::kAll;
diff --git a/services/network/public/cpp/web_sandbox_flags.h b/services/network/public/cpp/web_sandbox_flags.h
index 4443007..cbe5bca 100644
--- a/services/network/public/cpp/web_sandbox_flags.h
+++ b/services/network/public/cpp/web_sandbox_flags.h
@@ -63,7 +63,7 @@
 // or from the network process. See: docs/security/rule-of-2.md.
 COMPONENT_EXPORT(NETWORK_CPP)
 WebSandboxFlagsParsingResult ParseWebSandboxPolicy(
-    const std::string_view& input,
+    std::string_view input,
     mojom::WebSandboxFlags ignored_flags);
 
 }  // namespace network
diff --git a/services/network/public/mojom/devtools_observer.mojom b/services/network/public/mojom/devtools_observer.mojom
index 9052c19..9987491 100644
--- a/services/network/public/mojom/devtools_observer.mojom
+++ b/services/network/public/mojom/devtools_observer.mojom
@@ -47,6 +47,7 @@
   mojo_base.mojom.Time response_time;
   HttpResponseHeaders headers;
   string mime_type;
+  string charset;
   LoadTimingInfo load_timing;
   uint32 cert_status;
   int64 encoded_data_length;
diff --git a/services/network/shared_dictionary/shared_dictionary_constants.cc b/services/network/shared_dictionary/shared_dictionary_constants.cc
index 0396664..e01013a 100644
--- a/services/network/shared_dictionary/shared_dictionary_constants.cc
+++ b/services/network/shared_dictionary/shared_dictionary_constants.cc
@@ -16,9 +16,6 @@
 
 }  // namespace
 
-const char kSbrContentEncodingName[] = "sbr";
-const char kZstdDContentEncodingName[] = "zstd-d";
-
 const char kSecAvailableDictionaryHeaderName[] = "sec-available-dictionary";
 
 const char kUseAsDictionaryHeaderName[] = "use-as-dictionary";
diff --git a/services/network/shared_dictionary/shared_dictionary_constants.h b/services/network/shared_dictionary/shared_dictionary_constants.h
index a2d61ff..648478909 100644
--- a/services/network/shared_dictionary/shared_dictionary_constants.h
+++ b/services/network/shared_dictionary/shared_dictionary_constants.h
@@ -34,14 +34,6 @@
 base::ScopedClosureRunner SetDictionarySizeLimitForTesting(
     size_t dictionary_size_limit);
 
-// The content encoding name of "sbr".
-COMPONENT_EXPORT(NETWORK_SERVICE)
-extern const char kSbrContentEncodingName[];
-
-// The content encoding name of "zstd-d".
-COMPONENT_EXPORT(NETWORK_SERVICE)
-extern const char kZstdDContentEncodingName[];
-
 // The header name of "sec-available-dictionary".
 COMPONENT_EXPORT(NETWORK_SERVICE)
 extern const char kSecAvailableDictionaryHeaderName[];
diff --git a/services/network/shared_dictionary/shared_dictionary_network_transaction.cc b/services/network/shared_dictionary/shared_dictionary_network_transaction.cc
index c24a3d32..c5b8234 100644
--- a/services/network/shared_dictionary/shared_dictionary_network_transaction.cc
+++ b/services/network/shared_dictionary/shared_dictionary_network_transaction.cc
@@ -31,6 +31,7 @@
 #include "net/http/http_request_info.h"
 #include "net/ssl/ssl_private_key.h"
 #include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/shared_dictionary_encoding_names.h"
 #include "services/network/shared_dictionary/shared_dictionary.h"
 #include "services/network/shared_dictionary/shared_dictionary_constants.h"
 #include "services/network/shared_dictionary/shared_dictionary_manager.h"
@@ -137,11 +138,10 @@
   if (!headers.GetNormalizedHeader("Content-Encoding", &content_encoding)) {
     return SharedDictionaryEncodingType::kNotUsed;
   }
-  if (content_encoding == network::shared_dictionary::kSbrContentEncodingName) {
+  if (content_encoding == GetSharedBrotliContentEncodingName()) {
     return SharedDictionaryEncodingType::kSharedBrotli;
   } else if (base::FeatureList::IsEnabled(network::features::kSharedZstd) &&
-             content_encoding ==
-                 network::shared_dictionary::kZstdDContentEncodingName) {
+             content_encoding == GetSharedZstdContentEncodingName()) {
     return SharedDictionaryEncodingType::kSharedZstd;
   }
   return SharedDictionaryEncodingType::kNotUsed;
@@ -220,9 +220,11 @@
                           sizeof(shared_dictionary_->hash().data))));
 
   if (base::FeatureList::IsEnabled(network::features::kSharedZstd)) {
-    AddAcceptEncoding(request_headers, "sbr, zstd-d");
+    AddAcceptEncoding(request_headers,
+                      base::StrCat({GetSharedBrotliContentEncodingName(), ", ",
+                                    GetSharedZstdContentEncodingName()}));
   } else {
-    AddAcceptEncoding(request_headers, "sbr");
+    AddAcceptEncoding(request_headers, GetSharedBrotliContentEncodingName());
   }
 
   if (dictionary_status_ == DictionaryStatus::kNoDictionary) {
diff --git a/services/network/shared_dictionary/shared_dictionary_network_transaction_unittest.cc b/services/network/shared_dictionary/shared_dictionary_network_transaction_unittest.cc
index 2fada8d..1382005 100644
--- a/services/network/shared_dictionary/shared_dictionary_network_transaction_unittest.cc
+++ b/services/network/shared_dictionary/shared_dictionary_network_transaction_unittest.cc
@@ -239,7 +239,7 @@
       *response_data = kTestData;
     });
 
-const net::MockTransaction kBrotliDictionaryTestTransaction = {
+const net::MockTransaction kBrotliDictionaryTestTransactionV1 = {
     .url = "https://test.example/test",
     .method = "GET",
     .request_time = base::Time(),
@@ -263,6 +263,30 @@
     .read_return_code = net::OK,
 };
 
+const net::MockTransaction kBrotliDictionaryTestTransactionV2 = {
+    .url = "https://test.example/test",
+    .method = "GET",
+    .request_time = base::Time(),
+    .request_headers = "",
+    .load_flags = net::LOAD_CAN_USE_SHARED_DICTIONARY,
+    .transport_info = TestSpdyTransportInfo(),
+    .status = "HTTP/1.1 200 OK",
+    .response_headers = "content-encoding: br-d\n",
+    .response_time = base::Time(),
+    .data = "",  // We set the body in the `handler` function.
+    .dns_aliases = {},
+    .fps_cache_filter = absl::nullopt,
+    .browser_run_id = absl::nullopt,
+    .test_mode = net::TEST_MODE_NORMAL,
+    .handler = base::BindRepeating(&BrotliTestTransactionHandler),
+    .read_handler = net::MockTransactionReadHandler(),
+    .cert = nullptr,
+    .cert_status = 0,
+    .ssl_connection_status = 0,
+    .start_return_code = net::OK,
+    .read_return_code = net::OK,
+};
+
 const net::MockTransaction kZstdDictionaryTestTransaction = {
     .url = "https://test.example/test",
     .method = "GET",
@@ -287,20 +311,42 @@
     .read_return_code = net::OK,
 };
 
-class SharedDictionaryNetworkTransactionTest : public ::testing::Test {
+class SharedDictionaryNetworkTransactionTestBase : public ::testing::Test {
  public:
-  SharedDictionaryNetworkTransactionTest()
-      : network_layer_(std::make_unique<net::MockNetworkLayer>()) {
-    net::AddMockTransaction(&kBrotliDictionaryTestTransaction);
+  explicit SharedDictionaryNetworkTransactionTestBase(
+      network::features::CompressionDictionaryTransportBackendVersion version)
+      : version_(version),
+        network_layer_(std::make_unique<net::MockNetworkLayer>()) {
+    scoped_feature_list_.InitWithFeaturesAndParameters(
+        /*enabled_features=*/
+        {base::test::FeatureRefAndParams(
+            network::features::kCompressionDictionaryTransportBackend,
+            {{network::features::kCompressionDictionaryTransportBackendVersion
+                  .name,
+              network::features::kCompressionDictionaryTransportBackendVersion
+                  .GetName(GetVersion())}})},
+        /*disabled_features=*/{});
+    net::AddMockTransaction(&GetBrotliDictionaryTestTransaction());
   }
-  ~SharedDictionaryNetworkTransactionTest() override = default;
+  ~SharedDictionaryNetworkTransactionTestBase() override = default;
 
-  SharedDictionaryNetworkTransactionTest(
-      const SharedDictionaryNetworkTransactionTest&) = delete;
-  SharedDictionaryNetworkTransactionTest& operator=(
-      const SharedDictionaryNetworkTransactionTest&) = delete;
+  SharedDictionaryNetworkTransactionTestBase(
+      const SharedDictionaryNetworkTransactionTestBase&) = delete;
+  SharedDictionaryNetworkTransactionTestBase& operator=(
+      const SharedDictionaryNetworkTransactionTestBase&) = delete;
 
  protected:
+  network::features::CompressionDictionaryTransportBackendVersion GetVersion() {
+    return version_;
+  }
+  const net::MockTransaction& GetBrotliDictionaryTestTransaction() {
+    switch (GetVersion()) {
+      case network::features::CompressionDictionaryTransportBackendVersion::kV1:
+        return kBrotliDictionaryTestTransactionV1;
+      case network::features::CompressionDictionaryTransportBackendVersion::kV2:
+        return kBrotliDictionaryTestTransactionV2;
+    }
+  }
   std::unique_ptr<net::HttpTransaction> CreateNetworkTransaction() {
     std::unique_ptr<net::HttpTransaction> network_transaction;
     network_layer_->CreateTransaction(net::DEFAULT_PRIORITY,
@@ -313,17 +359,59 @@
   net::MockNetworkLayer& network_layer() { return *network_layer_.get(); }
 
  private:
+  const network::features::CompressionDictionaryTransportBackendVersion
+      version_;
   std::unique_ptr<net::MockNetworkLayer> network_layer_;
   base::test::TaskEnvironment task_environment_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-TEST_F(SharedDictionaryNetworkTransactionTest, SyncDictionary) {
+class SharedDictionaryNetworkTransactionTest
+    : public SharedDictionaryNetworkTransactionTestBase,
+      public ::testing::WithParamInterface<
+          network::features::CompressionDictionaryTransportBackendVersion> {
+ public:
+  SharedDictionaryNetworkTransactionTest()
+      : SharedDictionaryNetworkTransactionTestBase(GetVersion()) {}
+  ~SharedDictionaryNetworkTransactionTest() override = default;
+
+  SharedDictionaryNetworkTransactionTest(
+      const SharedDictionaryNetworkTransactionTest&) = delete;
+  SharedDictionaryNetworkTransactionTest& operator=(
+      const SharedDictionaryNetworkTransactionTest&) = delete;
+
+ protected:
+  network::features::CompressionDictionaryTransportBackendVersion GetVersion() {
+    return GetParam();
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    SharedDictionaryNetworkTransactionTest,
+    testing::Values(
+        network::features::CompressionDictionaryTransportBackendVersion::kV1,
+        network::features::CompressionDictionaryTransportBackendVersion::kV2),
+    [](const testing::TestParamInfo<
+        network::features::CompressionDictionaryTransportBackendVersion>&
+           info) {
+      switch (info.param) {
+        case network::features::CompressionDictionaryTransportBackendVersion::
+            kV1:
+          return "V1";
+        case network::features::CompressionDictionaryTransportBackendVersion::
+            kV2:
+          return "V2";
+      }
+    });
+
+TEST_P(SharedDictionaryNetworkTransactionTest, SyncDictionary) {
   DummySharedDictionaryManager manager(
       base::MakeRefCounted<DummySharedDictionaryStorage>(
           std::make_unique<DummySyncDictionary>(kTestDictionaryData)));
 
-  net::MockHttpRequest request(kBrotliDictionaryTestTransaction);
+  net::MockHttpRequest request(GetBrotliDictionaryTestTransaction());
   SharedDictionaryNetworkTransaction transaction(manager,
                                                  CreateNetworkTransaction());
   transaction.SetIsSharedDictionaryReadAllowedCallback(
@@ -346,14 +434,15 @@
   EXPECT_EQ(kTestData, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, NotAllowedToUseDictionary) {
+TEST_P(SharedDictionaryNetworkTransactionTest, NotAllowedToUseDictionary) {
   DummySharedDictionaryManager manager(
       base::MakeRefCounted<DummySharedDictionaryStorage>(
           std::make_unique<DummySyncDictionary>(kTestDictionaryData)));
 
   // Override MockTransaction to check that there is no sec-available-dictionary
   // header.
-  net::MockTransaction new_mock_transaction = kBrotliDictionaryTestTransaction;
+  net::MockTransaction new_mock_transaction =
+      GetBrotliDictionaryTestTransaction();
   new_mock_transaction.handler =
       kTestTransactionHandlerWithoutAvailableDictionary;
   net::AddMockTransaction(&new_mock_transaction);
@@ -381,7 +470,7 @@
   EXPECT_EQ(kTestData, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest,
+TEST_P(SharedDictionaryNetworkTransactionTest,
        RequireKnownRootCertCheckFailure) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(
@@ -392,7 +481,8 @@
 
   // Override MockTransaction to check that there is no sec-available-dictionary
   // header.
-  net::MockTransaction new_mock_transaction = kBrotliDictionaryTestTransaction;
+  net::MockTransaction new_mock_transaction =
+      GetBrotliDictionaryTestTransaction();
   new_mock_transaction.handler =
       kTestTransactionHandlerWithoutAvailableDictionary;
   new_mock_transaction.transport_info.cert_is_issued_by_known_root = false;
@@ -422,7 +512,7 @@
   EXPECT_EQ(kTestData, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest,
+TEST_P(SharedDictionaryNetworkTransactionTest,
        RequireKnownRootCertCheckSuccess) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(
@@ -433,7 +523,8 @@
 
   // The BrotliTestTransactionHandler `new_mock_transaction.handler` will check
   // that the there is a correct sec-available-dictionary request header.
-  net::MockTransaction new_mock_transaction = kBrotliDictionaryTestTransaction;
+  net::MockTransaction new_mock_transaction =
+      GetBrotliDictionaryTestTransaction();
   new_mock_transaction.transport_info.cert_is_issued_by_known_root = true;
 
   net::AddMockTransaction(&new_mock_transaction);
@@ -461,7 +552,7 @@
   EXPECT_EQ(kTestData, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest,
+TEST_P(SharedDictionaryNetworkTransactionTest,
        RequireKnownRootCertCheckSuccessForLocalhost) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(
@@ -472,7 +563,8 @@
 
   // The BrotliTestTransactionHandler `new_mock_transaction.handler` will check
   // that the there is a correct sec-available-dictionary request header.
-  net::MockTransaction new_mock_transaction = kBrotliDictionaryTestTransaction;
+  net::MockTransaction new_mock_transaction =
+      GetBrotliDictionaryTestTransaction();
   new_mock_transaction.url = "http:///localhost:1234/test";
   new_mock_transaction.transport_info.cert_is_issued_by_known_root = false;
 
@@ -501,13 +593,14 @@
   EXPECT_EQ(kTestData, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, NoMatchingDictionary) {
+TEST_P(SharedDictionaryNetworkTransactionTest, NoMatchingDictionary) {
   DummySharedDictionaryManager manager(
       base::MakeRefCounted<DummySharedDictionaryStorage>(nullptr));
 
   // Override MockTransaction to check that there is no sec-available-dictionary
   // header.
-  net::MockTransaction new_mock_transaction = kBrotliDictionaryTestTransaction;
+  net::MockTransaction new_mock_transaction =
+      GetBrotliDictionaryTestTransaction();
   new_mock_transaction.handler =
       kTestTransactionHandlerWithoutAvailableDictionary;
   net::AddMockTransaction(&new_mock_transaction);
@@ -535,14 +628,15 @@
   EXPECT_EQ(kTestData, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, OpaqueFrameOrigin) {
+TEST_P(SharedDictionaryNetworkTransactionTest, OpaqueFrameOrigin) {
   DummySharedDictionaryManager manager(
       base::MakeRefCounted<DummySharedDictionaryStorage>(
           std::make_unique<DummySyncDictionary>(kTestDictionaryData)));
 
   // Override MockTransaction to check that there is no sec-available-dictionary
   // header.
-  net::MockTransaction new_mock_transaction = kBrotliDictionaryTestTransaction;
+  net::MockTransaction new_mock_transaction =
+      GetBrotliDictionaryTestTransaction();
   new_mock_transaction.handler =
       kTestTransactionHandlerWithoutAvailableDictionary;
   net::AddMockTransaction(&new_mock_transaction);
@@ -571,12 +665,13 @@
   EXPECT_EQ(kTestData, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, WithoutValidLoadFlag) {
+TEST_P(SharedDictionaryNetworkTransactionTest, WithoutValidLoadFlag) {
   DummySharedDictionaryManager manager(/*storage=*/nullptr);
 
   // Override MockTransaction to check that there is no sec-available-dictionary
   // header.
-  net::MockTransaction new_mock_transaction = kBrotliDictionaryTestTransaction;
+  net::MockTransaction new_mock_transaction =
+      GetBrotliDictionaryTestTransaction();
   new_mock_transaction.handler =
       kTestTransactionHandlerWithoutAvailableDictionary;
   net::AddMockTransaction(&new_mock_transaction);
@@ -610,13 +705,14 @@
   EXPECT_FALSE(manager.create_storage_called());
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, NoSbrContentEncoding) {
+TEST_P(SharedDictionaryNetworkTransactionTest, NoSbrContentEncoding) {
   DummySharedDictionaryManager manager(
       base::MakeRefCounted<DummySharedDictionaryStorage>(
           std::make_unique<DummySyncDictionary>(kTestDictionaryData)));
 
   // Override MockTransaction to remove `content-encoding: sbr`.
-  net::MockTransaction new_mock_transaction = kBrotliDictionaryTestTransaction;
+  net::MockTransaction new_mock_transaction =
+      GetBrotliDictionaryTestTransaction();
   new_mock_transaction.response_headers = "";
   net::AddMockTransaction(&new_mock_transaction);
 
@@ -646,13 +742,14 @@
   EXPECT_EQ(kBrotliEncodedDataString, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, MultipleContentEncodingWithSbr) {
+TEST_P(SharedDictionaryNetworkTransactionTest, MultipleContentEncodingWithSbr) {
   DummySharedDictionaryManager manager(
       base::MakeRefCounted<DummySharedDictionaryStorage>(
           std::make_unique<DummySyncDictionary>(kTestDictionaryData)));
 
   // Override MockTransaction to set `content-encoding: sbr, deflate`.
-  net::MockTransaction new_mock_transaction = kBrotliDictionaryTestTransaction;
+  net::MockTransaction new_mock_transaction =
+      GetBrotliDictionaryTestTransaction();
   new_mock_transaction.response_headers = "content-encoding: sbr, deflate\n";
   net::AddMockTransaction(&new_mock_transaction);
 
@@ -682,7 +779,7 @@
   EXPECT_EQ(kBrotliEncodedDataString, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest,
+TEST_P(SharedDictionaryNetworkTransactionTest,
        AsyncDictionarySuccessBeforeStartReading) {
   std::unique_ptr<DummyAsyncDictionary> dictionary =
       std::make_unique<DummyAsyncDictionary>(kTestDictionaryData);
@@ -691,7 +788,7 @@
       base::MakeRefCounted<DummySharedDictionaryStorage>(
           std::move(dictionary)));
 
-  net::MockHttpRequest request(kBrotliDictionaryTestTransaction);
+  net::MockHttpRequest request(GetBrotliDictionaryTestTransaction());
   SharedDictionaryNetworkTransaction transaction(manager,
                                                  CreateNetworkTransaction());
   transaction.SetIsSharedDictionaryReadAllowedCallback(
@@ -719,7 +816,7 @@
   EXPECT_EQ(kTestData, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest,
+TEST_P(SharedDictionaryNetworkTransactionTest,
        AsyncDictionarySuccessAfterStartReading) {
   std::unique_ptr<DummyAsyncDictionary> dictionary =
       std::make_unique<DummyAsyncDictionary>(kTestDictionaryData);
@@ -728,7 +825,7 @@
       base::MakeRefCounted<DummySharedDictionaryStorage>(
           std::move(dictionary)));
 
-  net::MockHttpRequest request(kBrotliDictionaryTestTransaction);
+  net::MockHttpRequest request(GetBrotliDictionaryTestTransaction());
   SharedDictionaryNetworkTransaction transaction(manager,
                                                  CreateNetworkTransaction());
   transaction.SetIsSharedDictionaryReadAllowedCallback(
@@ -760,7 +857,7 @@
   EXPECT_EQ(kTestData, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest,
+TEST_P(SharedDictionaryNetworkTransactionTest,
        AsyncDictionarySuccessAfterTransactionDestroy) {
   std::unique_ptr<DummyAsyncDictionary> dictionary =
       std::make_unique<DummyAsyncDictionary>(kTestDictionaryData);
@@ -769,7 +866,7 @@
       base::MakeRefCounted<DummySharedDictionaryStorage>(
           std::move(dictionary)));
 
-  net::MockHttpRequest request(kBrotliDictionaryTestTransaction);
+  net::MockHttpRequest request(GetBrotliDictionaryTestTransaction());
   std::unique_ptr<SharedDictionaryNetworkTransaction> transaction =
       std::make_unique<SharedDictionaryNetworkTransaction>(
           manager, CreateNetworkTransaction());
@@ -802,7 +899,7 @@
   EXPECT_FALSE(read_callback.have_result());
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest,
+TEST_P(SharedDictionaryNetworkTransactionTest,
        AsyncDictionaryFailureBeforeStartReading) {
   std::unique_ptr<DummyAsyncDictionary> dictionary =
       std::make_unique<DummyAsyncDictionary>(kTestDictionaryData);
@@ -811,7 +908,7 @@
       base::MakeRefCounted<DummySharedDictionaryStorage>(
           std::move(dictionary)));
 
-  net::MockHttpRequest request(kBrotliDictionaryTestTransaction);
+  net::MockHttpRequest request(GetBrotliDictionaryTestTransaction());
   SharedDictionaryNetworkTransaction transaction(manager,
                                                  CreateNetworkTransaction());
   transaction.SetIsSharedDictionaryReadAllowedCallback(
@@ -836,7 +933,7 @@
       net::test::IsError(net::ERR_DICTIONARY_LOAD_FAILED));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest,
+TEST_P(SharedDictionaryNetworkTransactionTest,
        AsyncDictionaryFailureAfterStartReading) {
   std::unique_ptr<DummyAsyncDictionary> dictionary =
       std::make_unique<DummyAsyncDictionary>(kTestDictionaryData);
@@ -845,7 +942,7 @@
       base::MakeRefCounted<DummySharedDictionaryStorage>(
           std::move(dictionary)));
 
-  net::MockHttpRequest request(kBrotliDictionaryTestTransaction);
+  net::MockHttpRequest request(GetBrotliDictionaryTestTransaction());
   SharedDictionaryNetworkTransaction transaction(manager,
                                                  CreateNetworkTransaction());
   transaction.SetIsSharedDictionaryReadAllowedCallback(
@@ -875,7 +972,7 @@
   EXPECT_EQ(net::ERR_DICTIONARY_LOAD_FAILED, read_callback.WaitForResult());
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, Restart) {
+TEST_P(SharedDictionaryNetworkTransactionTest, Restart) {
   DummySharedDictionaryManager manager(
       base::MakeRefCounted<DummySharedDictionaryStorage>(nullptr));
 
@@ -916,7 +1013,7 @@
   ASSERT_FALSE(transaction.IsReadyToRestartForAuth());
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, StopCaching) {
+TEST_P(SharedDictionaryNetworkTransactionTest, StopCaching) {
   DummySharedDictionaryManager manager(
       base::MakeRefCounted<DummySharedDictionaryStorage>(nullptr));
   SharedDictionaryNetworkTransaction transaction(manager,
@@ -926,7 +1023,7 @@
   EXPECT_TRUE(network_layer().stop_caching_called());
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, DoneReading) {
+TEST_P(SharedDictionaryNetworkTransactionTest, DoneReading) {
   DummySharedDictionaryManager manager(
       base::MakeRefCounted<DummySharedDictionaryStorage>(nullptr));
 
@@ -937,7 +1034,7 @@
   EXPECT_TRUE(network_layer().done_reading_called());
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, GetLoadState) {
+TEST_P(SharedDictionaryNetworkTransactionTest, GetLoadState) {
   DummySharedDictionaryManager manager(
       base::MakeRefCounted<DummySharedDictionaryStorage>(nullptr));
 
@@ -966,7 +1063,7 @@
   EXPECT_EQ(net::LOAD_STATE_READING_RESPONSE, transaction.GetLoadState());
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, SharedZstd) {
+TEST_P(SharedDictionaryNetworkTransactionTest, SharedZstd) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(network::features::kSharedZstd);
 
@@ -1001,7 +1098,7 @@
   EXPECT_EQ(kTestData, std::string(buf->data(), read_result));
 }
 
-TEST_F(SharedDictionaryNetworkTransactionTest, NoZstdDContentEncoding) {
+TEST_P(SharedDictionaryNetworkTransactionTest, NoZstdDContentEncoding) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(network::features::kSharedZstd);
 
@@ -1083,13 +1180,18 @@
 }
 
 class SharedDictionaryNetworkTransactionProtocolCheckTest
-    : public SharedDictionaryNetworkTransactionTest,
+    : public SharedDictionaryNetworkTransactionTestBase,
       public testing::WithParamInterface<
           std::tuple<ProtocolCheckFeatureTestCase,
                      ProtocolCheckProtocolTestCase,
                      ProtocolCheckHostTestCase>> {
  public:
-  SharedDictionaryNetworkTransactionProtocolCheckTest() {
+  SharedDictionaryNetworkTransactionProtocolCheckTest()
+      : SharedDictionaryNetworkTransactionTestBase(
+            // Protocol check logic doesn't depend on versions. So we just check
+            // the V2 behavior.
+            network::features::CompressionDictionaryTransportBackendVersion::
+                kV2) {
     std::vector<base::test::FeatureRef> enabled_features;
     std::vector<base::test::FeatureRef> disabled_features;
     if (AllowHttp1()) {
@@ -1109,7 +1211,8 @@
 
  protected:
   net::MockTransaction CreateMockTransaction() {
-    net::MockTransaction mock_transaction = kBrotliDictionaryTestTransaction;
+    net::MockTransaction mock_transaction =
+        GetBrotliDictionaryTestTransaction();
     if (IsLocalHost()) {
       mock_transaction.url = "http://localhost/test";
     }
diff --git a/services/tracing/perfetto/privacy_filtered_fields-inl.h b/services/tracing/perfetto/privacy_filtered_fields-inl.h
index a2b403181..1f33cdd 100644
--- a/services/tracing/perfetto/privacy_filtered_fields-inl.h
+++ b/services/tracing/perfetto/privacy_filtered_fields-inl.h
@@ -662,10 +662,14 @@
     kBackgroundTracingMetadataIndices,
     kBackgroundTracingMetadataComplexMessages};
 
+// Proto Message: FinchHash
+constexpr int kFinchHashIndices[] = {1, 2, -1};
+constexpr MessageInfo kFinchHash = {kFinchHashIndices, nullptr};
+
 // Proto Message: ChromeMetadataPacket
-constexpr int kChromeMetadataPacketIndices[] = {1, 2, 3, -1};
+constexpr int kChromeMetadataPacketIndices[] = {1, 2, 3, 4, -1};
 constexpr MessageInfo const* kChromeMetadataPacketComplexMessages[] = {
-    &kBackgroundTracingMetadata, nullptr, nullptr};
+    &kBackgroundTracingMetadata, nullptr, nullptr, &kFinchHash};
 constexpr MessageInfo kChromeMetadataPacket = {
     kChromeMetadataPacketIndices, kChromeMetadataPacketComplexMessages};
 
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 59a6e48..79b5861 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -6112,9 +6112,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_v122.0.6248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 122.0.6248.0",
+        "description": "Run with ash-chrome version 122.0.6249.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6124,8 +6124,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v122.0.6248.0",
-              "revision": "version:122.0.6248.0"
+              "location": "lacros_version_skew_tests_v122.0.6249.0",
+              "revision": "version:122.0.6249.0"
             }
           ],
           "dimensions": {
@@ -6262,9 +6262,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_v122.0.6248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 122.0.6248.0",
+        "description": "Run with ash-chrome version 122.0.6249.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6274,8 +6274,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v122.0.6248.0",
-              "revision": "version:122.0.6248.0"
+              "location": "lacros_version_skew_tests_v122.0.6249.0",
+              "revision": "version:122.0.6249.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index 3f79bb9f..68388b9d 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -20446,9 +20446,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_v122.0.6248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 122.0.6248.0",
+        "description": "Run with ash-chrome version 122.0.6249.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20458,8 +20458,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v122.0.6248.0",
-              "revision": "version:122.0.6248.0"
+              "location": "lacros_version_skew_tests_v122.0.6249.0",
+              "revision": "version:122.0.6249.0"
             }
           ],
           "dimensions": {
@@ -20596,9 +20596,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_v122.0.6248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 122.0.6248.0",
+        "description": "Run with ash-chrome version 122.0.6249.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20608,8 +20608,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v122.0.6248.0",
-              "revision": "version:122.0.6248.0"
+              "location": "lacros_version_skew_tests_v122.0.6249.0",
+              "revision": "version:122.0.6249.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 06d14b477..06bc6ef6 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -42428,9 +42428,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_v122.0.6248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 122.0.6248.0",
+        "description": "Run with ash-chrome version 122.0.6249.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -42439,8 +42439,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v122.0.6248.0",
-              "revision": "version:122.0.6248.0"
+              "location": "lacros_version_skew_tests_v122.0.6249.0",
+              "revision": "version:122.0.6249.0"
             }
           ],
           "dimensions": {
@@ -42578,9 +42578,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_v122.0.6248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 122.0.6248.0",
+        "description": "Run with ash-chrome version 122.0.6249.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -42589,8 +42589,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v122.0.6248.0",
-              "revision": "version:122.0.6248.0"
+              "location": "lacros_version_skew_tests_v122.0.6249.0",
+              "revision": "version:122.0.6249.0"
             }
           ],
           "dimensions": {
@@ -43902,9 +43902,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_v122.0.6248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 122.0.6248.0",
+        "description": "Run with ash-chrome version 122.0.6249.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43913,8 +43913,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v122.0.6248.0",
-              "revision": "version:122.0.6248.0"
+              "location": "lacros_version_skew_tests_v122.0.6249.0",
+              "revision": "version:122.0.6249.0"
             }
           ],
           "dimensions": {
@@ -44052,9 +44052,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_v122.0.6248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 122.0.6248.0",
+        "description": "Run with ash-chrome version 122.0.6249.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -44063,8 +44063,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v122.0.6248.0",
-              "revision": "version:122.0.6248.0"
+              "location": "lacros_version_skew_tests_v122.0.6249.0",
+              "revision": "version:122.0.6249.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.goma.fyi.json b/testing/buildbot/chromium.goma.fyi.json
index 857dad8..e81b1ea 100644
--- a/testing/buildbot/chromium.goma.fyi.json
+++ b/testing/buildbot/chromium.goma.fyi.json
@@ -1,90 +1,11 @@
 {
   "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
   "AAAAA2 See generate_buildbot_json.py to make changes": {},
-  "Mac Builder (dbg) Goma RBE Canary (clobber)": {
-    "additional_compile_targets": [
-      "all"
-    ],
-    "gtest_tests": [
-      {
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "base_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Mac-13"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "base_unittests",
-        "test_id_prefix": "ninja://base:base_unittests/"
-      },
-      {
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "content_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Mac-13"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "content_unittests",
-        "test_id_prefix": "ninja://content/test:content_unittests/"
-      }
-    ]
-  },
-  "Mac M1 Builder (dbg) Goma RBE Canary (clobber)": {
-    "additional_compile_targets": [
-      "all"
-    ],
-    "gtest_tests": [
-      {
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "base_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "arm-64",
-            "os": "Mac-11"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "base_unittests",
-        "test_id_prefix": "ninja://base:base_unittests/"
-      },
-      {
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "content_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "arm-64",
-            "os": "Mac-11"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "content_unittests",
-        "test_id_prefix": "ninja://content/test:content_unittests/"
-      }
-    ]
-  },
   "chromeos-amd64-generic-rel-goma-rbe-canary": {
     "additional_compile_targets": [
       "chromiumos_preflight"
     ]
   },
-  "ios-device-goma-rbe-canary-clobber": {
-    "additional_compile_targets": [
-      "all"
-    ]
-  },
   "linux-archive-rel-goma-rbe-ats-canary": {
     "additional_compile_targets": [
       "all"
@@ -154,42 +75,5 @@
         "test_id_prefix": "ninja://content/test:content_unittests/"
       }
     ]
-  },
-  "mac-archive-rel-goma-rbe-canary": {
-    "additional_compile_targets": [
-      "chrome"
-    ],
-    "gtest_tests": [
-      {
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "base_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Mac-13"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "base_unittests",
-        "test_id_prefix": "ninja://base:base_unittests/"
-      },
-      {
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "content_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Mac-13"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "content_unittests",
-        "test_id_prefix": "ninja://content/test:content_unittests/"
-      }
-    ]
   }
 }
diff --git a/testing/buildbot/chromium.goma.json b/testing/buildbot/chromium.goma.json
index 523aaea..33f0946 100644
--- a/testing/buildbot/chromium.goma.json
+++ b/testing/buildbot/chromium.goma.json
@@ -71,80 +71,6 @@
       }
     ]
   },
-  "Chromium Mac Goma RBE Staging": {
-    "additional_compile_targets": [
-      "chrome"
-    ],
-    "gtest_tests": [
-      {
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "base_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Mac-13"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "base_unittests",
-        "test_id_prefix": "ninja://base:base_unittests/"
-      },
-      {
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "content_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Mac-13"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "content_unittests",
-        "test_id_prefix": "ninja://content/test:content_unittests/"
-      }
-    ]
-  },
-  "Chromium Mac Goma RBE Staging (dbg)": {
-    "additional_compile_targets": [
-      "chrome"
-    ],
-    "gtest_tests": [
-      {
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "base_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Mac-13"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "base_unittests",
-        "test_id_prefix": "ninja://base:base_unittests/"
-      },
-      {
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "content_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Mac-13"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "content_unittests",
-        "test_id_prefix": "ninja://content/test:content_unittests/"
-      }
-    ]
-  },
   "chromeos-amd64-generic-rel-goma-rbe-staging": {
     "additional_compile_targets": [
       "chromiumos_preflight"
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 498102a..d76f784 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -16316,12 +16316,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_v122.0.6248.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 122.0.6248.0",
+        "description": "Run with ash-chrome version 122.0.6249.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16331,8 +16331,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v122.0.6248.0",
-              "revision": "version:122.0.6248.0"
+              "location": "lacros_version_skew_tests_v122.0.6249.0",
+              "revision": "version:122.0.6249.0"
             }
           ],
           "dimensions": {
@@ -16486,12 +16486,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_v122.0.6248.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 122.0.6248.0",
+        "description": "Run with ash-chrome version 122.0.6249.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16501,8 +16501,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v122.0.6248.0",
-              "revision": "version:122.0.6248.0"
+              "location": "lacros_version_skew_tests_v122.0.6249.0",
+              "revision": "version:122.0.6249.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 0e41a229..2a61b6d 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -2327,25 +2327,6 @@
       'content_unittests': {},
     },
 
-    'goma_mac_gtests': {
-      'base_unittests': {
-        'swarming': {
-          'dimensions': {
-            'cpu': 'x86-64',
-            'os': 'Mac-13',
-          },
-        },
-      },
-      'content_unittests': {
-        'swarming': {
-          'dimensions': {
-            'cpu': 'x86-64',
-            'os': 'Mac-13',
-          },
-        },
-      },
-    },
-
     'gpu_angle_fuchsia_unittests_isolated_scripts': {
       'angle_unittests': {
         'mixins': [
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 36a865d0..dab8280 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -323,16 +323,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 122.0.6248.0',
+    'description': 'Run with ash-chrome version 122.0.6249.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6248.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6249.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v122.0.6248.0',
-          'revision': 'version:122.0.6248.0',
+          'location': 'lacros_version_skew_tests_v122.0.6249.0',
+          'revision': 'version:122.0.6249.0',
         },
       ],
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index f12290e..57ea44f1 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -3926,30 +3926,6 @@
           'gtest_tests': 'goma_gtests',
         },
       },
-      # Due to disk shortage on Mac, we build 'chrome' instead of 'all'.
-      # See crbug.com/899425
-      'Chromium Mac Goma RBE Staging': {
-        'mixins': [
-          'mac_default_x64',
-        ],
-        'additional_compile_targets': [
-          'chrome',
-        ],
-        'test_suites': {
-          'gtest_tests': 'goma_gtests',
-        },
-      },
-      'Chromium Mac Goma RBE Staging (dbg)': {
-        'mixins': [
-          'mac_default_x64',
-        ],
-        'additional_compile_targets': [
-          'chrome',
-        ],
-        'test_suites': {
-          'gtest_tests': 'goma_gtests',
-        },
-      },
       # ChromeOS (simple chrome) builders.
       # Note:
       # chromeos-amd64-generic-rel-goma-* builders mirror targets of
@@ -3965,28 +3941,6 @@
     'name': 'chromium.goma.fyi',
     'mixins': ['chromium-tester-service-account'],
     'machines': {
-      'Mac Builder (dbg) Goma RBE Canary (clobber)': {
-        'additional_compile_targets': [
-          'all',
-        ],
-        'test_suites': {
-          'gtest_tests': 'goma_mac_gtests',
-        },
-      },
-      'Mac M1 Builder (dbg) Goma RBE Canary (clobber)': {
-        'additional_compile_targets': [
-          'all',
-        ],
-        'test_suites': {
-          'gtest_tests': 'goma_mac_gtests',
-        },
-	      'swarming': {
-          'dimensions': {
-            'cpu': 'arm-64',
-            'os': 'Mac-11',
-          },
-	      },
-      },
       # Note:
       # chromeos-amd64-generic-rel-goma-* builders mirror targets of
       # chromeos-amd64-generic-rel.
@@ -3995,11 +3949,6 @@
           'chromiumos_preflight',
         ],
       },
-      'ios-device-goma-rbe-canary-clobber': {
-        'additional_compile_targets': [
-          'all',
-        ]
-      },
       'linux-archive-rel-goma-rbe-ats-canary': {
         'additional_compile_targets': [
           'all',
@@ -4022,16 +3971,6 @@
           'gtest_tests': 'goma_gtests',
         },
       },
-      'mac-archive-rel-goma-rbe-canary': {
-        'additional_compile_targets': [
-          # Due to disk shortage, we build 'chrome' instead of 'all'.
-          # See crbug.com/899425
-          'chrome',
-        ],
-        'test_suites': {
-          'gtest_tests': 'goma_mac_gtests',
-        },
-      },
     },
   },
   {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 0b22437..1a537cb8 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -600,28 +600,6 @@
             ]
         }
     ],
-    "AomVpxUseChromeThreads": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "LibaomUseChromeThreads",
-                        "LibvpxUseChromeThreads"
-                    ]
-                }
-            ]
-        }
-    ],
     "ApnRevamp": [
         {
             "platforms": [
@@ -5514,6 +5492,31 @@
             ]
         }
     ],
+    "DeprecateUnload": [
+        {
+            "platforms": [
+                "android",
+                "android_webview",
+                "chromeos",
+                "chromeos_lacros",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "params": {
+                        "rollout_bucket": "10",
+                        "rollout_percent": "100"
+                    },
+                    "enable_features": [
+                        "DeprecateUnload"
+                    ]
+                }
+            ]
+        }
+    ],
     "DeprecatedNonStreamingDeclarativeShadowDOM": [
         {
             "platforms": [
@@ -7452,22 +7455,6 @@
             ]
         }
     ],
-    "ForceSigninFlowInProfilePicker": [
-        {
-            "platforms": [
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "ForceSigninFlowInProfilePicker"
-                    ]
-                }
-            ]
-        }
-    ],
     "ForgotPasswordFormSupport": [
         {
             "platforms": [
@@ -8774,6 +8761,26 @@
             ]
         }
     ],
+    "HttpDiskCachePrewarming": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "chromeos_lacros",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled_20240115",
+                    "enable_features": [
+                        "HttpDiskCachePrewarming"
+                    ]
+                }
+            ]
+        }
+    ],
     "HttpsFirstModeV2ForTypicallySecureUsers": [
         {
             "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 9ff9d271..f19b9260 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -1977,6 +1977,10 @@
         &kSpeculativeServiceWorkerWarmUp, "sw_warm_up_from_loading_predictor",
         true};
 
+// Warms up service worker after service worker is stopped.
+const base::FeatureParam<bool> kSpeculativeServiceWorkerWarmUpOnStopped{
+    &kSpeculativeServiceWorkerWarmUp, "sw_warm_up_on_stopped", false};
+
 BASE_FEATURE(kStartMediaStreamCaptureIndicatorInBrowser,
              "StartMediaStreamCaptureIndicatorInBrowser",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 933df54..24b309c 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -1307,6 +1307,8 @@
     kSpeculativeServiceWorkerWarmUpOnPointerdown;
 BLINK_COMMON_EXPORT extern const base::FeatureParam<bool>
     kSpeculativeServiceWorkerWarmUpFromLoadingPredictor;
+BLINK_COMMON_EXPORT extern const base::FeatureParam<bool>
+    kSpeculativeServiceWorkerWarmUpOnStopped;
 
 // Make the browser decide when to turn on the capture indicator (red button)
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(
diff --git a/third_party/blink/public/common/loader/background_resource_fetch_histograms.h b/third_party/blink/public/common/loader/background_resource_fetch_histograms.h
index e4bc636..33effa9 100644
--- a/third_party/blink/public/common/loader/background_resource_fetch_histograms.h
+++ b/third_party/blink/public/common/loader/background_resource_fetch_histograms.h
@@ -20,7 +20,8 @@
   kUnsupportedNonGetRequest = 2,
   kUnsupportedNonHttpUrlRequest = 3,
   kUnsupportedKeepAliveRequest = 4,
-  kMaxValue = kUnsupportedKeepAliveRequest,
+  kUnsupportedPrefetchOnlyDocument = 5,
+  kMaxValue = kUnsupportedPrefetchOnlyDocument,
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index 69c51728..3a1e429 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -5720,6 +5720,8 @@
       deprecated optional string headersText
       # Resource mimeType as determined by the browser.
       string mimeType
+      # Resource charset as determined by the browser (if applicable).
+      string charset
       # Refined HTTP request headers that were actually transmitted over the network.
       optional Headers requestHeaders
       # HTTP request headers text. This has been replaced by the headers in Network.requestWillBeSentExtraInfo.
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index f4a1fb8..a3a5050 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -146,6 +146,8 @@
     "mediastream/media_devices.mojom",
     "mediastream/media_stream.mojom",
     "mime/mime_registry.mojom",
+    "model_execution/model_manager.mojom",
+    "model_execution/model_session.mojom",
     "navigation/navigation_api_history_entry_arrays.mojom",
     "navigation/navigation_initiator_activation_and_ad_status.mojom",
     "navigation/navigation_policy.mojom",
diff --git a/third_party/blink/public/mojom/model_execution/OWNERS b/third_party/blink/public/mojom/model_execution/OWNERS
new file mode 100644
index 0000000..08850f4
--- /dev/null
+++ b/third_party/blink/public/mojom/model_execution/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/model_execution/model_manager.mojom b/third_party/blink/public/mojom/model_execution/model_manager.mojom
new file mode 100644
index 0000000..49043c9
--- /dev/null
+++ b/third_party/blink/public/mojom/model_execution/model_manager.mojom
@@ -0,0 +1,21 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+import "third_party/blink/public/mojom/model_execution/model_session.mojom";
+
+// The manager that could create a new session for the model.
+interface ModelManager {
+  // Returns if it is possible to create a generic session. For example, when
+  // the service in charge of model loading and session creation is not
+  // available, this should return false.
+  CanCreateGenericSession() => (bool can_create);
+  // Creates a new session and returns if the session is created successfully.
+  // Note that this could return false even if the previous
+  // `CanCreateGenericSession()` returns true, because some errors can only
+  // occur when we actually create the generic session.
+  CreateGenericSession(pending_receiver<blink.mojom.ModelGenericSession> session)
+    => (bool success);
+};
diff --git a/third_party/blink/public/mojom/model_execution/model_session.mojom b/third_party/blink/public/mojom/model_execution/model_session.mojom
new file mode 100644
index 0000000..e789a95
--- /dev/null
+++ b/third_party/blink/public/mojom/model_execution/model_session.mojom
@@ -0,0 +1,32 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+// The status of the ModelStreamingResponder response.
+// TODO(leimy): return more information about the erroneous case.
+enum ModelStreamingResponseStatus {
+  // There response is not fully streamed back yet, and the interface will
+  // remain open.
+  kOngoing,
+  // The ModelStreamingResponder completes and closes.
+  kComplete,
+  // The ModelStreamingResponder closes with some errors.
+  kError,
+};
+
+// The responder provides methods for the session to return the execution
+// response in a streaming manner.
+interface ModelStreamingResponder {
+  // This is called when there is a new chunk of data available for
+  // streaming, or when the response is fully streamed, or when there are
+  // some errors.
+  OnResponse(ModelStreamingResponseStatus status, string? text);
+};
+
+// A session for a model that allows executing an input and streaming the output.
+interface ModelGenericSession {
+  // Executes model on the given input.
+  Execute(string input, pending_remote<ModelStreamingResponder> responder);
+};
diff --git a/third_party/blink/public/platform/url_loader_throttle_provider.h b/third_party/blink/public/platform/url_loader_throttle_provider.h
index c1040b86..c6c8df6 100644
--- a/third_party/blink/public/platform/url_loader_throttle_provider.h
+++ b/third_party/blink/public/platform/url_loader_throttle_provider.h
@@ -29,19 +29,55 @@
   kWorker
 };
 
+// How Clone() and CreateThrottles() are called:
+//
+// Frame subresource fetches:
+// - [Main Thread]
+//   - Startup: Create a URLLoaderThrottleProvider for all frames to share.
+//   - If BackgroundResourceFetch is off or the resource is not handled by
+//     BackgroundURLLoader, call CreateThrottles() (per request).
+//   - First supported BackgroundURLLoader request: Clone() provider and move it
+//     to the background thread. Call CreateThrottles() for subsequent requests
+//     on the background thread.
+//
+// Dedicated/Shared Worker resource fetches:
+// - [Main Thread]
+//    - Create a URLLoaderThrottleProvider and pass it to the worker thread.
+// - [Worker Thread]
+//    - Call CreateThrottles() for worker initiated resource fetch requests.
+//
+// Service Worker resource fetches:
+// - [Initiator Thread]
+//    - Create a URLLoaderThrottleProvider and pass it to the worker thread.
+// - [Worker Thread]
+//    - Call CreateThrottles() for worker initiated resource fetch requests.
+//
+// Nested Worker resource fetches:
+// - [Initiator Worker Thread]
+//    - Clone() the existing URLLoaderThrottleProvider and pass it to the nested
+//      worker thread.
+// - [Nested Worker Thread]
+//    - Call CreateThrottles() for each resource fetch request initiated by the
+//      nested worker.
+//
+// Note: BackgroundResourceFetch is not supported for worker resource fetches.
+//
 // TODO(crbug.com/1379780): This class name should have Web prefix according to
 // third_party/blink/public/README.md#naming-conventions
 class BLINK_PLATFORM_EXPORT URLLoaderThrottleProvider {
  public:
   virtual ~URLLoaderThrottleProvider() = default;
 
-  // Used to copy a URLLoaderThrottleProvider between worker threads.
+  // Used to copy a URLLoaderThrottleProvider between worker threads, and to
+  // copy a URLLoaderThrottleProvider for the BackgroundResourceFetch feature.
   virtual std::unique_ptr<URLLoaderThrottleProvider> Clone() = 0;
 
-  // For frame requests this is called on the main thread. Dedicated, shared and
-  // service workers call it on the worker thread. `local_frame_token` will be
-  // set to the corresponding frame for frame and dedicated worker requests,
-  // otherwise it will be not be set.
+  // For frame requests, this is called on the main thread if
+  // BackgroundResourceFetch feature is disabled. Otherwise, it is called on the
+  // background thread for some types of requests.
+  // Dedicated, shared and service workers call it on the worker thread.
+  //`local_frame_token` will be set to the corresponding frame for frame and
+  // dedicated worker requests, otherwise it will not be set.
   virtual WebVector<std::unique_ptr<URLLoaderThrottle>> CreateThrottles(
       base::optional_ref<const LocalFrameToken> local_frame_token,
       const network::ResourceRequest& request) = 0;
diff --git a/third_party/blink/public/platform/web_background_resource_fetch_assets.h b/third_party/blink/public/platform/web_background_resource_fetch_assets.h
index 6efb3ec..a98a8ea7 100644
--- a/third_party/blink/public/platform/web_background_resource_fetch_assets.h
+++ b/third_party/blink/public/platform/web_background_resource_fetch_assets.h
@@ -6,6 +6,8 @@
 #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_BACKGROUND_RESOURCE_FETCH_ASSETS_H_
 
 #include "base/memory/ref_counted.h"
+#include "third_party/blink/public/common/tokens/tokens.h"
+#include "third_party/blink/public/platform/url_loader_throttle_provider.h"
 #include "third_party/blink/public/platform/web_common.h"
 
 namespace base {
@@ -31,6 +33,10 @@
   // the background thread.
   virtual scoped_refptr<network::SharedURLLoaderFactory> GetLoaderFactory() = 0;
 
+  virtual URLLoaderThrottleProvider* GetThrottleProvider() = 0;
+
+  virtual const blink::LocalFrameToken& GetLocalFrameToken() = 0;
+
  protected:
   friend class base::RefCountedThreadSafe<WebBackgroundResourceFetchAssets>;
   virtual ~WebBackgroundResourceFetchAssets() = default;
diff --git a/third_party/blink/public/web/modules/credentialmanagement/throttle_helper.h b/third_party/blink/public/web/modules/credentialmanagement/throttle_helper.h
index 11777236..0a49ec5e 100644
--- a/third_party/blink/public/web/modules/credentialmanagement/throttle_helper.h
+++ b/third_party/blink/public/web/modules/credentialmanagement/throttle_helper.h
@@ -5,11 +5,12 @@
 #ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_CREDENTIALMANAGEMENT_THROTTLE_HELPER_H_
 #define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_CREDENTIALMANAGEMENT_THROTTLE_HELPER_H_
 
+#include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/blink/public/platform/web_common.h"
 
 namespace url {
 class Origin;
-}
+}  // namespace url
 
 namespace blink {
 
@@ -17,13 +18,13 @@
 enum class IdpSigninStatus;
 }  // namespace mojom
 
-class WebLocalFrame;
-
 // Sets the identity provider (IDP) signin state of the given |origin| to
 // |status|. This is meant for use with IdentityUrlLoaderThrottle.
-BLINK_MODULES_EXPORT void SetIdpSigninStatus(WebLocalFrame* frame,
-                                             const url::Origin& origin,
-                                             mojom::IdpSigninStatus status);
+// This method must be called on the main thread.
+BLINK_MODULES_EXPORT void SetIdpSigninStatus(
+    const blink::LocalFrameToken& local_frame_token,
+    const url::Origin& origin,
+    mojom::IdpSigninStatus status);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
index 112c730..a3d4f0a 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
@@ -379,7 +379,8 @@
         cache_handler->SetCachedMetadata(
             code_cache_host, V8CodeCache::TagForCodeCache(cache_handler), data,
             length);
-        base::UmaHistogramTimes("V8.ProduceCodeCache", timer.Elapsed());
+        base::UmaHistogramMicrosecondsTimes("V8.ProduceCodeCacheMicroseconds",
+                                            timer.Elapsed());
       }
 
       TRACE_EVENT_END1(kTraceEventCategoryGroup, trace_name, "data",
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index bbeba4d..ad0cae79 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -1357,6 +1357,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gamepad_haptics_result.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gamepad_mapping_type.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gamepad_mapping_type.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_generic_model_availability.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_generic_model_availability.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_address_mode.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_address_mode.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_auto_layout_mode.cc",
@@ -2340,6 +2342,10 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_operand.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_mojo.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_mojo.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_model_generic_session.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_model_generic_session.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_model_manager.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_model_manager.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_navigation_preload_manager.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_navigation_preload_manager.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_navigator.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni
index 0ea9830..b23f500 100644
--- a/third_party/blink/renderer/bindings/idl_in_modules.gni
+++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -489,6 +489,9 @@
   "//third_party/blink/renderer/modules/ml/webnn/ml_operand.idl",
   "//third_party/blink/renderer/modules/ml/webnn/ml_operand_descriptor.idl",
   "//third_party/blink/renderer/modules/ml/worker_navigator_ml.idl",
+  "//third_party/blink/renderer/modules/model_execution/model_generic_session.idl",
+  "//third_party/blink/renderer/modules/model_execution/model_manager.idl",
+  "//third_party/blink/renderer/modules/model_execution/window_model.idl",
   "//third_party/blink/renderer/modules/mojo/mojo_file_system_access.idl",
   "//third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.idl",
   "//third_party/blink/renderer/modules/netinfo/navigator_network_information.idl",
diff --git a/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc b/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
index 20c69eef..15dd789 100644
--- a/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
+++ b/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
@@ -419,10 +419,10 @@
       FirstLetterPseudoElement::FirstLetterLength(old_text, preserve_breaks);
 
   // In case of inline level content made of punctuation, we use
-  // first_letter_text length instead of FirstLetterLength.
+  // the whole text length instead of FirstLetterLength.
   if (IsParentInlineLayoutObject(first_letter_text) && length == 0 &&
-      first_letter_text->TransformedTextLength()) {
-    length = first_letter_text->TransformedTextLength();
+      old_text.length()) {
+    length = old_text.length();
   }
 
   unsigned remaining_length = old_text.length() - length;
diff --git a/third_party/blink/renderer/core/editing/element_inner_text.cc b/third_party/blink/renderer/core/editing/element_inner_text.cc
index f70515f..6e32730 100644
--- a/third_party/blink/renderer/core/editing/element_inner_text.cc
+++ b/third_party/blink/renderer/core/editing/element_inner_text.cc
@@ -242,7 +242,7 @@
 
 void ElementInnerTextCollector::ProcessLayoutText(const LayoutText& layout_text,
                                                   const Text& text_node) {
-  if (layout_text.TransformedTextLength() == 0) {
+  if (layout_text.HasEmptyText()) {
     return;
   }
   if (layout_text.Style()->Visibility() != EVisibility::kVisible) {
@@ -407,7 +407,7 @@
     return;
   const LayoutText& layout_text = *node.GetLayoutObject();
   if (LayoutText* first_letter_part = layout_text.GetFirstLetterPart()) {
-    if (layout_text.TransformedTextLength() == 0 ||
+    if (layout_text.HasEmptyText() ||
         OffsetMapping::GetInlineFormattingContextOf(layout_text) !=
             OffsetMapping::GetInlineFormattingContextOf(*first_letter_part)) {
       // "::first-letter" with "float" reach here.
diff --git a/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.cc b/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.cc
index bcb24f97..3e8f7082 100644
--- a/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.cc
+++ b/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.cc
@@ -24,6 +24,7 @@
 // Resolves kMaxOffset to an actual number. Should simply return |dom_length|
 // when we can handle text-transform correctly.
 unsigned CalculateMaxOffset(const Text& text) {
+  DCHECK(!RuntimeEnabledFeatures::OffsetMappingUnitVariableEnabled());
   DCHECK(text.GetLayoutObject());
   unsigned dom_length = text.data().length();
   unsigned layout_length;
@@ -189,7 +190,11 @@
 void TextIteratorTextNodeHandler::HandleTextNodeStartFrom(
     const Text* node,
     unsigned start_offset) {
-  HandleTextNodeInRange(node, start_offset, kMaxOffset);
+  unsigned end_offset =
+      RuntimeEnabledFeatures::OffsetMappingUnitVariableEnabled()
+          ? node->data().length()
+          : kMaxOffset;
+  HandleTextNodeInRange(node, start_offset, end_offset);
 }
 
 void TextIteratorTextNodeHandler::HandleTextNodeEndAt(const Text* node,
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
index 46b8eb9..309e642 100644
--- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -1027,12 +1027,18 @@
       break;
   }
 
-  // Use mime type from cached resource in case the one in response is empty
-  // or the response is a 304 Not Modified.
+  // Use mime type and charset from cached resource in case the one in response
+  // is empty or the response is a 304 Not Modified.
   String mime_type = response.MimeType();
-  if (cached_resource &&
-      (mime_type.empty() || response.HttpStatusCode() == 304))
-    mime_type = cached_resource->GetResponse().MimeType();
+  String charset = response.TextEncodingName();
+  if (cached_resource) {
+    if (mime_type.empty() || response.HttpStatusCode() == 304) {
+      mime_type = cached_resource->GetResponse().MimeType();
+    }
+    if (charset.empty() || response.HttpStatusCode() == 304) {
+      charset = cached_resource->GetResponse().TextEncodingName();
+    }
+  }
 
   if (is_empty)
     *is_empty = !status && mime_type.empty() && !headers_map.size();
@@ -1044,6 +1050,7 @@
           .setStatusText(status_text)
           .setHeaders(BuildObjectForHeaders(headers_map))
           .setMimeType(mime_type)
+          .setCharset(charset)
           .setConnectionReused(response.ConnectionReused())
           .setConnectionId(response.ConnectionID())
           .setEncodedDataLength(encoded_data_length)
diff --git a/third_party/blink/renderer/core/layout/absolute_utils.cc b/third_party/blink/renderer/core/layout/absolute_utils.cc
index b460303..c320f40 100644
--- a/third_party/blink/renderer/core/layout/absolute_utils.cc
+++ b/third_party/blink/renderer/core/layout/absolute_utils.cc
@@ -394,6 +394,9 @@
     AnchorEvaluatorImpl* anchor_evaluator) {
   InsetArea inset_area;
   if (!style.GetInsetArea().IsNone() && anchor_evaluator->HasDefaultAnchor()) {
+    // We only need to know if the inset-area is 'auto' or not below, but need
+    // to consider writing direction as the inset-area falls back to 'auto' if
+    // the axes are not orthogonal.
     inset_area = style.GetInsetArea().ToPhysical(container_writing_direction,
                                                  self_writing_direction);
   }
@@ -401,47 +404,47 @@
   // `direction`.
   const PhysicalSize available_size = ToPhysicalSize(
       available_logical_size, self_writing_direction.GetWritingMode());
-  const Length& left_length =
-      style.UsedLeft().IsAuto() ? inset_area.UsedLeft() : style.UsedLeft();
   std::optional<LayoutUnit> left;
-  if (!left_length.IsAuto()) {
+  if (const Length& left_length = style.UsedLeft(); !left_length.IsAuto()) {
     anchor_evaluator->SetAxis(/* is_y_axis */ false,
                               /* is_right_or_bottom */ false,
                               available_size.width);
     left = MinimumValueForLength(left_length, available_size.width,
                                  anchor_evaluator);
+  } else if (!inset_area.IsNone()) {
+    left = LayoutUnit();
   }
   std::optional<LayoutUnit> right;
-  const Length& right_length =
-      style.UsedRight().IsAuto() ? inset_area.UsedRight() : style.UsedRight();
-  if (!right_length.IsAuto()) {
+  if (const Length& right_length = style.UsedRight(); !right_length.IsAuto()) {
     anchor_evaluator->SetAxis(/* is_y_axis */ false,
                               /* is_right_or_bottom */ true,
                               available_size.width);
     right = MinimumValueForLength(right_length, available_size.width,
                                   anchor_evaluator);
+  } else if (!inset_area.IsNone()) {
+    right = LayoutUnit();
   }
 
   std::optional<LayoutUnit> top;
-  const Length& top_length =
-      style.UsedTop().IsAuto() ? inset_area.UsedTop() : style.UsedTop();
-  if (!top_length.IsAuto()) {
+  if (const Length& top_length = style.UsedTop(); !top_length.IsAuto()) {
     anchor_evaluator->SetAxis(/* is_y_axis */ true,
                               /* is_right_or_bottom */ false,
                               available_size.height);
     top = MinimumValueForLength(top_length, available_size.height,
                                 anchor_evaluator);
+  } else if (!inset_area.IsNone()) {
+    top = LayoutUnit();
   }
   std::optional<LayoutUnit> bottom;
-  const Length& bottom_length = style.UsedBottom().IsAuto()
-                                    ? inset_area.UsedBottom()
-                                    : style.UsedBottom();
-  if (!bottom_length.IsAuto()) {
+  if (const Length& bottom_length = style.UsedBottom();
+      !bottom_length.IsAuto()) {
     anchor_evaluator->SetAxis(/* is_y_axis */ true,
                               /* is_right_or_bottom */ true,
                               available_size.height);
     bottom = MinimumValueForLength(bottom_length, available_size.height,
                                    anchor_evaluator);
+  } else if (!inset_area.IsNone()) {
+    bottom = LayoutUnit();
   }
 
   // Convert the physical insets to logical.
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_rect.h b/third_party/blink/renderer/core/layout/geometry/logical_rect.h
index e9c6e40..20d0e0db 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_rect.h
+++ b/third_party/blink/renderer/core/layout/geometry/logical_rect.h
@@ -92,6 +92,13 @@
     size.block_size += block_start + block_end;
   }
 
+  void ContractEdges(LayoutUnit block_start,
+                     LayoutUnit inline_end,
+                     LayoutUnit block_end,
+                     LayoutUnit inline_start) {
+    ExpandEdges(-block_start, -inline_end, -block_end, -inline_start);
+  }
+
   // Update inline-start offset without changing the inline-end offset.
   void ShiftInlineStartEdgeTo(LayoutUnit edge) {
     LayoutUnit new_size = (InlineEndOffset() - edge).ClampNegativeToZero();
diff --git a/third_party/blink/renderer/core/layout/inline/inline_item.cc b/third_party/blink/renderer/core/layout/inline/inline_item.cc
index 6ce8c8f..113e0b6 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_item.cc
+++ b/third_party/blink/renderer/core/layout/inline/inline_item.cc
@@ -118,13 +118,6 @@
 
 InlineItem::~InlineItem() = default;
 
-const ShapeResult* InlineItem::TextShapeResultNotSharedSlow() {
-  DCHECK(shape_result_);
-  DCHECK(!shape_result_->HasOneRef());
-  shape_result_ = ShapeResult::Create(*shape_result_);
-  return shape_result_.get();
-}
-
 void InlineItem::ComputeBoxProperties() {
   DCHECK(!is_empty_item_);
 
diff --git a/third_party/blink/renderer/core/layout/inline/inline_item.h b/third_party/blink/renderer/core/layout/inline/inline_item.h
index 526cfb4b..0428ae2 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_item.h
+++ b/third_party/blink/renderer/core/layout/inline/inline_item.h
@@ -90,10 +90,10 @@
   }
 
   const ShapeResult* TextShapeResult() const { return shape_result_.get(); }
-  const ShapeResult* TextShapeResultNotShared() {
-    return !shape_result_ || shape_result_->HasOneRef()
-               ? shape_result_.get()
-               : TextShapeResultNotSharedSlow();
+  ShapeResult* CloneTextShapeResult() {
+    scoped_refptr<ShapeResult> clone = ShapeResult::Create(*shape_result_);
+    shape_result_ = clone;
+    return clone.get();
   }
   bool IsUnsafeToReuseShapeResult() const {
     return is_unsafe_to_reuse_shape_result_;
@@ -265,7 +265,6 @@
   void Trace(Visitor* visitor) const;
 
  private:
-  const ShapeResult* TextShapeResultNotSharedSlow();
   void ComputeBoxProperties();
 
   unsigned start_offset_;
diff --git a/third_party/blink/renderer/core/layout/inline/inline_text_auto_space.cc b/third_party/blink/renderer/core/layout/inline/inline_text_auto_space.cc
index 90c85cd..12560ea 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_text_auto_space.cc
+++ b/third_party/blink/renderer/core/layout/inline/inline_text_auto_space.cc
@@ -94,14 +94,8 @@
     }
     DCHECK(last_item_);
 
-    // TODO(https://crbug.com/1463890): Using `const_cast` does not look good,
-    // consider refactoring.
-    // TODO(https://crbug.com/1463890): Instead of recreating a new
-    // `ShapeResult`, maybe we can reuse the `ShapeResult` and skip the applying
-    // text-space step.
     InlineItem* item = const_cast<InlineItem*>(last_item_);
-    ShapeResult* shape_result =
-        const_cast<ShapeResult*>(item->TextShapeResultNotShared());
+    ShapeResult* shape_result = item->CloneTextShapeResult();
     DCHECK(shape_result);
     shape_result->ApplyTextAutoSpacing(offsets_with_spacing_);
     item->SetUnsafeToReuseShapeResult();
diff --git a/third_party/blink/renderer/core/layout/out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/out_of_flow_layout_part.cc
index 74f8bce..ef6a9c1 100644
--- a/third_party/blink/renderer/core/layout/out_of_flow_layout_part.cc
+++ b/third_party/blink/renderer/core/layout/out_of_flow_layout_part.cc
@@ -591,6 +591,119 @@
   }
 }
 
+const OutOfFlowLayoutPart::ContainingBlockInfo
+OutOfFlowLayoutPart::ApplyInsetArea(
+    const InsetArea& inset_area,
+    const ContainingBlockInfo& container_info,
+    const LogicalOofPositionedNode& candidate,
+    const LogicalAnchorQueryMap* anchor_queries) {
+  // A non-'none' inset-area modifies an anchor positioned element's absolute
+  // position containing block. This method returns a modified
+  // ContainingBlockInfo with the rect adjusted by inset-area.
+  DCHECK(!inset_area.IsNone());
+  const LayoutObject* implicit_anchor = nullptr;
+  if (Element* element = DynamicTo<Element>(candidate.Node().GetDOMNode())) {
+    if (element->ImplicitAnchorElement()) {
+      implicit_anchor = element->ImplicitAnchorElement()->GetLayoutObject();
+    }
+  }
+
+  absl::optional<AnchorEvaluatorImpl> anchor_evaluator_storage;
+  CreateAnchorEvaluator(
+      anchor_evaluator_storage, container_info, candidate.Node().Style(),
+      *candidate.Node().GetLayoutBox(), anchor_queries, implicit_anchor);
+  AnchorEvaluatorImpl* anchor_evaluator = &*anchor_evaluator_storage;
+  if (!anchor_evaluator) {
+    return container_info;
+  }
+
+  float top = 0;
+  float bottom = 0;
+  float left = 0;
+  float right = 0;
+
+  const bool y_axis = true;
+  const bool x_axis = false;
+  const bool right_or_bottom = true;
+  const bool left_or_top = false;
+
+  PhysicalSize container_physical_content_size = ToPhysicalSize(
+      container_info.rect.size, GetConstraintSpace().GetWritingMode());
+  LayoutUnit available_width = container_physical_content_size.width;
+  LayoutUnit available_height = container_physical_content_size.height;
+
+  // The InsetArea::Used*() methods either return a 0px length or an anchor()
+  // function, using top/left/right/bottom, to adjust the containing block to
+  // align with either of the physical edges of the default anchor.
+  //
+  // IsCalculated() means the value is an anchor() function, otherwise the inset
+  // adjustment is already set to 0 above.
+  if (inset_area.UsedTop().IsCalculated()) {
+    anchor_evaluator->SetAxis(y_axis, left_or_top, available_height);
+    top = inset_area.UsedTop().NonNanCalculatedValue(available_height,
+                                                     anchor_evaluator);
+  }
+  if (inset_area.UsedBottom().IsCalculated()) {
+    anchor_evaluator->SetAxis(y_axis, right_or_bottom, available_height);
+    bottom = inset_area.UsedBottom().NonNanCalculatedValue(available_height,
+                                                           anchor_evaluator);
+  }
+  if (inset_area.UsedLeft().IsCalculated()) {
+    anchor_evaluator->SetAxis(x_axis, left_or_top, available_width);
+    left = inset_area.UsedLeft().NonNanCalculatedValue(available_width,
+                                                       anchor_evaluator);
+  }
+  if (inset_area.UsedRight().IsCalculated()) {
+    anchor_evaluator->SetAxis(x_axis, right_or_bottom, available_width);
+    right = inset_area.UsedRight().NonNanCalculatedValue(available_width,
+                                                         anchor_evaluator);
+  }
+
+  PhysicalToLogical converter(container_info.writing_direction, top, right,
+                              bottom, left);
+  ContainingBlockInfo adjusted_container_info(container_info);
+
+  // Reduce the container size and adjust the offset based on the inset-area.
+  adjusted_container_info.rect.ContractEdges(
+      LayoutUnit(converter.BlockStart()), LayoutUnit(converter.InlineEnd()),
+      LayoutUnit(converter.BlockEnd()), LayoutUnit(converter.InlineStart()));
+
+  // For 'center' values (aligned with start and end anchor sides), the
+  // containing block is aligned and sized with the anchor, regardless of
+  // whether it's/ inside the original containing block or not. Otherwise,
+  // ContractEdges above might have created a negative size if the inset-area is
+  // aligned with an anchor side outside the containing block.
+  if (adjusted_container_info.rect.size.inline_size < LayoutUnit()) {
+    DCHECK(converter.InlineStart() == LayoutUnit() ||
+           converter.InlineEnd() == LayoutUnit())
+        << "If aligned to both anchor edges, the size should never be "
+           "negative.";
+    // Collapse the inline size to 0 and align with the single anchor edge
+    // defined by the inset-area.
+    if (converter.InlineStart() == LayoutUnit()) {
+      DCHECK(converter.InlineEnd() != LayoutUnit());
+      adjusted_container_info.rect.offset.inline_offset +=
+          adjusted_container_info.rect.size.inline_size;
+    }
+    adjusted_container_info.rect.size.inline_size = LayoutUnit();
+  }
+  if (adjusted_container_info.rect.size.block_size < LayoutUnit()) {
+    DCHECK(converter.BlockStart() == LayoutUnit() ||
+           converter.BlockEnd() == LayoutUnit())
+        << "If aligned to both anchor edges, the size should never be "
+           "negative.";
+    // Collapse the block size to 0 and align with the single anchor edge
+    // defined by the inset-area.
+    if (converter.BlockStart() == LayoutUnit()) {
+      DCHECK(converter.BlockEnd() != LayoutUnit());
+      adjusted_container_info.rect.offset.block_offset +=
+          adjusted_container_info.rect.size.block_size;
+    }
+    adjusted_container_info.rect.size.block_size = LayoutUnit();
+  }
+  return adjusted_container_info;
+}
+
 // Retrieve the stored ContainingBlockInfo needed for placing positioned nodes.
 // When fragmenting, the ContainingBlockInfo is not stored ahead of time and
 // must be generated on demand. The reason being that during fragmentation, we
@@ -1006,11 +1119,12 @@
                                  conainer_converter);
         }
 
-        NodeInfo node_info = SetupNodeInfo(candidate);
+        LogicalAnchorQueryMap* anchor_query_map =
+            needs_anchor_queries ? &*anchor_queries : nullptr;
+        NodeInfo node_info = SetupNodeInfo(candidate, anchor_query_map);
         NodeToLayout node_to_layout = {
-            node_info,
-            CalculateOffset(node_info, /* is_first_run */ false,
-                            needs_anchor_queries ? &*anchor_queries : nullptr)};
+            node_info, CalculateOffset(node_info, /* is_first_run */ false,
+                                       anchor_query_map)};
         const LayoutResult* result = LayoutOOFNode(node_to_layout);
         PhysicalBoxStrut physical_margins =
             node_to_layout.offset_info.node_dimensions.margins
@@ -1441,7 +1555,8 @@
           }
         }
 
-        NodeInfo node_info = SetupNodeInfo(descendant);
+        NodeInfo node_info =
+            SetupNodeInfo(descendant, &stitched_anchor_queries);
         NodeToLayout node_to_layout = {
             node_info, CalculateOffset(node_info, /* is_first_run */ true,
                                        &stitched_anchor_queries)};
@@ -1591,8 +1706,46 @@
   }
 }
 
+void OutOfFlowLayoutPart::CreateAnchorEvaluator(
+    absl::optional<AnchorEvaluatorImpl>& anchor_evaluator_storage,
+    const ContainingBlockInfo& container_info,
+    const ComputedStyle& candidate_style,
+    const LayoutBox& candidate_layout_box,
+    const LogicalAnchorQueryMap* anchor_queries,
+    const LayoutObject* implicit_anchor) {
+  LogicalSize container_content_size = container_info.rect.size;
+  PhysicalSize container_physical_content_size = ToPhysicalSize(
+      container_content_size, GetConstraintSpace().GetWritingMode());
+  const WritingModeConverter container_converter(
+      container_info.writing_direction, container_physical_content_size);
+  const WritingDirectionMode candidate_writing_direction =
+      candidate_style.GetWritingDirection();
+  if (anchor_queries) {
+    // When the containing block is block-fragmented, the |container_builder_|
+    // is the fragmentainer, not the containing block, and the coordinate system
+    // is stitched. Use the given |anchor_query|.
+    const LayoutObject* css_containing_block = candidate_layout_box.Container();
+    CHECK(css_containing_block);
+    anchor_evaluator_storage.emplace(
+        candidate_layout_box, *anchor_queries, candidate_style.AnchorDefault(),
+        implicit_anchor, *css_containing_block, container_converter,
+        candidate_writing_direction,
+        container_converter.ToPhysical(container_info.rect).offset);
+  } else if (const LogicalAnchorQuery* anchor_query =
+                 container_builder_->AnchorQuery()) {
+    // Otherwise the |container_builder_| is the containing block.
+    anchor_evaluator_storage.emplace(
+        candidate_layout_box, *anchor_query, candidate_style.AnchorDefault(),
+        implicit_anchor, container_converter, candidate_writing_direction,
+        container_converter.ToPhysical(container_info.rect).offset);
+  } else {
+    anchor_evaluator_storage.emplace();
+  }
+}
+
 OutOfFlowLayoutPart::NodeInfo OutOfFlowLayoutPart::SetupNodeInfo(
-    const LogicalOofPositionedNode& oof_node) {
+    const LogicalOofPositionedNode& oof_node,
+    const LogicalAnchorQueryMap* anchor_queries) {
   BlockNode node = oof_node.Node();
   const PhysicalFragment* containing_block_fragment =
       oof_node.is_for_fragmentation
@@ -1621,9 +1774,15 @@
   }
 #endif
 
-  const ContainingBlockInfo container_info = GetContainingBlockInfo(oof_node);
+  ContainingBlockInfo container_info = GetContainingBlockInfo(oof_node);
   const ComputedStyle& oof_style = node.Style();
   const auto oof_writing_direction = oof_style.GetWritingDirection();
+  const InsetArea inset_area = oof_style.GetInsetArea().ToPhysical(
+      container_info.writing_direction, oof_style.GetWritingDirection());
+  if (!inset_area.IsNone()) {
+    container_info =
+        ApplyInsetArea(inset_area, container_info, oof_node, anchor_queries);
+  }
 
   LogicalSize container_content_size = container_info.rect.size;
   PhysicalSize container_physical_content_size = ToPhysicalSize(
@@ -1888,31 +2047,9 @@
   }
 
   absl::optional<AnchorEvaluatorImpl> anchor_evaluator_storage;
-  const WritingModeConverter container_converter(
-      container_writing_direction, node_info.container_physical_content_size);
-  if (anchor_queries) {
-    // When the containing block is block-fragmented, the |container_builder_|
-    // is the fragmentainer, not the containing block, and the coordinate system
-    // is stitched. Use the given |anchor_query|.
-    const LayoutObject* css_containing_block =
-        node_info.node.GetLayoutBox()->Container();
-    DCHECK(css_containing_block);
-    anchor_evaluator_storage.emplace(
-        *node_info.node.GetLayoutBox(), *anchor_queries,
-        candidate_style.AnchorDefault(), implicit_anchor, *css_containing_block,
-        container_converter, candidate_writing_direction,
-        container_converter.ToPhysical(node_info.container_info.rect).offset);
-  } else if (const LogicalAnchorQuery* anchor_query =
-                 container_builder_->AnchorQuery()) {
-    // Otherwise the |container_builder_| is the containing block.
-    anchor_evaluator_storage.emplace(
-        *node_info.node.GetLayoutBox(), *anchor_query,
-        candidate_style.AnchorDefault(), implicit_anchor, container_converter,
-        candidate_writing_direction,
-        container_converter.ToPhysical(node_info.container_info.rect).offset);
-  } else {
-    anchor_evaluator_storage.emplace();
-  }
+  CreateAnchorEvaluator(anchor_evaluator_storage, node_info.container_info,
+                        candidate_style, *node_info.node.GetLayoutBox(),
+                        anchor_queries, implicit_anchor);
   AnchorEvaluatorImpl* anchor_evaluator = &*anchor_evaluator_storage;
 
   const LogicalOofInsets insets = ComputeOutOfFlowInsets(
diff --git a/third_party/blink/renderer/core/layout/out_of_flow_layout_part.h b/third_party/blink/renderer/core/layout/out_of_flow_layout_part.h
index 72bf61e4..d0a29836 100644
--- a/third_party/blink/renderer/core/layout/out_of_flow_layout_part.h
+++ b/third_party/blink/renderer/core/layout/out_of_flow_layout_part.h
@@ -303,7 +303,22 @@
       bool outer_context_has_fixedpos_container = false,
       HeapVector<MulticolChildInfo>* multicol_children = nullptr);
 
-  NodeInfo SetupNodeInfo(const LogicalOofPositionedNode& oof_node);
+  void CreateAnchorEvaluator(
+      absl::optional<AnchorEvaluatorImpl>& anchor_evaluator_storage,
+      const ContainingBlockInfo& container_info,
+      const ComputedStyle& candidate_style,
+      const LayoutBox& candidate_layout_box,
+      const LogicalAnchorQueryMap* anchor_queries,
+      const LayoutObject* implicit_anchor);
+
+  const ContainingBlockInfo ApplyInsetArea(
+      const InsetArea& inset_area,
+      const ContainingBlockInfo& container_info,
+      const LogicalOofPositionedNode& candidate,
+      const LogicalAnchorQueryMap* anchor_queries);
+
+  NodeInfo SetupNodeInfo(const LogicalOofPositionedNode& oof_node,
+                         const LogicalAnchorQueryMap* anchor_queries);
 
   const LayoutResult* LayoutOOFNode(
       NodeToLayout& oof_node_to_layout,
diff --git a/third_party/blink/renderer/core/loader/DEPS b/third_party/blink/renderer/core/loader/DEPS
index 88e27bf..14e3561 100644
--- a/third_party/blink/renderer/core/loader/DEPS
+++ b/third_party/blink/renderer/core/loader/DEPS
@@ -34,6 +34,7 @@
   "+base/no_destructor.h",
   "+base/strings/utf_string_conversions.h",
   "+services/network/public/cpp/client_hints.h",
+  "+services/network/public/cpp/shared_dictionary_encoding_names.h",
   "+services/network/public/cpp/shared_url_loader_factory.h",
   "+services/network/public/cpp/wrapper_shared_url_loader_factory.h",
   "+url/url_features.h",
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 9129390..059d39e 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -46,6 +46,7 @@
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/network/public/cpp/client_hints.h"
 #include "services/network/public/cpp/header_util.h"
+#include "services/network/public/cpp/shared_dictionary_encoding_names.h"
 #include "services/network/public/cpp/web_sandbox_flags.h"
 #include "services/network/public/mojom/url_response_head.mojom-shared.h"
 #include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
@@ -3136,9 +3137,11 @@
     CountUse(frame_->IsOutermostMainFrame()
                  ? WebFeature::kSharedDictionaryUsedForMainFrameNavigation
                  : WebFeature::kSharedDictionaryUsedForSubFrameNavigation);
-    if (content_encoding.LowerASCII() == "sbr") {
+    if (content_encoding.LowerASCII() ==
+        network::GetSharedBrotliContentEncodingName()) {
       CountUse(WebFeature::kSharedDictionaryUsedWithSharedBrotli);
-    } else if (content_encoding.LowerASCII() == "zstd-d") {
+    } else if (content_encoding.LowerASCII() ==
+               network::GetSharedZstdContentEncodingName()) {
       CountUse(WebFeature::kSharedDictionaryUsedWithSharedZstd);
     }
   }
diff --git a/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc b/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
index 647d86aa..a70f557 100644
--- a/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
+++ b/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/loader/loader_factory_for_frame.h"
 
+#include "base/functional/bind.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/task/single_thread_task_runner.h"
@@ -42,6 +43,28 @@
   return *cors_exempt_header_list;
 }
 
+Vector<std::unique_ptr<URLLoaderThrottle>> CreateThrottlesImpl(
+    URLLoaderThrottleProvider* throttle_provider,
+    const LocalFrameToken local_frame_token,
+    const network::ResourceRequest* network_request) {
+  if (!throttle_provider) {
+    return {};
+  }
+  CHECK(network_request);
+
+  WebVector<std::unique_ptr<URLLoaderThrottle>> web_throttles =
+      throttle_provider->CreateThrottles(local_frame_token, *network_request);
+  // TODO(crbug.com/1517144): Stop WebVector->Vector manual conversion when we
+  // have a WTF::Vector constructor which creates a vector with items moved from
+  // a collection.
+  Vector<std::unique_ptr<URLLoaderThrottle>> throttles;
+  throttles.reserve(base::checked_cast<wtf_size_t>(web_throttles.size()));
+  for (auto& throttle : web_throttles) {
+    throttles.push_back(std::move(throttle));
+  }
+  return throttles;
+}
+
 }  // namespace
 
 // static
@@ -83,9 +106,6 @@
     const absl::optional<base::UnguessableToken>&
         service_worker_race_network_request_token,
     bool is_from_origin_dirty_style_sheet) {
-  Vector<std::unique_ptr<URLLoaderThrottle>> throttles =
-      CreateThrottles(network_request);
-
   mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
       url_loader_factory;
   if (options.url_loader_factory) {
@@ -134,7 +154,7 @@
         ->CreateURLLoader(
             network_request, freezable_task_runner, unfreezable_task_runner,
             /*keep_alive_handle=*/mojo::NullRemote(),
-            back_forward_cache_loader_helper, std::move(throttles));
+            back_forward_cache_loader_helper, CreateThrottles(network_request));
   }
 
   if (document_loader_->GetServiceWorkerNetworkProvider()) {
@@ -155,13 +175,19 @@
           ->CreateURLLoader(network_request, freezable_task_runner,
                             unfreezable_task_runner, std::move(pending_remote),
                             back_forward_cache_loader_helper,
-                            std::move(throttles));
+                            CreateThrottles(network_request));
     }
   }
 
   if (prefetched_signed_exchange_manager_) {
+    // CreateThrottlesImpl will be called synchronously only when there is a
+    // matching prefetched response.
     auto loader = prefetched_signed_exchange_manager_->MaybeCreateURLLoader(
-        network_request, throttles);
+        network_request,
+        WTF::BindOnce(&CreateThrottlesImpl,
+                      WTF::Unretained(GetURLLoaderThrottleProvider()),
+                      window_->GetFrame()->GetLocalFrameToken(),
+                      WTF::Unretained(&network_request)));
     if (loader)
       return loader;
   }
@@ -176,7 +202,8 @@
     return loader;
   }
 
-  if (BackgroundURLLoader::CanHandleRequest(network_request, options)) {
+  if (BackgroundURLLoader::CanHandleRequest(
+          network_request, options, window_->document()->IsPrefetchOnly())) {
     scoped_refptr<WebBackgroundResourceFetchAssets>
         web_background_resource_fetch_assets =
             frame->MaybeGetBackgroundResourceFetchAssets();
@@ -186,8 +213,7 @@
       return std::make_unique<BackgroundURLLoader>(
           std::move(web_background_resource_fetch_assets),
           GetCorsExemptHeaderList(), unfreezable_task_runner,
-          back_forward_cache_loader_helper, std::move(throttles),
-          GetBackgroundCodeCacheHost());
+          back_forward_cache_loader_helper, GetBackgroundCodeCacheHost());
     }
   }
 
@@ -196,7 +222,8 @@
              /*terminate_sync_load_event=*/nullptr)
       ->CreateURLLoader(network_request, freezable_task_runner,
                         unfreezable_task_runner, std::move(pending_remote),
-                        back_forward_cache_loader_helper, std::move(throttles));
+                        back_forward_cache_loader_helper,
+                        CreateThrottles(network_request));
 }
 
 CodeCacheHost* LoaderFactoryForFrame::GetCodeCacheHost() {
@@ -236,34 +263,27 @@
   return background_code_cache_host_;
 }
 
-Vector<std::unique_ptr<URLLoaderThrottle>>
-LoaderFactoryForFrame::CreateThrottles(
-    const network::ResourceRequest& network_request) {
+URLLoaderThrottleProvider*
+LoaderFactoryForFrame::GetURLLoaderThrottleProvider() {
   // LocalFrameClient member may not be valid in some tests.
   if (!window_->GetFrame()->Client() ||
       !window_->GetFrame()->Client()->GetWebFrame() ||
       !window_->GetFrame()->Client()->GetWebFrame()->Client()) {
-    return {};
+    return nullptr;
   }
-  URLLoaderThrottleProvider* throttle_provider =
-      window_->GetFrame()
-          ->Client()
-          ->GetWebFrame()
-          ->Client()
-          ->GetURLLoaderThrottleProvider();
-  if (!throttle_provider) {
-    return {};
-  }
-  WebVector<std::unique_ptr<URLLoaderThrottle>> web_throttles =
-      throttle_provider->CreateThrottles(
-          window_->GetFrame()->GetLocalFrameToken(), network_request);
-  Vector<std::unique_ptr<URLLoaderThrottle>> throttles;
+  return window_->GetFrame()
+      ->Client()
+      ->GetWebFrame()
+      ->Client()
+      ->GetURLLoaderThrottleProvider();
+}
 
-  throttles.reserve(base::checked_cast<wtf_size_t>(web_throttles.size()));
-  for (auto& throttle : web_throttles) {
-    throttles.push_back(std::move(throttle));
-  }
-  return throttles;
+Vector<std::unique_ptr<URLLoaderThrottle>>
+LoaderFactoryForFrame::CreateThrottles(
+    const network::ResourceRequest& network_request) {
+  return CreateThrottlesImpl(GetURLLoaderThrottleProvider(),
+                             window_->GetFrame()->GetLocalFrameToken(),
+                             &network_request);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/loader_factory_for_frame.h b/third_party/blink/renderer/core/loader/loader_factory_for_frame.h
index f965fe92..5754212 100644
--- a/third_party/blink/renderer/core/loader/loader_factory_for_frame.h
+++ b/third_party/blink/renderer/core/loader/loader_factory_for_frame.h
@@ -53,6 +53,8 @@
       mojom::blink::LocalFrameHost& local_frame_host,
       mojo::PendingReceiver<mojom::blink::KeepAliveHandle> pending_receiver);
   scoped_refptr<BackgroundCodeCacheHost> GetBackgroundCodeCacheHost();
+
+  URLLoaderThrottleProvider* GetURLLoaderThrottleProvider();
   Vector<std::unique_ptr<URLLoaderThrottle>> CreateThrottles(
       const network::ResourceRequest&);
 
diff --git a/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.cc b/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.cc
index 23f8cd3a..b1d495b 100644
--- a/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.cc
+++ b/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.cc
@@ -250,7 +250,8 @@
 std::unique_ptr<URLLoader>
 PrefetchedSignedExchangeManager::MaybeCreateURLLoader(
     const network::ResourceRequest& network_request,
-    Vector<std::unique_ptr<URLLoaderThrottle>>& throttles) {
+    base::OnceCallback<Vector<std::unique_ptr<URLLoaderThrottle>>(void)>
+        create_throttles_callback) {
   if (started_)
     return nullptr;
   const auto* matching_resource = alternative_resources_->FindMatchingEntry(
@@ -264,7 +265,7 @@
           network_request,
           frame_->GetFrameScheduler()->GetTaskRunner(
               TaskType::kInternalLoading),
-          std::move(throttles));
+          std::move(create_throttles_callback).Run());
   loaders_.emplace_back(loader->GetWeakPtr());
   return loader;
 }
diff --git a/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h b/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h
index d47c3f5..23e91e9 100644
--- a/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h
+++ b/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PREFETCHED_SIGNED_EXCHANGE_MANAGER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PREFETCHED_SIGNED_EXCHANGE_MANAGER_H_
 
+#include "base/functional/callback_forward.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/network/public/mojom/url_loader_factory.mojom-blink-forward.h"
 #include "third_party/blink/public/web/web_navigation_params.h"
@@ -67,7 +68,8 @@
   // StartPrefetchedLinkHeaderPreloads() will be called.
   std::unique_ptr<URLLoader> MaybeCreateURLLoader(
       const network::ResourceRequest& request,
-      Vector<std::unique_ptr<URLLoaderThrottle>>& throttles);
+      base::OnceCallback<Vector<std::unique_ptr<URLLoaderThrottle>>(void)>
+          create_throttles_callback);
 
   // If the all loaders which have been created by MaybeCreateURLLoader() have
   // a matching "alternate" link header in the outer response and the matching
diff --git a/third_party/blink/renderer/core/workers/README.md b/third_party/blink/renderer/core/workers/README.md
index 4e8ba67..ec6bc9d 100644
--- a/third_party/blink/renderer/core/workers/README.md
+++ b/third_party/blink/renderer/core/workers/README.md
@@ -128,12 +128,6 @@
 : Counts of `Worklet#addModule()` calls in `Document`. This includes all worklet
 types. Each worklet type has its own counter, too.
 
-## UMA
-
-The UMA data is internal-only.
-
-- WorkerThread.ExitCode : Records the exit code of `WorkerThread`.
-
 # Tests
 
 When you add a new worker or worklet type, please consider adding tests in
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 9c536a8..e357b3e 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -124,6 +124,7 @@
     "//third_party/blink/renderer/modules/mediastream",
     "//third_party/blink/renderer/modules/media",
     "//third_party/blink/renderer/modules/ml",
+    "//third_party/blink/renderer/modules/model_execution",
     "//third_party/blink/renderer/modules/navigatorcontentutils",
     "//third_party/blink/renderer/modules/netinfo",
     "//third_party/blink/renderer/modules/nfc",
diff --git a/third_party/blink/renderer/modules/credentialmanagement/federated_credential.cc b/third_party/blink/renderer/modules/credentialmanagement/federated_credential.cc
index 3e2b181..520b8afc 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/federated_credential.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/federated_credential.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/modules/credentialmanagement/credential_manager_proxy.h"
 #include "third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
 
 namespace blink {
 
@@ -78,10 +79,14 @@
   return true;
 }
 
-void SetIdpSigninStatus(WebLocalFrame* frame,
+void SetIdpSigninStatus(const blink::LocalFrameToken& local_frame_token,
                         const url::Origin& origin,
                         mojom::blink::IdpSigninStatus status) {
-  LocalFrame* local_frame = To<LocalFrame>(WebFrame::ToCoreFrame(*frame));
+  CHECK(WTF::IsMainThread());
+  LocalFrame* local_frame = LocalFrame::FromFrameToken(local_frame_token);
+  if (!local_frame) {
+    return;
+  }
   auto* auth_request = CredentialManagerProxy::From(local_frame->DomWindow())
                            ->FederatedAuthRequest();
   auth_request->SetIdpSigninStatus(SecurityOrigin::CreateFromUrlOrigin(origin),
diff --git a/third_party/blink/renderer/modules/model_execution/BUILD.gn b/third_party/blink/renderer/modules/model_execution/BUILD.gn
new file mode 100644
index 0000000..37f87d7f
--- /dev/null
+++ b/third_party/blink/renderer/modules/model_execution/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2024 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/blink/renderer/modules/modules.gni")
+
+blink_modules_sources("model_execution") {
+  sources = [
+    "model_generic_session.cc",
+    "model_generic_session.h",
+    "model_manager.cc",
+    "model_manager.h",
+    "window_model.cc",
+    "window_model.h",
+  ]
+
+  public_deps = [ "//third_party/blink/public/mojom:mojom_modules_blink" ]
+}
diff --git a/third_party/blink/renderer/modules/model_execution/OWNERS b/third_party/blink/renderer/modules/model_execution/OWNERS
new file mode 100644
index 0000000..a640f819
--- /dev/null
+++ b/third_party/blink/renderer/modules/model_execution/OWNERS
@@ -0,0 +1 @@
+file://chrome/browser/model_execution/OWNERS
diff --git a/third_party/blink/renderer/modules/model_execution/model_generic_session.cc b/third_party/blink/renderer/modules/model_execution/model_generic_session.cc
new file mode 100644
index 0000000..967676d
--- /dev/null
+++ b/third_party/blink/renderer/modules/model_execution/model_generic_session.cc
@@ -0,0 +1,177 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/model_execution/model_generic_session.h"
+
+#include "base/functional/callback_helpers.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/task/sequenced_task_runner.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
+#include "third_party/blink/public/mojom/model_execution/model_session.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/model_execution/model_session.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
+#include "third_party/blink/renderer/core/streams/underlying_source_base.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+namespace blink {
+
+// Implementation of blink::mojom::blink::ModelStreamingResponder that
+// handles the streaming output of the model execution, and returns the full
+// result through a promise.
+class ModelGenericSession::Responder final
+    : public GarbageCollected<ModelGenericSession::Responder>,
+      public blink::mojom::blink::ModelStreamingResponder {
+ public:
+  explicit Responder(ScriptState* script_state)
+      : resolver_(MakeGarbageCollected<ScriptPromiseResolver>(script_state)) {}
+  ~Responder() override = default;
+
+  void Trace(Visitor* visitor) const { visitor->Trace(resolver_); }
+
+  ScriptPromise GetPromise() { return resolver_->Promise(); }
+
+  // `blink::mojom::blink::ModelStreamingResponder` implementation.
+  void OnResponse(mojom::blink::ModelStreamingResponseStatus status,
+                  const WTF::String& text) override {
+    switch (status) {
+      case mojom::blink::ModelStreamingResponseStatus::kOngoing: {
+        response_ = text;
+        break;
+      }
+      case mojom::blink::ModelStreamingResponseStatus::kComplete: {
+        resolver_->Resolve(response_);
+        break;
+      }
+      case mojom::blink::ModelStreamingResponseStatus::kError: {
+        resolver_->Reject();
+      }
+    }
+  }
+
+ private:
+  Member<ScriptPromiseResolver> resolver_;
+  WTF::String response_;
+};
+
+// Implementation of blink::mojom::blink::ModelStreamingResponder that
+// handles the streaming output of the model execution, and returns the full
+// result through a ReadableStream.
+class ModelGenericSession::StreamingResponder final
+    : public UnderlyingSourceBase,
+      public blink::mojom::blink::ModelStreamingResponder {
+ public:
+  explicit StreamingResponder(ScriptState* script_state)
+      : UnderlyingSourceBase(script_state), script_state_(script_state) {}
+  ~StreamingResponder() override = default;
+
+  void Trace(Visitor* visitor) const override {
+    UnderlyingSourceBase::Trace(visitor);
+    visitor->Trace(script_state_);
+  }
+
+  // `UnderlyingSourceBase` implementation.
+  ScriptPromise Pull(ScriptState* script_state,
+                     ExceptionState& exception_state) override {
+    return ScriptPromise::CastUndefined(script_state);
+  }
+
+  ScriptPromise Cancel(ScriptState* script_state,
+                       ScriptValue reason,
+                       ExceptionState& exception_state) override {
+    return ScriptPromise::CastUndefined(script_state);
+  }
+
+  // `blink::mojom::blink::ModelStreamingResponder` implementation.
+  void OnResponse(mojom::blink::ModelStreamingResponseStatus status,
+                  const WTF::String& text) override {
+    switch (status) {
+      case mojom::blink::ModelStreamingResponseStatus::kOngoing: {
+        Controller()->Enqueue(text);
+        break;
+      }
+      case mojom::blink::ModelStreamingResponseStatus::kComplete: {
+        Controller()->Close();
+        break;
+      }
+      case mojom::blink::ModelStreamingResponseStatus::kError: {
+        // TODO(leimy): better error information design after the prototype.
+        Controller()->Error(V8ThrowException::CreateError(
+            script_state_->GetIsolate(), "Model execution error"));
+      }
+    }
+  }
+
+ private:
+  Member<ScriptState> script_state_;
+};
+
+ModelGenericSession::ModelGenericSession(
+    scoped_refptr<base::SequencedTaskRunner> task_runner)
+    : task_runner_(task_runner) {}
+
+void ModelGenericSession::Trace(Visitor* visitor) const {
+  ScriptWrappable::Trace(visitor);
+  visitor->Trace(model_session_remote_);
+}
+
+mojo::PendingReceiver<blink::mojom::blink::ModelGenericSession>
+ModelGenericSession::GetModelSessionReceiver() {
+  return model_session_remote_.BindNewPipeAndPassReceiver(task_runner_);
+}
+
+ScriptPromise ModelGenericSession::execute(ScriptState* script_state,
+                                           const WTF::String& input,
+                                           ExceptionState& exception_state) {
+  if (!script_state->ContextIsValid()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+                                      "The execution context is not valid.");
+    return ScriptPromise();
+  }
+
+  ModelGenericSession::Responder* responder =
+      MakeGarbageCollected<ModelGenericSession::Responder>(script_state);
+
+  HeapMojoReceiver<blink::mojom::blink::ModelStreamingResponder,
+                   ModelGenericSession::Responder>
+      receiver{responder, nullptr};
+
+  model_session_remote_->Execute(
+      input, receiver.BindNewPipeAndPassRemote(task_runner_));
+  return responder->GetPromise();
+}
+
+ReadableStream* ModelGenericSession::executeStreaming(
+    ScriptState* script_state,
+    const WTF::String& input,
+    ExceptionState& exception_state) {
+  if (!script_state->ContextIsValid()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+                                      "The execution context is not valid.");
+    return nullptr;
+  }
+
+  ModelGenericSession::StreamingResponder* responder =
+      MakeGarbageCollected<ModelGenericSession::StreamingResponder>(
+          script_state);
+
+  HeapMojoReceiver<blink::mojom::blink::ModelStreamingResponder,
+                   ModelGenericSession::StreamingResponder>
+      receiver{responder, nullptr};
+
+  model_session_remote_->Execute(
+      input, receiver.BindNewPipeAndPassRemote(task_runner_));
+
+  // Set the high water mark to 1 so the backpressure will be applied on every
+  // enqueue.
+  return ReadableStream::CreateWithCountQueueingStrategy(script_state,
+                                                         responder, 1);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/model_execution/model_generic_session.h b/third_party/blink/renderer/modules/model_execution/model_generic_session.h
new file mode 100644
index 0000000..a2e4787
--- /dev/null
+++ b/third_party/blink/renderer/modules/model_execution/model_generic_session.h
@@ -0,0 +1,51 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MODEL_EXECUTION_MODEL_GENERIC_SESSION_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_MODEL_EXECUTION_MODEL_GENERIC_SESSION_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "base/task/sequenced_task_runner.h"
+#include "third_party/blink/public/mojom/model_execution/model_session.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
+#include "third_party/blink/renderer/core/streams/readable_stream.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+
+namespace blink {
+
+// The class that represents a session with simple generic model execution.
+class ModelGenericSession final : public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  explicit ModelGenericSession(
+      scoped_refptr<base::SequencedTaskRunner> task_runner);
+  ~ModelGenericSession() override = default;
+
+  void Trace(Visitor* visitor) const override;
+
+  mojo::PendingReceiver<blink::mojom::blink::ModelGenericSession>
+  GetModelSessionReceiver();
+
+  // model_generic_session.idl implementation.
+  ScriptPromise execute(ScriptState* script_state,
+                        const WTF::String& input,
+                        ExceptionState& exception_state);
+  ReadableStream* executeStreaming(ScriptState* script_state,
+                                   const WTF::String& input,
+                                   ExceptionState& exception_state);
+
+ private:
+  class Responder;
+  class StreamingResponder;
+
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  HeapMojoRemote<blink::mojom::blink::ModelGenericSession>
+      model_session_remote_{nullptr};
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_MODEL_EXECUTION_MODEL_GENERIC_SESSION_H_
diff --git a/third_party/blink/renderer/modules/model_execution/model_generic_session.idl b/third_party/blink/renderer/modules/model_execution/model_generic_session.idl
new file mode 100644
index 0000000..e33b4a89
--- /dev/null
+++ b/third_party/blink/renderer/modules/model_execution/model_generic_session.idl
@@ -0,0 +1,12 @@
+// Copyright 2024 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+  RuntimeEnabled=ModelExecutionAPI,
+  Exposed=Window
+]
+interface ModelGenericSession {
+  [CallWith=ScriptState, RaisesException] Promise<DOMString> execute(DOMString input);
+  [CallWith=ScriptState, RaisesException] ReadableStream executeStreaming(DOMString input);
+};
diff --git a/third_party/blink/renderer/modules/model_execution/model_manager.cc b/third_party/blink/renderer/modules/model_execution/model_manager.cc
new file mode 100644
index 0000000..67d51ac
--- /dev/null
+++ b/third_party/blink/renderer/modules/model_execution/model_manager.cc
@@ -0,0 +1,114 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/model_execution/model_manager.h"
+
+#include "base/functional/callback_helpers.h"
+#include "base/task/sequenced_task_runner.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/streams/readable_stream.h"
+#include "third_party/blink/renderer/modules/model_execution/model_generic_session.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+namespace blink {
+
+String AvailabilityToString(ModelManager::Availability availability) {
+  DEFINE_STATIC_LOCAL(const String, readily, ("readily"));
+  DEFINE_STATIC_LOCAL(const String, after_download, ("after-download"));
+  DEFINE_STATIC_LOCAL(const String, no, ("no"));
+
+  switch (availability) {
+    case ModelManager::kReadily:
+      return readily;
+    case ModelManager::kAfterDownload:
+      return after_download;
+    case ModelManager::kNo:
+      return no;
+  }
+
+  NOTREACHED();
+  return String();
+}
+
+ModelManager::ModelManager(LocalDOMWindow* window)
+    : task_runner_(window->GetTaskRunner(TaskType::kInternalDefault)) {
+  CHECK(window && window->GetFrame());
+  window->GetFrame()->GetBrowserInterfaceBroker().GetInterface(
+      model_manager_remote_.BindNewPipeAndPassReceiver(task_runner_));
+}
+
+void ModelManager::Trace(Visitor* visitor) const {
+  ScriptWrappable::Trace(visitor);
+  visitor->Trace(model_manager_remote_);
+}
+
+ScriptPromise ModelManager::canCreateGenericSession(
+    ScriptState* script_state,
+    ExceptionState& exception_state) {
+  if (!script_state->ContextIsValid()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+                                      "The execution context is not valid.");
+    return ScriptPromise();
+  }
+
+  ScriptPromiseResolver* resolver =
+      MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  ScriptPromise promise = resolver->Promise();
+  // TODO(leimy): in the future, we may need to check if the model has been
+  // downloaded etc.
+  if (!model_manager_remote_.is_connected()) {
+    resolver->Resolve(AvailabilityToString(kNo));
+  } else {
+    model_manager_remote_->CanCreateGenericSession(WTF::BindOnce(
+        [](ScriptPromiseResolver* resolver, bool can_create) {
+          Availability availability = kNo;
+          if (can_create) {
+            availability = kReadily;
+          }
+          resolver->Resolve(AvailabilityToString(availability));
+        },
+        WrapPersistent(resolver)));
+  }
+
+  return promise;
+}
+
+ScriptPromise ModelManager::createGenericSession(
+    ScriptState* script_state,
+    ExceptionState& exception_state) {
+  if (!script_state->ContextIsValid()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+                                      "The execution context is not valid.");
+    return ScriptPromise();
+  }
+
+  ScriptPromiseResolver* resolver =
+      MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  ScriptPromise promise = resolver->Promise();
+
+  ModelGenericSession* generic_session =
+      MakeGarbageCollected<ModelGenericSession>(task_runner_);
+  model_manager_remote_->CreateGenericSession(
+      generic_session->GetModelSessionReceiver(),
+      WTF::BindOnce(
+          [](ScriptPromiseResolver* resolver,
+             ModelGenericSession* generic_session, bool success) {
+            if (success) {
+              resolver->Resolve(generic_session);
+            } else {
+              resolver->Reject();
+            }
+          },
+          WrapPersistent(resolver), WrapPersistent(generic_session)));
+
+  return promise;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/model_execution/model_manager.h b/third_party/blink/renderer/modules/model_execution/model_manager.h
new file mode 100644
index 0000000..c770f2b
--- /dev/null
+++ b/third_party/blink/renderer/modules/model_execution/model_manager.h
@@ -0,0 +1,45 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MODEL_EXECUTION_MODEL_MANAGER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_MODEL_EXECUTION_MODEL_MANAGER_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "base/task/sequenced_task_runner.h"
+#include "third_party/blink/public/mojom/model_execution/model_manager.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+
+namespace blink {
+
+// The class that manages the exposed model APIs that load model assets and
+// create ModelGenericSession.
+class ModelManager final : public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  enum Availability { kReadily, kAfterDownload, kNo };
+
+  explicit ModelManager(LocalDOMWindow* window);
+  ~ModelManager() override = default;
+
+  void Trace(Visitor* visitor) const override;
+
+  // model_manager.idl implementation.
+  ScriptPromise canCreateGenericSession(ScriptState* script_state,
+                                        ExceptionState& exception_state);
+  ScriptPromise createGenericSession(ScriptState* script_state,
+                                     ExceptionState& exception_state);
+
+ private:
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  HeapMojoRemote<mojom::blink::ModelManager> model_manager_remote_{nullptr};
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_MODEL_EXECUTION_MODEL_MANAGER_H_
diff --git a/third_party/blink/renderer/modules/model_execution/model_manager.idl b/third_party/blink/renderer/modules/model_execution/model_manager.idl
new file mode 100644
index 0000000..e1ba97d
--- /dev/null
+++ b/third_party/blink/renderer/modules/model_execution/model_manager.idl
@@ -0,0 +1,14 @@
+// Copyright 2024 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+enum GenericModelAvailability { "readily", "after-download", "no" };
+
+[
+  RuntimeEnabled=ModelExecutionAPI,
+  Exposed=Window
+]
+interface ModelManager {
+  [CallWith=ScriptState, RaisesException] Promise<GenericModelAvailability> canCreateGenericSession();
+  [CallWith=ScriptState, RaisesException] Promise<ModelGenericSession> createGenericSession();
+};
diff --git a/third_party/blink/renderer/modules/model_execution/window_model.cc b/third_party/blink/renderer/modules/model_execution/window_model.cc
new file mode 100644
index 0000000..a1557f9
--- /dev/null
+++ b/third_party/blink/renderer/modules/model_execution/window_model.cc
@@ -0,0 +1,48 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/model_execution/window_model.h"
+
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/modules/model_execution/model_manager.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+WindowModel::WindowModel(LocalDOMWindow& window)
+    : Supplement<LocalDOMWindow>(window) {}
+
+void WindowModel::Trace(Visitor* visitor) const {
+  visitor->Trace(model_);
+  Supplement<LocalDOMWindow>::Trace(visitor);
+}
+
+// static
+const char WindowModel::kSupplementName[] = "WindowModel";
+
+// static
+WindowModel& WindowModel::From(LocalDOMWindow& window) {
+  WindowModel* supplement =
+      Supplement<LocalDOMWindow>::From<WindowModel>(window);
+  if (!supplement) {
+    supplement = MakeGarbageCollected<WindowModel>(window);
+    ProvideTo(window, supplement);
+  }
+  return *supplement;
+}
+
+// static
+ModelManager* WindowModel::model(LocalDOMWindow& window) {
+  return From(window).model();
+}
+
+ModelManager* WindowModel::model() {
+  if (!model_) {
+    model_ = MakeGarbageCollected<ModelManager>(GetSupplementable());
+  }
+  return model_.Get();
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/model_execution/window_model.h b/third_party/blink/renderer/modules/model_execution/window_model.h
new file mode 100644
index 0000000..aa398fe
--- /dev/null
+++ b/third_party/blink/renderer/modules/model_execution/window_model.h
@@ -0,0 +1,38 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MODEL_EXECUTION_WINDOW_MODEL_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_MODEL_EXECUTION_WINDOW_MODEL_H_
+
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class ModelManager;
+class LocalDOMWindow;
+
+class WindowModel final : public GarbageCollected<WindowModel>,
+                          public Supplement<LocalDOMWindow> {
+ public:
+  static const char kSupplementName[];
+
+  static WindowModel& From(LocalDOMWindow&);
+  static ModelManager* model(LocalDOMWindow&);
+
+  explicit WindowModel(LocalDOMWindow&);
+  WindowModel(const WindowModel&) = delete;
+  WindowModel& operator=(const WindowModel&) = delete;
+
+  void Trace(Visitor*) const override;
+
+ private:
+  ModelManager* model();
+
+  Member<ModelManager> model_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_MODEL_EXECUTION_WINDOW_MODEL_H_
diff --git a/third_party/blink/renderer/modules/model_execution/window_model.idl b/third_party/blink/renderer/modules/model_execution/window_model.idl
new file mode 100644
index 0000000..8ee68dd
--- /dev/null
+++ b/third_party/blink/renderer/modules/model_execution/window_model.idl
@@ -0,0 +1,11 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(leimy): Add link to spec/explainer?
+[
+    ImplementedAs=WindowModel,
+    RuntimeEnabled=ModelExecutionAPI
+] partial interface Window {
+    readonly attribute ModelManager model;
+};
diff --git a/third_party/blink/renderer/platform/fonts/shaping/han_kerning.cc b/third_party/blink/renderer/platform/fonts/shaping/han_kerning.cc
index 2424063..272fc17 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/han_kerning.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/han_kerning.cc
@@ -135,6 +135,11 @@
   return type == CharType::kOpen || type == CharType::kOpenQuote;
 }
 
+bool HanKerning::MaybeClose(UChar ch) {
+  const CharType type = Character::GetHanKerningCharType(ch);
+  return type == CharType::kClose || type == CharType::kCloseQuote;
+}
+
 inline bool HanKerning::ShouldKern(CharType type, CharType last_type) {
   return type == CharType::kOpen &&
          (last_type == CharType::kOpen || last_type == CharType::kMiddle ||
@@ -177,7 +182,7 @@
   // Compute for the first character.
   Vector<wtf_size_t, 32> indices;
   CharType last_type;
-  if (options.apply_start) {
+  if (UNLIKELY(options.apply_start)) {
     indices.push_back(start);
     last_type = GetCharType(text[start], font_data);
   } else if (start) {
@@ -194,7 +199,9 @@
   if (font_data.has_contextual_spacing) {
     // The `chws` feature can handle charcters in a run.
     // Compute the end edge if there are following runs.
-    if (end < text.length()) {
+    if (UNLIKELY(options.apply_end)) {
+      indices.push_back(end - 1);
+    } else if (end < text.length()) {
       if (end - 1 > start) {
         last_type = GetCharType(text[end - 1], font_data);
       }
@@ -218,7 +225,9 @@
     }
 
     // Compute for the last character.
-    if (end < text.length()) {
+    if (UNLIKELY(options.apply_end)) {
+      indices.push_back(end - 1);
+    } else if (end < text.length()) {
       type = GetCharType(text[end], font_data);
       if (ShouldKernLast(type, last_type)) {
         indices.push_back(end - 1);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/han_kerning.h b/third_party/blink/renderer/platform/fonts/shaping/han_kerning.h
index 961ac15..c1a41e0 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/han_kerning.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/han_kerning.h
@@ -46,6 +46,7 @@
   struct Options {
     bool is_horizontal = true;
     bool apply_start = false;
+    bool apply_end = false;
   };
 
   HanKerning(const String& text,
@@ -104,6 +105,8 @@
   // font. `CharType` depends on fonts, so it may not be `kOpen` even when this
   // function returns `true`.
   static bool MaybeOpen(UChar ch);
+  // Same as `MaybeOpen` but for `kClose`.
+  static bool MaybeClose(UChar ch);
 
  private:
   static CharType GetCharType(UChar ch, const FontData& font_data);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
index 1d86bfd..d2c3319 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
@@ -866,7 +866,9 @@
         text_, shape_start, shape_end, *adjusted_font, font_description,
         {.is_horizontal = HB_DIRECTION_IS_HORIZONTAL(direction),
          .apply_start = range_data->options.han_kerning_start &&
-                        range_data->start == shape_start},
+                        range_data->start == shape_start,
+         .apply_end = range_data->options.han_kerning_end &&
+                      range_data->end == shape_end},
         &range_data->font_features);
 
     if (!ShapeRange(range_data->buffer, range_data->font_features,
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_options.h b/third_party/blink/renderer/platform/fonts/shaping/shape_options.h
index a3aaea8..82a359a0 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_options.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_options.h
@@ -14,6 +14,7 @@
 //
 struct PLATFORM_EXPORT ShapeOptions {
   bool han_kerning_start = false;
+  bool han_kerning_end = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc b/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
index b515c052..e026c6d 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
@@ -314,6 +314,32 @@
     candidate_break =
         result_->AdjustOffsetForAutoSpacing(candidate_break, end_position);
   }
+
+  // Extend the `candidate_break` if the next character can fit by applying the
+  // `HanKerning` at the line end.
+  unsigned last_safe;
+  scoped_refptr<const ShapeResult> line_end_result;
+  if (candidate_break < range_end &&
+      UNLIKELY(RuntimeEnabledFeatures::CSSTextSpacingTrimEnabled()) &&
+      ShouldTrimEnd(text_spacing_trim_) &&
+      UNLIKELY(HanKerning::MaybeClose(text[candidate_break]))) {
+    const unsigned adjusted_candidate_break = candidate_break + 1;
+    if (break_iterator_->IsBreakable(adjusted_candidate_break)) {
+      last_safe = result_->CachedPreviousSafeToBreakOffset(candidate_break);
+      line_end_result =
+          Shape(last_safe, adjusted_candidate_break, {.han_kerning_end = true});
+      const float last_safe_position =
+          result_->CachedPositionForOffset(last_safe - range_start);
+      const float width_to_last_safe =
+          FlipRtl(last_safe_position - start_position, direction);
+      if (width_to_last_safe + line_end_result->Width() <= available_space) {
+        candidate_break = adjusted_candidate_break;
+      } else {
+        line_end_result = nullptr;
+      }
+    }
+  }
+
   if (candidate_break >= range_end) {
     // The |result_| does not have glyphs to fill the available space,
     // and thus unable to compute. Return the result up to range_end.
@@ -398,7 +424,7 @@
     }
   }
 
-  bool reshape_line_end = true;
+  bool reshape_line_end = !line_end_result;
   // |range_end| may not be a break opportunity, but this function cannot
   // measure beyond it.
   if (break_opportunity.offset >= range_end) {
@@ -424,10 +450,10 @@
   // We may have options that imply avoiding re-shape.
   // Note: we must evaluate the need of re-shaping the end of the line, before
   // we consider the non-hangable-run-end.
-  if (dont_reshape_end_if_at_space_) {
+  if (dont_reshape_end_if_at_space_ && reshape_line_end) {
     // If the actual offset is in a breakable-space sequence, we may need to run
     // the re-shape logic and consider the non-hangable-run-end.
-    reshape_line_end &= !IsBreakableSpace(text[break_opportunity.offset - 1]);
+    reshape_line_end = !IsBreakableSpace(text[break_opportunity.offset - 1]);
   }
 
   // Use the non-hanable-run end as breaking offset (unless we break after eny
@@ -452,8 +478,6 @@
   DCHECK_GE(first_safe.offset, start);
   DCHECK_LE(first_safe.offset, break_opportunity.offset);
 
-  scoped_refptr<const ShapeResult> line_end_result;
-  unsigned last_safe = break_opportunity.offset;
   if (reshape_line_end) {
     // If the previous valid break opportunity is not at a safe-to-break
     // boundary reshape between the safe-to-break offset and the valid break
@@ -529,7 +553,7 @@
   }
 
   if (!line_end_result) {
-    DCHECK_EQ(break_opportunity.offset, last_safe);
+    last_safe = break_opportunity.offset;
     DCHECK_GT(last_safe, start);
     if (UNLIKELY(result_->HasAutoSpacingBefore(last_safe))) {
       last_safe = result_->CachedPreviousSafeToBreakOffset(last_safe - 1);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/text_spacing_trim.h b/third_party/blink/renderer/platform/fonts/shaping/text_spacing_trim.h
index e801644..76ed298 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/text_spacing_trim.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/text_spacing_trim.h
@@ -33,6 +33,10 @@
          value == TextSpacingTrim::kTrimStart;
 }
 
+inline bool ShouldTrimEnd(TextSpacingTrim value) {
+  return value != TextSpacingTrim::kSpaceAll;
+}
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_TEXT_SPACING_TRIM_H_
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
index 4089d434..5b5eb0b 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
@@ -491,6 +491,10 @@
   ScopedPixelLocalStorageInterrupt scoped_pls_interrupt(
       drawing_buffer_->client());
   auto* sii = drawing_buffer_->ContextProvider()->SharedImageInterface();
+
+  // These shared images will be imported into textures on the GL context. We
+  // take a read/write access scope whenever the color buffer is used as the
+  // back buffer.
   uint32_t usage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ |
                    gpu::SHARED_IMAGE_USAGE_GLES2_READ |
                    gpu::SHARED_IMAGE_USAGE_GLES2_WRITE |
@@ -505,9 +509,6 @@
   gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL();
   gl->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData());
 
-  // The shared image is imported into a texture on the GL context. We take a
-  // read/write access scope whenever the color buffer is used as the back
-  // buffer.
   GLuint texture_id = gl->CreateAndTexStorage2DSharedImageCHROMIUM(
       client_shared_image->mailbox().name);
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index f68e75c..d516121 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -48,6 +48,7 @@
 #include "services/network/public/cpp/cross_origin_embedder_policy.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/shared_dictionary_encoding_names.h"
 #include "services/network/public/mojom/blocked_by_response_reason.mojom-shared.h"
 #include "services/network/public/mojom/fetch_api.mojom-blink.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -831,10 +832,12 @@
     fetcher_->GetUseCounter().CountUse(WebFeature::kSharedDictionaryUsed);
     fetcher_->GetUseCounter().CountUse(
         WebFeature::kSharedDictionaryUsedForSubresource);
-    if (content_encoding.LowerASCII() == "sbr") {
+    if (content_encoding.LowerASCII() ==
+        network::GetSharedBrotliContentEncodingName()) {
       fetcher_->GetUseCounter().CountUse(
           WebFeature::kSharedDictionaryUsedWithSharedBrotli);
-    } else if (content_encoding.LowerASCII() == "zstd-d") {
+    } else if (content_encoding.LowerASCII() ==
+               network::GetSharedZstdContentEncodingName()) {
       fetcher_->GetUseCounter().CountUse(
           WebFeature::kSharedDictionaryUsedWithSharedZstd);
     }
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader.cc
index 77633e9..0dccce1 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader.cc
@@ -121,7 +121,8 @@
 
 BackgroundResourceFetchSupportStatus CanHandleRequestInternal(
     const network::ResourceRequest& request,
-    const ResourceLoaderOptions& options) {
+    const ResourceLoaderOptions& options,
+    bool is_prefech_only_document) {
   if (options.synchronous_policy == kRequestSynchronously) {
     return BackgroundResourceFetchSupportStatus::kUnsupportedSyncRequest;
   }
@@ -145,6 +146,13 @@
     return BackgroundResourceFetchSupportStatus::kUnsupportedKeepAliveRequest;
   }
 
+  // Currently prerender::NoStatePrefetchHelper doesn't work on the background
+  // thread.
+  if (is_prefech_only_document) {
+    return BackgroundResourceFetchSupportStatus::
+        kUnsupportedPrefetchOnlyDocument;
+  }
+
   // TODO(crbug.com/1379780): Determine the range of supported requests.
   return BackgroundResourceFetchSupportStatus::kSupported;
 }
@@ -159,7 +167,6 @@
           const Vector<String>& cors_exempt_header_list,
           scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
           BackForwardCacheLoaderHelper* back_forward_cache_loader_helper,
-          Vector<std::unique_ptr<URLLoaderThrottle>> throttles,
           scoped_refptr<BackgroundCodeCacheHost> background_code_cache_host)
       : background_resource_fetch_context_(
             std::move(background_resource_fetch_context)),
@@ -170,7 +177,6 @@
         back_forward_cache_loader_helper_(
             std::make_unique<WeakPersistent<BackForwardCacheLoaderHelper>>(
                 back_forward_cache_loader_helper)),
-        throttles_(std::move(throttles)),
         background_code_cache_host_(std::move(background_code_cache_host)) {
     DETACH_FROM_SEQUENCE(background_sequence_checker_);
   }
@@ -237,20 +243,13 @@
     has_devtools_request_id_ = request->devtools_request_id.has_value();
     client_ = client;
 
-    std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
-    throttles.reserve(throttles_.size());
-    for (auto& throttle : throttles_) {
-      throttle->DetachFromCurrentSequence();
-      throttles.push_back(std::move(throttle));
-    }
-
     PostCrossThreadTask(
         *background_task_runner_, FROM_HERE,
         CrossThreadBindOnce(
             &Context::StartOnBackground, scoped_refptr(this),
             std::move(background_resource_fetch_context_), std::move(request),
             top_frame_origin ? top_frame_origin->ToUrlOrigin() : url::Origin(),
-            no_mime_sniffing, cors_exempt_header_list_, std::move(throttles),
+            no_mime_sniffing, cors_exempt_header_list_,
             std::move(resource_load_info_notifier_wrapper),
             should_use_code_cache_host));
   }
@@ -312,7 +311,6 @@
       const url::Origin& top_frame_origin,
       bool no_mime_sniffing,
       const Vector<String>& cors_exempt_header_list,
-      std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles,
       std::unique_ptr<ResourceLoadInfoNotifierWrapper>
           resource_load_info_notifier_wrapper,
       bool should_use_code_cache_host) {
@@ -323,6 +321,20 @@
       return;
     }
 
+    std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
+    URLLoaderThrottleProvider* throttle_provider =
+        background_resource_fetch_context->GetThrottleProvider();
+    if (throttle_provider) {
+      WebVector<std::unique_ptr<blink::URLLoaderThrottle>> web_throttles =
+          throttle_provider->CreateThrottles(
+              background_resource_fetch_context->GetLocalFrameToken(),
+              *request);
+      throttles.reserve(base::checked_cast<wtf_size_t>(web_throttles.size()));
+      for (auto& throttle : web_throttles) {
+        throttles.push_back(std::move(throttle));
+      }
+    }
+
     resource_request_sender_ = std::make_unique<ResourceRequestSender>();
     net::NetworkTrafficAnnotationTag tag =
         FetchUtils::GetTrafficAnnotationTag(*request);
@@ -532,9 +544,6 @@
       back_forward_cache_loader_helper_
           GUARDED_BY_CONTEXT(main_thread_sequence_checker_);
 
-  Vector<std::unique_ptr<URLLoaderThrottle>> throttles_
-      GUARDED_BY_CONTEXT(main_thread_sequence_checker_);
-
   scoped_refptr<BackgroundCodeCacheHost> background_code_cache_host_
       GUARDED_BY_CONTEXT(background_sequence_checker_);
 
@@ -561,9 +570,11 @@
 // static
 bool BackgroundURLLoader::CanHandleRequest(
     const network::ResourceRequest& request,
-    const ResourceLoaderOptions& options) {
+    const ResourceLoaderOptions& options,
+    bool is_prefech_only_document) {
   CHECK(IsMainThread());
-  auto result = CanHandleRequestInternal(request, options);
+  auto result =
+      CanHandleRequestInternal(request, options, is_prefech_only_document);
   base::UmaHistogramEnumeration(
       kBackgroundResourceFetchSupportStatusHistogramName, result);
   return result == BackgroundResourceFetchSupportStatus::kSupported;
@@ -575,14 +586,12 @@
     const Vector<String>& cors_exempt_header_list,
     scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
     BackForwardCacheLoaderHelper* back_forward_cache_loader_helper,
-    Vector<std::unique_ptr<URLLoaderThrottle>> throttles,
     scoped_refptr<BackgroundCodeCacheHost> background_code_cache_host)
     : context_(base::MakeRefCounted<Context>(
           std::move(background_resource_fetch_context),
           cors_exempt_header_list,
           std::move(unfreezable_task_runner),
           back_forward_cache_loader_helper,
-          std::move(throttles),
           std::move(background_code_cache_host))) {
   CHECK(IsMainThread());
 }
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader.h
index 0ff2db63..56522b0 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader.h
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader.h
@@ -42,7 +42,8 @@
   // BackgroundURLLoader, and if this says it's supported and the feature is
   // enabled, the request comes to the BackgroundURLLoader.
   static bool CanHandleRequest(const network::ResourceRequest& request,
-                               const ResourceLoaderOptions& options);
+                               const ResourceLoaderOptions& options,
+                               bool is_prefech_only_document);
 
   BackgroundURLLoader(
       scoped_refptr<WebBackgroundResourceFetchAssets>
@@ -50,7 +51,6 @@
       const Vector<String>& cors_exempt_header_list,
       scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner,
       BackForwardCacheLoaderHelper* back_forward_cache_loader_helper,
-      Vector<std::unique_ptr<URLLoaderThrottle>> throttles,
       scoped_refptr<BackgroundCodeCacheHost> background_code_cache_host);
   ~BackgroundURLLoader() override;
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader_unittest.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader_unittest.cc
index f5f93ea..86f0ecbaa 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader_unittest.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/background_url_loader_unittest.cc
@@ -213,11 +213,17 @@
     return url_loader_factory_;
   }
 
+  URLLoaderThrottleProvider* GetThrottleProvider() override { return nullptr; }
+  const blink::LocalFrameToken& GetLocalFrameToken() override {
+    return local_frame_token_;
+  }
+
  private:
   scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
   std::unique_ptr<network::PendingSharedURLLoaderFactory>
       pending_loader_factory_;
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+  const blink::LocalFrameToken local_frame_token_;
 };
 
 class FakeURLLoaderClient : public URLLoaderClient {
@@ -420,7 +426,6 @@
             std::move(background_resource_fetch_assets),
             /*cors_exempt_header_list=*/Vector<String>(),
             unfreezable_task_runner_, bfcache_loader_helper_,
-            Vector<std::unique_ptr<URLLoaderThrottle>>(),
             /*background_code_cache_host=*/nullptr);
     background_url_loader->LoadAsynchronously(
         std::move(request), SecurityOrigin::Create(KURL(kTestURL)),
@@ -675,7 +680,6 @@
           /*cors_exempt_header_list=*/Vector<String>(),
           unfreezable_task_runner_,
           /*back_forward_cache_loader_helper=*/nullptr,
-          Vector<std::unique_ptr<URLLoaderThrottle>>(),
           /*background_code_cache_host*/ nullptr);
   FakeURLLoaderClient client(unfreezable_task_runner_);
   background_url_loader->LoadAsynchronously(
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index eb512a9..fc477344 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -2472,6 +2472,11 @@
       base_feature: "none",
     },
     {
+      name: "ModelExecutionAPI",
+      status: "test",
+      base_feature: "EnableModelExecutionAPI",
+    },
+    {
       name: "MojoJS",
       status: "test",
       base_feature: "none",
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index 867b605..28d24b72 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -2206,9 +2206,30 @@
 crbug.com/1500120 [ Win10.20h2 ] virtual/webnn-service-enabled/external/wpt/webnn/gpu/* [ Skip ]
 
 ######## Unload Deprecation
-# This is for tests in the "deprecate-unload" virtual suite that
-# cannot be fixed, e.g. because they are explicitly testing unload.
+# This is for tests in the "unload-allowed" virtual suite that
+# fail by default but keep passing when DeprecteUnload is disabled.
+# They will be removed when unload is removed.
 
-crbug.com/1488371 virtual/deprecate-unload/http/tests/devtools/sources/debugger/skip-pause-during-navigation.js [ Skip ]
+crbug.com/1488371 external/wpt/fetch/api/basic/keepalive.any.html [ Skip ]
+crbug.com/1488371 external/wpt/fetch/api/cors/cors-keepalive.any.html [ Skip Skip ]
+crbug.com/1488371 external/wpt/fetch/api/redirect/redirect-keepalive.any.html [ Skip ]
+crbug.com/1488371 external/wpt/fetch/metadata/unload.https.sub.html [ Skip ]
+crbug.com/1488371 external/wpt/html/browsers/the-window-object/open-close/close_unload.html [ Skip ]
+crbug.com/1488371 external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/009.html [ Skip ]
+crbug.com/1488371 external/wpt/html/browsers/history/the-history-interface/traverse_the_history_unload_1.html [ Skip ]
+crbug.com/1488371 external/wpt/navigation-api/navigate-event/replaceState-in-unload-then-remove-iframe.html [ Skip ]
+# Also tests timing, so cannot be moved to pagehide.
+crbug.com/1488371 external/wpt/navigation-timing/nested-unload-timing.html [ Skip ]
+crbug.com/1488371 external/wpt/screen-details/getScreenDetails.tentative.https.window.html [ Skip ]
+crbug.com/1488371 http/tests/inspector-protocol/issues/deprecation-issue-unload.js [ Skip ]
+crbug.com/1488371 http/tests/navigation/targeted-navigation-in-unload-handler.html [ Skip ]
+crbug.com/1488371 http/tests/devtools/sources/debugger/skip-pause-during-navigation.js [ Skip Skip ]
+crbug.com/1488371 external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-origin.sub.window.html [ Skip ]
+crbug.com/1488371 external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-xml.window.html [ Skip ]
+crbug.com/1488371 external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window.html [ Skip ]
+crbug.com/1488371 external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.html [ Skip ]
+
+# Pagehide is not appropriate as the test checks if PiP window is functional until the very end of the page's lifecycle:
+crbug.com/1488371 external/wpt/document-picture-in-picture/clears-session-on-close.https.html [ Skip ]
 
 ######## End Unload Deprecation
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 58b744e..29eb170 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1153,6 +1153,9 @@
 # Flaky layout tests
 crbug.com/1356336 fast/block/float/shrink-to-avoid-float-complexity.html [ Failure Pass ]
 
+# Anchor positioning failures
+crbug.com/1517558 external/wpt/css/css-anchor-position/inset-area-inline-container.html [ Failure ]
+
 # ====== Layout team owned tests to here ======
 
 # ====== LayoutNG-only failures from here ======
@@ -1505,32 +1508,6 @@
 # Bug in <select multiple> tap behavior:
 crbug.com/1045672 fast/forms/select/listbox-tap.html [ Failure ]
 
-######## Unload Deprecation
-# This is for tests in the "deprecate-unload" virtual suite that
-# cannot be fixed and require a timeout expecation.
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/fetch/api/basic/keepalive.any.html [ Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/fetch/api/cors/cors-keepalive.any.html [ Skip Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/fetch/api/redirect/redirect-keepalive.any.html [ Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/fetch/metadata/unload.https.sub.html [ Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/the-window-object/open-close/close_unload.html [ Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/009.html [ Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/history/the-history-interface/traverse_the_history_unload_1.html [ Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/navigation-api/navigate-event/replaceState-in-unload-then-remove-iframe.html [ Timeout ]
-# Also tests timing, so cannot be moved to pagehide.
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/navigation-timing/nested-unload-timing.html [ Failure ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/screen-details/getScreenDetails.tentative.https.window.html [ Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/http/tests/navigation/targeted-navigation-in-unload-handler.html [ Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/http/tests/devtools/sources/debugger/skip-pause-during-navigation.js [ Skip Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-origin.sub.window.html [ Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-xml.window.html [ Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window.html [ Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.html [ Timeout ]
-
-# Pagehide is not appropriate as the test checks if PiP window is functional until the very end of the page's lifecycle:
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/document-picture-in-picture/clears-session-on-close.https.html [ Timeout ]
-
-######## End Unload Deprecation
-
 ### sheriff 2019-07-16
 
 ### sheriff 2018-05-28
@@ -3414,6 +3391,10 @@
 crbug.com/1463891 external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-dynamic-001.html?class=chws [ Failure ]
 crbug.com/1463891 external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-dot-001.html?class=halt,htb [ Failure ]
 crbug.com/1463891 external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-dot-001.html?class=halt,vrl [ Failure ]
+crbug.com/1463891 external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001.html?class=halt,htb [ Failure ]
+crbug.com/1463891 external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001.html?class=halt,vrl [ Failure ]
+crbug.com/1463891 external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001.html?class=chws,htb [ Failure ]
+crbug.com/1463891 external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001.html?class=chws,vrl [ Failure ]
 crbug.com/1463891 external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-narrow-001.html?class=halt,htb [ Failure ]
 crbug.com/1463891 external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-narrow-001.html?class=halt,vrl [ Failure ]
 crbug.com/1463891 external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-quote-001.html?class=halt,htb&lang=ja [ Failure ]
@@ -3442,6 +3423,10 @@
 crbug.com/1463891 virtual/css-text-spacing-trim/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-dynamic-001.html?class=chws [ Pass ]
 crbug.com/1463891 virtual/css-text-spacing-trim/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-dot-001.html?class=halt,htb [ Pass ]
 crbug.com/1463891 virtual/css-text-spacing-trim/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-dot-001.html?class=halt,vrl [ Pass ]
+crbug.com/1463891 virtual/css-text-spacing-trim/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001.html?class=halt,htb [ Pass ]
+crbug.com/1463891 virtual/css-text-spacing-trim/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001.html?class=halt,vrl [ Pass ]
+crbug.com/1463891 virtual/css-text-spacing-trim/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001.html?class=chws,htb [ Pass ]
+crbug.com/1463891 virtual/css-text-spacing-trim/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001.html?class=chws,vrl [ Pass ]
 crbug.com/1463891 virtual/css-text-spacing-trim/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-narrow-001.html?class=halt,htb [ Pass ]
 crbug.com/1463891 virtual/css-text-spacing-trim/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-narrow-001.html?class=halt,vrl [ Pass ]
 crbug.com/1463891 virtual/css-text-spacing-trim/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-quote-001.html?class=halt,htb&lang=ja [ Pass ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index b721a0b..fe17d53 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -2595,7 +2595,7 @@
     "owners": ["rafael.cintron@microsoft.com", "ningxin.hu@intel.com", "kbr@chromium.org"]
   },
   {
-    "prefix": "deprecate-unload",
+    "prefix": "unload-allowed",
     "platforms": ["Linux", "Mac", "Win"],
     "bases": [
       "http/tests/devtools/sources/debugger/skip-pause-during-navigation.js",
@@ -2649,7 +2649,7 @@
       "wpt_internal/presentation/presentation-receiver-terminate-connection.https.html",
       "wpt_internal/speech/scripted/speechrecognition-no-crash-detached.html"
      ],
-    "args": ["--enable-features=DeprecateUnload"],
+    "args": ["--disable-features=DeprecateUnload"],
     "expires": "Jun 1, 2024",
     "owners": ["fergal@chromium.org", "rakina@chromium.org"]
   },
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/inset-area-abs-inline-container.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/inset-area-abs-inline-container.html
new file mode 100644
index 0000000..368a227
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/inset-area-abs-inline-container.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>CSS Anchor Positioning: inset-area positioning with absolute inline container</title>
+<link rel="help" href="https://drafts.csswg.org/css-anchor-position/#inset-area">
+<link rel="match" href="inset-area-inline-container-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<style>
+  #in-flow {
+    font-family: Ahem;
+    font-size: 100px;
+    color: orange;
+  }
+  #inline-container {
+    position: absolute;
+  }
+  #anchor {
+    position: absolute;
+    top: 25px;
+    left: 100px;
+    width: 200px;
+    height: 50px;
+    anchor-name: --anchor;
+    background-color: cyan;
+  }
+  .anchored {
+    position: absolute;
+    anchor-default: --anchor;
+    background-color: blue;
+  }
+  #top-left { inset-area: top / left; }
+  #top-right { inset-area: top / right; }
+  #bottom-left { inset-area: bottom / left; }
+  #bottom-right { inset-area: bottom / right; }
+</style>
+<div id="in-flow">
+  <br>
+  <br>
+  &nbsp;&nbsp;<span id="inline-container">XXXX<span id="anchor"></span><div id="top-left" class="anchored"></div><div id="top-right" class="anchored"></div><div id="bottom-left" class="anchored"></div><div id="bottom-right" class="anchored"></div></span>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/inset-area-inline-container-ref.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/inset-area-inline-container-ref.html
new file mode 100644
index 0000000..ecf54f1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/inset-area-inline-container-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>CSS Test Reference</title>
+<div style="position:relative">
+  <!-- The Ahem 'XXXX' text: -->
+  <div style="position:absolute; background-color:orange; left:200px; top:200px; width:400px; height:100px"></div>
+  <!-- The #anchor -->
+  <div style="position:absolute; background-color:cyan; left:300px; top:225px; width:200px; height:50px"></div>
+  <!-- top / left -->
+  <div style="position:absolute; background-color:blue; left:200px; top:200px; width:100px; height:25px"></div>
+  <!-- top / right -->
+  <div style="position:absolute; background-color:blue; left:500px; top:200px; width:100px; height:25px"></div>
+  <!-- bottom / left -->
+  <div style="position:absolute; background-color:blue; left:200px; top:275px; width:100px; height:25px"></div>
+  <!-- bottom / right -->
+  <div style="position:absolute; background-color:blue; left:500px; top:275px; width:100px; height:25px"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/inset-area-inline-container.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/inset-area-inline-container.html
new file mode 100644
index 0000000..91c9b097
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/inset-area-inline-container.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>CSS Anchor Positioning: inset-area positioning with inline container</title>
+<link rel="help" href="https://drafts.csswg.org/css-anchor-position/#inset-area">
+<link rel="match" href="inset-area-inline-container-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<style>
+  #in-flow {
+    font-family: Ahem;
+    font-size: 100px;
+    color: orange;
+  }
+  #inline-container {
+    position: relative;
+  }
+  #anchor {
+    position: absolute;
+    top: 25px;
+    left: 100px;
+    width: 200px;
+    height: 50px;
+    anchor-name: --anchor;
+    background-color: cyan;
+  }
+  .anchored {
+    position: absolute;
+    anchor-default: --anchor;
+    background-color: blue;
+  }
+  #top-left { inset-area: top / left; }
+  #top-right { inset-area: top / right; }
+  #bottom-left { inset-area: bottom / left; }
+  #bottom-right { inset-area: bottom / right; }
+</style>
+<div id="in-flow">
+  <br>
+  <br>
+  &nbsp;&nbsp;<span id="inline-container">XXXX<span id="anchor"></span><div id="top-left" class="anchored"></div><div id="top-right" class="anchored"></div><div id="bottom-left" class="anchored"></div><div id="bottom-right" class="anchored"></div></span>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001-ref.html
new file mode 100644
index 0000000..5701388
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="support/variant-class.js"></script>
+<style>
+@font-face {
+  font-family: halt-font;
+  src: url('/fonts/noto/cjk/NotoSansCJKjp-Regular-subset-halt.otf');
+}
+#container {
+  font-family: halt-font;
+  font-size: 20px;
+}
+.vrl {
+  writing-mode: vertical-rl;
+}
+</style>
+<div id="container">
+  <div>国国国)<br>国国国)</div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001.html
new file mode 100644
index 0000000..c5293f09
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-end-001.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-spacing-trim-property">
+<link rel="match" href="text-spacing-trim-end-001-ref.html">
+<script src="support/variant-class.js"></script>
+<meta name="variant" content="?class=halt,htb">
+<meta name="variant" content="?class=chws,htb">
+<meta name="variant" content="?class=halt,vrl">
+<meta name="variant" content="?class=chws,vrl">
+<style>
+@font-face {
+  font-family: halt-font;
+  src: url('/fonts/noto/cjk/NotoSansCJKjp-Regular-subset-halt.otf');
+}
+@font-face {
+  font-family: chws-font;
+  src: url('/fonts/noto/cjk/NotoSansCJKjp-Regular-subset-chws.otf');
+}
+#container {
+  font-family: halt-font;
+  font-size: 20px;
+  inline-size: 3.6em;
+  text-spacing-trim: trim-start;
+}
+.chws #container {
+  font-family: chws-font;
+}
+.vrl {
+  writing-mode: vertical-rl;
+}
+</style>
+<div id="container">
+  <div>国国国)国国国)</div>
+</div>
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/fetch/api/redirect/redirect-keepalive.any-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-keepalive.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/fetch/api/redirect/redirect-keepalive.any-expected.txt
rename to third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-keepalive.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/001-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/001-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/001-expected.txt
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/001-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/002-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/002-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/002-expected.txt
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/002-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/003-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/003-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/003-expected.txt
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/003-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
index 87334f6..6780d77 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
 [FAIL] document.open in beforeunload with button
-  assert_equals: expected "ABCDEFGHIJKLMN" but got "ABGHLMN"
+  assert_equals: expected "ABCDEFGHIJKLMN" but got "ABGLMN"
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/005-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/005-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/005-expected.txt
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/005-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/004-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/004-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/004-expected.txt
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/004-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/007-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/007-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/007-expected.txt
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/007-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-cross-origin.window-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-cross-origin.window-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-cross-origin.window-expected.txt
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-cross-origin.window-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-same-origin.window-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-same-origin.window-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-same-origin.window-expected.txt
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-same-origin.window-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-text-size.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-text-size.html
new file mode 100644
index 0000000..7f294828
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-text-size.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<link rel="help" href="https://html.spec.whatwg.org/C/#the-input-element-as-a-text-entry-widget">
+<title>Test `size` attribute behaivor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+
+<input id="missing">
+<input id="invalid" size="-1">
+<input id="size0" size="0">
+<input id="size1" size="1">
+<input id="size10" size="10">
+<input id="size20" size="20">
+<input id="size21" size="21">
+<input id="computed" style="border:none; padding:0;" size="19">
+
+<script>
+test(() => {
+  assert_equals(missing.offsetWidth, size20.offsetWidth);
+}, 'A misssing attribute is equivalent to size=20');
+
+test(() => {
+  assert_equals(invalid.offsetWidth, size20.offsetWidth, 'size="-1"');
+  assert_equals(size0.offsetWidth, size20.offsetWidth, 'size="0"');
+}, 'An invalid attribute value is equivalent to size=20');
+
+test(() => {
+  assert_less_than(size1.offsetWidth, size10.offsetWidth, '1 < 10');
+  assert_less_than(size10.offsetWidth, size20.offsetWidth, '10 < 20');
+  assert_less_than(size20.offsetWidth, size21.offsetWidth, '20 < 21');
+}, 'The width depends on a size attribute');
+
+test(() => {
+  const computedString = getComputedStyle(computed).width;
+  assert_equals(computed.offsetWidth,
+      parseInt(computedString.substring(0, computedString.length - 2)));
+}, 'Size attribute value affects computed style');
+</script>
+
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/textarea-cols-rows.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/textarea-cols-rows.html
new file mode 100644
index 0000000..012c5aa
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/textarea-cols-rows.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<link rel="help" href="https://html.spec.whatwg.org/C/#the-textarea-element-2">
+<title>Test `cols` `rows` attributes behaivor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+
+<textarea id="missing"></textarea>
+<textarea id="invalid" cols="-1" rows="-1"></textarea>
+<textarea id="computed" style="border:none; padding:0;" cols="19" rows="5"></textarea>
+
+<textarea id="cols0" cols="0"></textarea>
+<textarea id="cols1" cols="1"></textarea>
+<textarea id="cols10" cols="10"></textarea>
+<textarea id="cols20" cols="20"></textarea>
+<textarea id="cols21" cols="21"></textarea>
+
+<textarea id="rows0" rows="0"></textarea>
+<textarea id="rows1" rows="1"></textarea>
+<textarea id="rows2" rows="2"></textarea>
+<textarea id="rows3" rows="3"></textarea>
+
+<script>
+test(() => {
+  assert_equals(missing.offsetWidth, cols20.offsetWidth);
+  assert_equals(missing.offsetHeight, rows2.offsetHeight);
+}, 'A misssing attribute is equivalent to cols=20 rows=2');
+
+test(() => {
+  assert_equals(invalid.offsetWidth, cols20.offsetWidth);
+  assert_equals(invalid.offsetHeight, rows2.offsetHeight);
+  assert_equals(cols0.offsetWidth, cols20.offsetWidth);
+  assert_equals(rows0.offsetHeight, rows2.offsetHeight);
+}, 'An invalid attribute value is equivalent to cols=20 rows=2');
+
+test(() => {
+  assert_less_than(cols1.offsetWidth, cols10.offsetWidth, '1 < 10');
+  assert_less_than(cols10.offsetWidth, cols20.offsetWidth, '10 < 20');
+  assert_less_than(cols20.offsetWidth, cols21.offsetWidth, '20 < 21');
+}, 'The width depends on a cols attribute');
+
+test(() => {
+  assert_less_than(rows1.offsetHeight, rows2.offsetHeight, '1 < 2');
+  assert_less_than(rows2.offsetHeight, rows3.offsetHeight, '2 < 3');
+}, 'The height depends on a rows attribute');
+
+test(() => {
+  const computedWidth = getComputedStyle(computed).width;
+  assert_equals(computed.offsetWidth,
+      parseInt(computedWidth.substring(0, computedWidth.length - 2)));
+
+  const computedHeight = getComputedStyle(computed).height;
+  assert_equals(computed.offsetHeight,
+      parseInt(computedHeight.substring(0, computedHeight.length - 2)));
+}, 'Cols/rows attribute values affect computed style');
+</script>
+
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt
index 97f5695..af5565e 100644
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt
@@ -1,16 +1,22 @@
 This is a testharness.js-based test.
-Found 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 9 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[FAIL] shadowed unload (document.body)
+  assert_equals: alternative body should reflect expected (function) function "() => 0" but got (object) null
 [FAIL] not shadowed copy (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed cut (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed paste (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
+[FAIL] shadowed unload (document.createElement("body"))
+  assert_equals: body should reflect expected (function) function "() => 0" but got (object) null
 [FAIL] not shadowed copy (document.createElement("body"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed cut (document.createElement("body"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed paste (document.createElement("body"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
+[FAIL] shadowed unload (window)
+  assert_equals: body should reflect expected (function) function "() => 0" but got (object) null
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt
index e18da97..6cd6f8a 100644
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt
@@ -1,16 +1,22 @@
 This is a testharness.js-based test.
-Found 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 9 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[FAIL] shadowed unload (document.body)
+  assert_equals: alternative body should reflect expected (function) function "() => 0" but got (object) null
 [FAIL] not shadowed copy (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed cut (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed paste (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
+[FAIL] shadowed unload (document.createElement("frameset"))
+  assert_equals: body should reflect expected (function) function "() => 0" but got (object) null
 [FAIL] not shadowed copy (document.createElement("frameset"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed cut (document.createElement("frameset"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed paste (document.createElement("frameset"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
+[FAIL] shadowed unload (window)
+  assert_equals: body should reflect expected (function) function "() => 0" but got (object) null
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/webappapis/scripting/events/event-handler-attributes-windowless-body-expected.txt b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-windowless-body-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/webappapis/scripting/events/event-handler-attributes-windowless-body-expected.txt
rename to third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-windowless-body-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/lint.ignore b/third_party/blink/web_tests/external/wpt/lint.ignore
index c82f8027..15442c0c 100644
--- a/third_party/blink/web_tests/external/wpt/lint.ignore
+++ b/third_party/blink/web_tests/external/wpt/lint.ignore
@@ -395,6 +395,7 @@
 SET TIMEOUT: scheduler/tentative/current-task-signal-async-priority.any.js
 SET TIMEOUT: speculation-rules/prerender/resources/activation-start.html
 SET TIMEOUT: speculation-rules/prerender/resources/prerender-response-code.html
+SET TIMEOUT: speculation-rules/prerender/resources/prerender-while-prerender-outer.html
 SET TIMEOUT: speculation-rules/prerender/resources/deferred-promise-utils.js
 SET TIMEOUT: speculation-rules/prerender/resources/session-history-harness.js
 SET TIMEOUT: speculation-rules/prerender/resources/utils.js
diff --git a/third_party/blink/web_tests/external/wpt/navigation-api/ordering-and-transition/back-cross-document-event-order-expected.txt b/third_party/blink/web_tests/external/wpt/navigation-api/ordering-and-transition/back-cross-document-event-order-expected.txt
new file mode 100644
index 0000000..67bdfe9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/navigation-api/ordering-and-transition/back-cross-document-event-order-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] back() event ordering for cross-document traversal
+  assert_array_equals: lengths differ, expected array ["onnavigate", "onunload", "readystateinteractive", "domcontentloaded", "readystatecomplete", "onload", "onpageshow"] length 7, got ["onnavigate", "readystateinteractive", "domcontentloaded", "readystatecomplete", "onload", "onpageshow"] length 6
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/navigation-api/ordering-and-transition/navigate-cross-document-event-order-expected.txt b/third_party/blink/web_tests/external/wpt/navigation-api/ordering-and-transition/navigate-cross-document-event-order-expected.txt
new file mode 100644
index 0000000..b0cf970d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/navigation-api/ordering-and-transition/navigate-cross-document-event-order-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] navigate() event ordering for cross-document navigation
+  assert_array_equals: lengths differ, expected array ["onnavigate", "onunload", "readystateinteractive", "domcontentloaded", "readystatecomplete", "onload", "onpageshow"] length 7, got ["onnavigate", "readystateinteractive", "domcontentloaded", "readystatecomplete", "onload", "onpageshow"] length 6
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window-expected.txt b/third_party/blink/web_tests/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window-expected.txt
rename to third_party/blink/web_tests/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window-expected.txt b/third_party/blink/web_tests/external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window-expected.txt
rename to third_party/blink/web_tests/external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/prerender-while-prerender.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/prerender-while-prerender.html
index e04fafbf..8aa80ba 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/prerender-while-prerender.html
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/prerender-while-prerender.html
@@ -12,47 +12,35 @@
 <script>
 setup(() => assertSpeculationRulesIsSupported());
 
+// We attempted to write this test using `RemoteContextHelper`. See
+// https://github.com/web-platform-tests/wpt/blob/23ed0c7015082f21dd29dd09a545e2979dc3e08c/speculation-rules/prerender/prerender-while-prerender.html.
+//
+// However, that ended up being flaky in Chromium. See
+// https://bugs.chromium.org/p/chromium/issues/detail?id=1517319.
+//
+// We're unsure yet if that flakiness was due to a test bug or an implementation
+// bug. In case it is due to a test bug, we are currently trying the following
+// uglier `PrerenderChannel` version. If it is still flaky, then probably it is
+// an implementation bug, and we can revert to the prettier
+// `RemoteContextHelper` version.
+
 promise_test(async t => {
-  const rcHelper = new RemoteContextHelper();
-  const referrerRC = await rcHelper.addWindow(undefined, { features: 'noopener' });
-  const outerPrerenderedRC = await addPrerenderRC(referrerRC);
+  const uid = token();
+  const channel = new PrerenderChannel("result", uid);
+  const result = new Promise(r => channel.addEventListener("message", e => r(e.data)));
 
-  // Double-check we're set up correctly.
-  assert_equals(await outerPrerenderedRC.executeScript(() => document.prerendering), true);
+  window.open(
+    `resources/prerender-while-prerender-initiator.html?uid=${uid}`,
+    "_blank",
+    "noopener"
+  );
 
-  const innerPrerenderRC = await addPrerenderRC(outerPrerenderedRC);
+  assert_equals(
+    await result,
+    false,
+    "document.prerendering in the inner page must be false"
+  );
 
-  // Do not `await`. Since (per spec) prerendering is not allowed inside
-  // a prerender, there is not actually a real `RemoteContextHelper`
-  // representing the inner prerender at this time, since there is no
-  // prerender running. Instead, the `RemoteContextHelper` it is waiting
-  // for something to appear at its URL, which will happen later. At
-  // that time, the script will run. But `await`ing the script now would
-  // just block, since it will not run until that later point.
-  const scriptResultInInner = innerPrerenderRC.executeScript(() => document.prerendering);
-
-  // When the outer prerender is activated, inside the `prerenderingchange`
-  // event, attempt to activate the inner prerender. In reality, this will just
-  // perform a normal navigation to `innerPrerenderRC.url`.
-  await outerPrerenderedRC.executeScript(innerPrerenderRCURL => {
-    document.addEventListener("prerenderingchange", () => {
-      // executeScriptToNavigate is normally an implementation detail of the
-      // RemoteContextHelper framework, used by, e.g., `rch.navigateTo()`.
-      // However, because we're setting up an event listener to navigate later,
-      // we can't call `rch.navigateTo()`, and so need to call it directly.
-      executeScriptToNavigate(innerPrerenderRCURL => {
-        location.href = innerPrerenderRCURL;
-      }, [innerPrerenderRCURL]);
-    });
-  }, [innerPrerenderRC.url]);
-
-  // Now that everything is set up, activate the outer prerender.
-  await activatePrerenderRC(referrerRC, outerPrerenderedRC);
-
-  // Testing that this is false means two things:
-  // - The inner prerender attempt did not happen; we did a normal navigation
-  //   instead.
-  // - Nothing crashed or got confused.
-  assert_equals(await scriptResultInInner, false);
+  channel.close();
 }, "Prerendering inside a prerender doesn't work, and navigating inside prerenderingchange is fine");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/prerender-while-prerender-initiator.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/prerender-while-prerender-initiator.html
new file mode 100644
index 0000000..1764271
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/prerender-while-prerender-initiator.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Prerender while prerendering test: referrer page, opened in a window</title>
+<script src="utils.js"></script>
+
+<script type="module">
+const params = new URLSearchParams(location.search);
+const uid = params.get("uid");
+const outerURL = `prerender-while-prerender-outer.html?uid=${uid}`;
+
+startPrerendering(outerURL);
+
+const channel = new PrerenderChannel("start-test", uid);
+await new Promise(r => channel.addEventListener("message", r));
+channel.close();
+
+location.href = outerURL;
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/prerender-while-prerender-inner.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/prerender-while-prerender-inner.html
new file mode 100644
index 0000000..60b6c64
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/prerender-while-prerender-inner.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Prerender while prerendering test: inner maybe-prerendered page</title>
+
+<script>
+"use strict";
+window.onFirstScriptExecutedPrerendering = document.prerendering;
+</script>
+
+<script src="utils.js"></script>
+
+<script type="module">
+const params = new URLSearchParams(location.search);
+const uid = params.get("uid");
+
+const channel = new PrerenderChannel("result", uid);
+channel.postMessage(window.onFirstScriptExecutedPrerendering);
+channel.close();
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/prerender-while-prerender-outer.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/prerender-while-prerender-outer.html
new file mode 100644
index 0000000..313c3466
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/prerender-while-prerender-outer.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Prerender while prerendering test: outer prerendered page</title>
+<script src="utils.js"></script>
+
+<script type="module">
+const params = new URLSearchParams(location.search);
+const uid = params.get("uid");
+const innerURL = `prerender-while-prerender-inner.html?uid=${uid}`;
+
+startPrerendering(innerURL);
+// Wait 5 seconds for any potential prerender to start and get to the point
+// where it would send a message that would cause a failure.
+await new Promise(r => setTimeout(r, 5_000));
+
+document.addEventListener("prerenderingchange", () => {
+  location.href = innerURL;
+});
+
+const channel = new PrerenderChannel("start-test", uid);
+channel.postMessage("ready to start");
+channel.close();
+</script>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-and-redirect-cross-site-when-document-alive.https-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-and-redirect-cross-site-when-document-alive.https-expected.txt
index 3d34aece..c211689c 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-and-redirect-cross-site-when-document-alive.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-and-redirect-cross-site-when-document-alive.https-expected.txt
@@ -41,6 +41,7 @@
     redirectHasExtraInfo : false
     redirectResponse : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 248
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-and-redirect-when-document-alive.https-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-and-redirect-when-document-alive.https-expected.txt
index a10a7d4..94fe849 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-and-redirect-when-document-alive.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-and-redirect-when-document-alive.https-expected.txt
@@ -41,6 +41,7 @@
     redirectHasExtraInfo : false
     redirectResponse : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 226
@@ -95,6 +96,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 257
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-when-document-alive.https-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-when-document-alive.https-expected.txt
index 46ade91..80ee8aa 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-when-document-alive.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch-later/activate-when-document-alive.https-expected.txt
@@ -36,6 +36,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 334
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/content-type-utf16.php b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/content-type-utf16.php
new file mode 100644
index 0000000..5277e8c
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/content-type-utf16.php
@@ -0,0 +1,4 @@
+<?php
+  header("Content-Type: text/html; charset=utf-16");
+  echo base64_decode("PABwAD4ASQDxAHQA6wByAG4A4gB0AGkA9ABuAOAAbABpAHoA5gB0AGkA+ABuAAMmNNgG3zwALwBwAD4A");
+?>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/content-type.php b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/content-type.php
new file mode 100644
index 0000000..87b254a2
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/content-type.php
@@ -0,0 +1,11 @@
+<?php
+$contentType = $_GET["contentType"] ?? null;
+// If the magic quotes option is enabled, the charset could be escaped and we
+// would fail our test. For example, charset="utf-8" would become charset=\"utf-8\".
+if (get_magic_quotes_gpc()) {
+    $contentType = stripslashes($contentType);
+}
+header("Content-Type: $contentType");
+?>
+
+<p>Iñtërnâtiônàlizætiøn☃𝌆</p>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/response-charset-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/response-charset-expected.txt
new file mode 100644
index 0000000..68ded71
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/response-charset-expected.txt
@@ -0,0 +1,12 @@
+Tests that Network.Response includes the charset
+Network Enabled
+Fetching with no charset
+Network.Response.charset: 
+Fetching with utf-8
+Network.Response.charset: utf-8
+Fetching with iso-8869-1
+Network.Response.charset: iso-8859-1
+Fetching utf-16 content
+Network.Response.charset: utf-16
+Response body: <p>Iñtërnâtiônàlizætiøn☃𝌆</p>
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/response-charset.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/response-charset.js
new file mode 100644
index 0000000..d0a4757
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/response-charset.js
@@ -0,0 +1,43 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Tests that Network.Response includes the charset`);
+
+  await dp.Network.enable();
+  await dp.Network.setCacheDisabled({cacheDisabled: true});
+  testRunner.log('Network Enabled');
+
+  {
+    testRunner.log('Fetching with no charset');
+    session.evaluate(`fetch('/inspector-protocol/network/resources/content-type.php?contentType=${encodeURI('text/html')}');`);
+    const event = await dp.Network.onceResponseReceived();
+    testRunner.log(`Network.Response.charset: ${event.params.response.charset}`);
+    await dp.Network.onceLoadingFinished();  // Prevent racing with other tests.
+  }
+
+  {
+    testRunner.log('Fetching with utf-8');
+    session.evaluate(`fetch('/inspector-protocol/network/resources/content-type.php?contentType=${encodeURI('text/html; charset=utf-8')}');`);
+    const event = await dp.Network.onceResponseReceived();
+    testRunner.log(`Network.Response.charset: ${event.params.response.charset}`);
+    await dp.Network.onceLoadingFinished();  // Prevent racing with other tests.
+  }
+
+  {
+    testRunner.log('Fetching with iso-8869-1');
+    session.evaluate(`fetch('/inspector-protocol/network/resources/content-type.php?contentType=${encodeURI('text/html; charset=iso-8859-1')}');`);
+    const event = await dp.Network.onceResponseReceived();
+    testRunner.log(`Network.Response.charset: ${event.params.response.charset}`);
+    await dp.Network.onceLoadingFinished();  // Prevent racing with other tests.
+  }
+
+  {
+    testRunner.log('Fetching utf-16 content');
+    session.evaluate(`fetch('/inspector-protocol/network/resources/content-type-utf16.php');`);
+    const event = await dp.Network.onceResponseReceived();
+    testRunner.log(`Network.Response.charset: ${event.params.response.charset}`);
+    await dp.Network.onceLoadingFinished();
+    const {result: {body}} = await dp.Network.getResponseBody({requestId: event.params.requestId});
+    testRunner.log(`Response body: ${body}`);
+  }
+  testRunner.completeTest();
+});
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/permissions-policy-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/permissions-policy-expected.txt
index 1d9fda3bd..905837e 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/permissions-policy-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/permissions-policy-expected.txt
@@ -16,6 +16,14 @@
             frameId : <string>
         }
     }
+    [2] : {
+        allowed : false
+        feature : unload
+        locator : {
+            blockReason : Header
+            frameId : <string>
+        }
+    }
 ]
 {
     error : {
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt
index d02ebff..22bba0f 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt
@@ -58,6 +58,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 261
@@ -178,6 +179,7 @@
     redirectHasExtraInfo : true
     redirectResponse : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 248
@@ -272,6 +274,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : false
         encodedDataLength : 257
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt
index 0fb936b..ed83128 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt
@@ -58,6 +58,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 261
@@ -178,6 +179,7 @@
     redirectHasExtraInfo : true
     redirectResponse : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 226
@@ -273,6 +275,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 257
diff --git a/third_party/blink/web_tests/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt b/third_party/blink/web_tests/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt
index c2541f4..02c9218 100644
--- a/third_party/blink/web_tests/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt
+++ b/third_party/blink/web_tests/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt
@@ -1 +1,2 @@
+CONSOLE ERROR: Permissions policy violation: unload is not allowed in this document.
 PASS if no crash.
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
similarity index 66%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
copy to third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
index 6780d77..f9005d5 100644
--- a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
@@ -1,5 +1,4 @@
 This is a testharness.js-based test.
 [FAIL] document.open in beforeunload with button
-  assert_equals: expected "ABCDEFGHIJKLMN" but got "ABGLMN"
+  assert_equals: expected "ABCDEFGHIJKLMN" but got "ABGHLMN"
 Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch-reusable/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch-reusable/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt
index 10e56c8d..9e45c22 100644
--- a/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch-reusable/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt
+++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch-reusable/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt
@@ -58,6 +58,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 261
@@ -178,6 +179,7 @@
     redirectHasExtraInfo : true
     redirectResponse : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 247
@@ -272,6 +274,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : false
         encodedDataLength : 257
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch-reusable/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch-reusable/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt
index 3615107..72d6cb8 100644
--- a/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch-reusable/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt
+++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch-reusable/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt
@@ -58,6 +58,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 261
@@ -178,6 +179,7 @@
     redirectHasExtraInfo : true
     redirectResponse : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 225
@@ -273,6 +275,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 257
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt
index 10e56c8d..9e45c22 100644
--- a/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt
+++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect-cross-site.https-expected.txt
@@ -58,6 +58,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 261
@@ -178,6 +179,7 @@
     redirectHasExtraInfo : true
     redirectResponse : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 247
@@ -272,6 +274,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : false
         encodedDataLength : 257
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt
index 3615107..72d6cb8 100644
--- a/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt
+++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/prefetch/http/tests/inspector-protocol/prefetch/request-will-be-sent-redirect.https-expected.txt
@@ -58,6 +58,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 261
@@ -178,6 +179,7 @@
     redirectHasExtraInfo : true
     redirectResponse : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 225
@@ -273,6 +275,7 @@
     requestId : <string>
     response : {
         alternateProtocolUsage : unspecifiedReason
+        charset : 
         connectionId : <number>
         connectionReused : true
         encodedDataLength : 257
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/README.md b/third_party/blink/web_tests/virtual/deprecate-unload/README.md
deleted file mode 100644
index 4be2473..0000000
--- a/third_party/blink/web_tests/virtual/deprecate-unload/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-Tests that fail when unload is deprecated (--enable-features=DeprecateUnload).
-See https://crbug.com/1488371. Eventually DeprecateUnload will be on by default
-for tests, the expectations here will be moved into main suite and we will
-replace this suite with one that disables the deprecation.
-
-This should only contain tests that truly depend on unload. Tests that fail but
-can be rewritten not to use unload should not be included here.
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt b/third_party/blink/web_tests/virtual/deprecate-unload/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt
deleted file mode 100644
index 02c9218..0000000
--- a/third_party/blink/web_tests/virtual/deprecate-unload/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-CONSOLE ERROR: Permissions policy violation: unload is not allowed in this document.
-PASS if no crash.
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/http/tests/inspector-protocol/permissions-policy-expected.txt b/third_party/blink/web_tests/virtual/plz-dedicated-worker-disabled/http/tests/inspector-protocol/permissions-policy-expected.txt
similarity index 77%
rename from third_party/blink/web_tests/virtual/deprecate-unload/http/tests/inspector-protocol/permissions-policy-expected.txt
rename to third_party/blink/web_tests/virtual/plz-dedicated-worker-disabled/http/tests/inspector-protocol/permissions-policy-expected.txt
index 905837e..1d9fda3bd 100644
--- a/third_party/blink/web_tests/virtual/deprecate-unload/http/tests/inspector-protocol/permissions-policy-expected.txt
+++ b/third_party/blink/web_tests/virtual/plz-dedicated-worker-disabled/http/tests/inspector-protocol/permissions-policy-expected.txt
@@ -16,14 +16,6 @@
             frameId : <string>
         }
     }
-    [2] : {
-        allowed : false
-        feature : unload
-        locator : {
-            blockReason : Header
-            frameId : <string>
-        }
-    }
 ]
 {
     error : {
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt
new file mode 100644
index 0000000..c2541f4
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt
@@ -0,0 +1 @@
+PASS if no crash.
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/threaded/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/threaded/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/threaded/external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/threaded/external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window-expected.txt
diff --git a/third_party/blink/web_tests/virtual/unload-allowed/README.md b/third_party/blink/web_tests/virtual/unload-allowed/README.md
new file mode 100644
index 0000000..03f2a72
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/unload-allowed/README.md
@@ -0,0 +1,4 @@
+Tests that fail when unload is deprecated (--enable-features=DeprecateUnload).
+See https://crbug.com/1488371. DeprecateUnload is on by default for tests, the
+expectations here are for tests that require unload (usually because they are
+explicitly testing it).
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/fetch/api/redirect/redirect-keepalive.any-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/fetch/api/redirect/redirect-keepalive.any-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
rename to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/001-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
rename to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/001-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/002-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/002-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/003-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/003-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
similarity index 67%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
rename to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
index 6780d77..87334f6 100644
--- a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
+++ b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/004-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
 [FAIL] document.open in beforeunload with button
-  assert_equals: expected "ABCDEFGHIJKLMN" but got "ABGLMN"
+  assert_equals: expected "ABCDEFGHIJKLMN" but got "ABGHLMN"
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/005-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/005-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/004-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/004-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/007-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/007-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-cross-origin.window-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-cross-origin.window-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-same-origin.window-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-same-origin.window-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt
similarity index 66%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt
rename to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt
index af5565e..97f5695 100644
--- a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt
+++ b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt
@@ -1,22 +1,16 @@
 This is a testharness.js-based test.
-Found 9 FAIL, 0 TIMEOUT, 0 NOTRUN.
-[FAIL] shadowed unload (document.body)
-  assert_equals: alternative body should reflect expected (function) function "() => 0" but got (object) null
+Found 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
 [FAIL] not shadowed copy (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed cut (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed paste (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
-[FAIL] shadowed unload (document.createElement("body"))
-  assert_equals: body should reflect expected (function) function "() => 0" but got (object) null
 [FAIL] not shadowed copy (document.createElement("body"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed cut (document.createElement("body"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed paste (document.createElement("body"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
-[FAIL] shadowed unload (window)
-  assert_equals: body should reflect expected (function) function "() => 0" but got (object) null
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt
similarity index 66%
rename from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt
rename to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt
index 6cd6f8a..e18da97 100644
--- a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt
+++ b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt
@@ -1,22 +1,16 @@
 This is a testharness.js-based test.
-Found 9 FAIL, 0 TIMEOUT, 0 NOTRUN.
-[FAIL] shadowed unload (document.body)
-  assert_equals: alternative body should reflect expected (function) function "() => 0" but got (object) null
+Found 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
 [FAIL] not shadowed copy (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed cut (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed paste (document.body)
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
-[FAIL] shadowed unload (document.createElement("frameset"))
-  assert_equals: body should reflect expected (function) function "() => 0" but got (object) null
 [FAIL] not shadowed copy (document.createElement("frameset"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed cut (document.createElement("frameset"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
 [FAIL] not shadowed paste (document.createElement("frameset"))
   assert_equals: window should reflect expected (object) null but got (undefined) undefined
-[FAIL] shadowed unload (window)
-  assert_equals: body should reflect expected (function) function "() => 0" but got (object) null
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/webappapis/scripting/events/event-handler-attributes-windowless-body-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/html/webappapis/scripting/events/event-handler-attributes-windowless-body-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/external/wpt/permissions-policy/experimental-features/unload-disallowed-subframe.tentative.window-expected.txt
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger/skip-pause-during-navigation-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/http/tests/devtools/sources/debugger/skip-pause-during-navigation-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/http/tests/devtools/sources/debugger/skip-pause-during-navigation-expected.txt
rename to third_party/blink/web_tests/virtual/unload-allowed/http/tests/devtools/sources/debugger/skip-pause-during-navigation-expected.txt
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/http/tests/inspector-protocol/permissions-policy-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/http/tests/inspector-protocol/permissions-policy-expected.txt
similarity index 77%
copy from third_party/blink/web_tests/virtual/deprecate-unload/http/tests/inspector-protocol/permissions-policy-expected.txt
copy to third_party/blink/web_tests/virtual/unload-allowed/http/tests/inspector-protocol/permissions-policy-expected.txt
index 905837e..1d9fda3bd 100644
--- a/third_party/blink/web_tests/virtual/deprecate-unload/http/tests/inspector-protocol/permissions-policy-expected.txt
+++ b/third_party/blink/web_tests/virtual/unload-allowed/http/tests/inspector-protocol/permissions-policy-expected.txt
@@ -16,14 +16,6 @@
             frameId : <string>
         }
     }
-    [2] : {
-        allowed : false
-        feature : unload
-        locator : {
-            blockReason : Header
-            frameId : <string>
-        }
-    }
 ]
 {
     error : {
diff --git a/third_party/blink/web_tests/virtual/unload-allowed/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt b/third_party/blink/web_tests/virtual/unload-allowed/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt
new file mode 100644
index 0000000..c2541f4
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/unload-allowed/http/tests/navigation/image-css-load-in-subframe-unload-handler-expected.txt
@@ -0,0 +1 @@
+PASS if no crash.
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 4b85005e..1ed3912 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -6267,6 +6267,16 @@
     method constructor
     method item
     method namedItem
+interface ModelGenericSession
+    attribute @@toStringTag
+    method constructor
+    method execute
+    method executeStreaming
+interface ModelManager
+    attribute @@toStringTag
+    method canCreateGenericSession
+    method constructor
+    method createGenericSession
 interface Mojo
     static method bindInterface
     static method createDataPipe
@@ -12569,6 +12579,7 @@
     getter location
     getter locationbar
     getter menubar
+    getter model
     getter name
     getter navigation
     getter navigator
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/inset-area-anchor-outside.html b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/inset-area-anchor-outside.html
new file mode 100644
index 0000000..d49ac56
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/inset-area-anchor-outside.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>CSS Anchor Positioning: inset-area positioning - anchor outside containing block</title>
+<link rel="help" href="https://drafts.csswg.org/css-anchor-position/#inset-area">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/9598#issuecomment-1836854109">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+  #container {
+    position: relative;
+    width: 400px;
+    height: 400px;
+  }
+  #anchor {
+    position: absolute;
+    left: -200px;
+    top: 500px;
+    width: 100px;
+    height: 100px;
+    anchor-name: --anchor;
+  }
+  #anchored {
+    position: absolute;
+    anchor-default: --anchor;
+  }
+</style>
+<div id="container">
+  <div id="anchor"></div>
+  <div id="anchored"></div>
+</div>
+<script>
+  function test_inset_area(inset_area, expected_offsets) {
+    anchored.style.insetArea = inset_area;
+
+    test(() => {
+      assert_equals(anchored.offsetLeft, expected_offsets.left, "Check expected offsetLeft");
+      assert_equals(anchored.offsetTop, expected_offsets.top, "Check expected offsetTop");
+      assert_equals(anchored.offsetWidth, expected_offsets.width, "Check expected offsetWidth");
+      assert_equals(anchored.offsetHeight, expected_offsets.height, "Check expected offsetHeight");
+    }, "Offsets for inset-area: " + inset_area);
+  }
+
+  test_inset_area("all", {left:0, top:0, width:400, height:400});
+
+  test_inset_area("left / all", {left:-200, top:0, width:0, height:400});
+  test_inset_area("left center / all", {left:-100, top:0, width:0, height:400});
+  test_inset_area("center / top bottom", {left:-200, top:0, width:100, height:400});
+  test_inset_area("center right / all", {left:-200, top:0, width:600, height:400});
+  test_inset_area("right / all", {left:-100, top:0, width:500, height:400});
+
+  test_inset_area("top / all", {left:0, top:0, width:400, height:500});
+  test_inset_area("top center / all", {left:0, top:0, width:400, height:600});
+  test_inset_area("center / left right", {left:0, top:500, width:400, height:100});
+  test_inset_area("center bottom / all", {left:0, top:500, width:400, height:0});
+  test_inset_area("bottom / all", {left:0, top:600, width:400, height:0});
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/inset-area-anchor-partially-outside.html b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/inset-area-anchor-partially-outside.html
new file mode 100644
index 0000000..25e4da1
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/inset-area-anchor-partially-outside.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>CSS Anchor Positioning: inset-area positioning - anchor partially outside containing block</title>
+<link rel="help" href="https://drafts.csswg.org/css-anchor-position/#inset-area">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/9598#issuecomment-1836854109">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+  #container {
+    position: relative;
+    width: 400px;
+    height: 400px;
+  }
+  #anchor {
+    position: absolute;
+    right: -50px;
+    top: -50px;
+    width: 100px;
+    height: 100px;
+    anchor-name: --anchor;
+  }
+  #anchored {
+    position: absolute;
+    anchor-default: --anchor;
+  }
+</style>
+<div id="container">
+  <div id="anchor"></div>
+  <div id="anchored"></div>
+</div>
+<script>
+  function test_inset_area(inset_area, expected_offsets) {
+    anchored.style.insetArea = inset_area;
+
+    test(() => {
+      assert_equals(anchored.offsetLeft, expected_offsets.left, "Check expected offsetLeft");
+      assert_equals(anchored.offsetTop, expected_offsets.top, "Check expected offsetTop");
+      assert_equals(anchored.offsetWidth, expected_offsets.width, "Check expected offsetWidth");
+      assert_equals(anchored.offsetHeight, expected_offsets.height, "Check expected offsetHeight");
+    }, "Offsets for inset-area: " + inset_area);
+  }
+
+  test_inset_area("all", {left:0, top:0, width:400, height:400});
+
+  test_inset_area("left / all", {left:0, top:0, width:350, height:400});
+  test_inset_area("left center / all", {left:0, top:0, width:450, height:400});
+  test_inset_area("center / top bottom", {left:350, top:0, width:100, height:400});
+  test_inset_area("center right / all", {left:350, top:0, width:50, height:400});
+  test_inset_area("right / all", {left:450, top:0, width:0, height:400});
+
+  test_inset_area("top / all", {left:0, top:-50, width:400, height:0});
+  test_inset_area("top center / all", {left:0, top:0, width:400, height:50});
+  test_inset_area("center / left right", {left:0, top:-50, width:400, height:100});
+  test_inset_area("center bottom / all", {left:0, top:-50, width:400, height:450});
+  test_inset_area("bottom / all", {left:0, top:50, width:400, height:350});
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/inset-area-with-insets.html b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/inset-area-with-insets.html
new file mode 100644
index 0000000..e2e0340
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/inset-area-with-insets.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<title>CSS Anchor Positioning: inset-area positioning with additional insets</title>
+<link rel="help" href="https://drafts.csswg.org/css-anchor-position/#inset-area">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/9598#issuecomment-1836854109">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!-- The grid:
+
+          100      150      150
+      +--------+--------+--------+
+      |        |        |        |
+  150 |        |        |        |
+      |        |        |        |
+      +--------+--------+--------+
+      |        |        |        |
+   75 |        |        |        |
+      |        |        |        |
+      +--------+--------+--------+
+      |        |        |        |
+  175 |        |        |        |
+      |        |        |        |
+      +--------+--------+--------+
+
+  -->
+<style>
+  #container {
+    position: absolute;
+    width: 400px;
+    height: 400px;
+  }
+  #anchored {
+    position: absolute;
+    anchor-default: --anchor;
+  }
+  #anchor {
+    margin-top: 150px;
+    margin-left: 100px;
+    width: 150px;
+    height: 75px;
+    anchor-name: --anchor;
+  }
+</style>
+<div id="container">
+  <div id="anchored"></div>
+  <div id="anchor"></div>
+</div>
+<script>
+  function test_inset_area(inset_area, insets, expected_offsets) {
+    anchored.style.insetArea = inset_area;
+    for (const [prop, value] of Object.entries(insets)) {
+      anchored.style[prop] = value;
+    }
+
+    test(() => {
+      assert_equals(anchored.offsetLeft, expected_offsets.left, "Check expected offsetLeft");
+      assert_equals(anchored.offsetTop, expected_offsets.top, "Check expected offsetTop");
+      assert_equals(anchored.offsetWidth, expected_offsets.width, "Check expected offsetWidth");
+      assert_equals(anchored.offsetHeight, expected_offsets.height, "Check expected offsetHeight");
+    }, "Offsets for inset-area: " + inset_area + " and insets: " + JSON.stringify(insets));
+  }
+
+  test_inset_area("all", {top:"5px", bottom:"5px", left:"5px", right:"5px"},
+                  {left:5, top:5, width:390, height:390});
+
+  test_inset_area("center / center", {top:"10px", bottom:"40px", left:"5px", right:"15px"},
+                  {left:105, top:160, width:130, height:25});
+
+  test_inset_area("left / bottom", {top:"10px", bottom:"40px", left:"5px", right:"15px"},
+                  {left:5, top:235, width:80, height:125});
+
+  test_inset_area("center right / center", {top:"20%", bottom:"auto", left:"auto", right:"25%"},
+                  {left:100, top:165, width:225, height:60});
+
+  // No implicit anchor means the inset-area should not apply, but the insets still should.
+  anchored.style.anchorDefault = "implicit";
+  test_inset_area("bottom / right", {left:"50px", right:"100px", top:"30px" , bottom:"10px"},
+                  {left:50, top:30, width:250, height:360});
+</script>
diff --git a/third_party/dawn b/third_party/dawn
index 33ffb37..fc8f2b6 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit 33ffb3786277319c85806c06fcf51a6fbbb21aee
+Subproject commit fc8f2b61a0e606040b3a5f88d16692b3c44b1970
diff --git a/third_party/depot_tools b/third_party/depot_tools
index 6592c25..9f668bb 160000
--- a/third_party/depot_tools
+++ b/third_party/depot_tools
@@ -1 +1 @@
-Subproject commit 6592c255249330478d24c29866cc4e5967a7a951
+Subproject commit 9f668bbff99167ba797888c6d322dd309f338aee
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index bfe8ffef..c957575 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-13-2-98-g7bac4d146
-Revision: 7bac4d146a86482c154bf878221ff321faccac4c
+Version: VER-2-13-2-100-g576177824
+Revision: 57617782464411201ce7bbc93b086c1b4d7d84a5
 CPEPrefix: cpe:/a:freetype:freetype:2.13.2
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
diff --git a/third_party/freetype/src b/third_party/freetype/src
index 7bac4d1..5761778 160000
--- a/third_party/freetype/src
+++ b/third_party/freetype/src
@@ -1 +1 @@
-Subproject commit 7bac4d146a86482c154bf878221ff321faccac4c
+Subproject commit 57617782464411201ce7bbc93b086c1b4d7d84a5
diff --git a/third_party/libc++/src b/third_party/libc++/src
index 69115fd..53801f26 160000
--- a/third_party/libc++/src
+++ b/third_party/libc++/src
@@ -1 +1 @@
-Subproject commit 69115fd1bdb6ffc918b5559eaef1d0caeb3a045a
+Subproject commit 53801f26327be0359ffd785d2c9b186067ac6ef6
diff --git a/third_party/skia b/third_party/skia
index 56b6168..7708357 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit 56b616844ff7afddf73ae342ac4287a816603ca2
+Subproject commit 770835703800e0017d21c39414c615004675913d
diff --git a/third_party/webrtc b/third_party/webrtc
index f8587da7..edd80481 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit f8587da72b065606a1b5e2074f628f9cc1473604
+Subproject commit edd804816cd1e57374717e9e2bdd2c4237b6e692
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 1a2da32e..bdcfe0b 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -1664,6 +1664,7 @@
   <int value="2" label="Unsupported because HTTP method is not GET"/>
   <int value="3" label="Unsupported non-HTTP scheme URL request"/>
   <int value="4" label="Unsupported keepalive request"/>
+  <int value="5" label="Unsupported request from prefetch only document"/>
 </enum>
 
 <enum name="BackgroundSyncFiredEvents">
@@ -20135,6 +20136,7 @@
   <int value="-1863020461" label="PasswordChangeInSettings:enabled"/>
   <int value="-1861814223" label="MidiManagerDynamicInstantiation:enabled"/>
   <int value="-1861278695" label="BulkTabRestore:enabled"/>
+  <int value="-1860959988" label="Picker:disabled"/>
   <int value="-1860481724" label="ChromeHomeExpandButton:enabled"/>
   <int value="-1860477300" label="DefaultStyleSheetsEarlyInit:disabled"/>
   <int value="-1860459751" label="CastEnableStreamingWithHiDPI:disabled"/>
@@ -21224,6 +21226,7 @@
   <int value="-1351968795" label="SingleProcessMash:enabled"/>
   <int value="-1351328710"
       label="OmniboxUIExperimentJogTextfieldOnPopup:disabled"/>
+  <int value="-1351107814" label="Picker:enabled"/>
   <int value="-1349896789" label="DelayNavigation:enabled"/>
   <int value="-1349872906"
       label="disallow-autofill-sync-credential-for-reauth"/>
diff --git a/tools/metrics/histograms/metadata/page/enums.xml b/tools/metrics/histograms/metadata/page/enums.xml
index aba0295..234c0df 100644
--- a/tools/metrics/histograms/metadata/page/enums.xml
+++ b/tools/metrics/histograms/metadata/page/enums.xml
@@ -190,13 +190,6 @@
   <int value="1" label="Prerender Activation Navigation"/>
 </enum>
 
-<enum name="PageLoadPrerenderForegroundCheckResult">
-  <int value="0" label="Activated in background"/>
-  <int value="1" label="No event time"/>
-  <int value="2" label="Backgrounded before the event"/>
-  <int value="3" label="Passed the check"/>
-</enum>
-
 <enum name="PageLoadPrerenderObserverEvent">
   <int value="0" label="OnPrerenderStart"/>
   <int value="1" label="DidActivatePrerenderedPage"/>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index db86fc7..21d2337 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -2586,23 +2586,6 @@
   </summary>
 </histogram>
 
-<histogram
-    name="PageLoad.Internal.Prerender2.ForegroundCheckResult.{PageLoadPrerenderForegroundCheckEvent}"
-    enum="PageLoadPrerenderForegroundCheckResult" expires_after="2024-05-12">
-  <owner>nhiroki@chromium.org</owner>
-  <owner>src/content/browser/preloading/prerender/OWNERS</owner>
-  <summary>
-    Records results of the foreground check per event type in
-    PrerenderPageLoadMetricsObserver.
-  </summary>
-  <token key="PageLoadPrerenderForegroundCheckEvent">
-    <variant name="FirstContentfulPaint"/>
-    <variant name="FirstInputDelay"/>
-    <variant name="FirstPaint"/>
-    <variant name="LargestContentfulPaint"/>
-  </token>
-</histogram>
-
 <histogram name="PageLoad.Internal.Prerender2.ObserverEvent"
     enum="PageLoadPrerenderObserverEvent" expires_after="2024-05-12">
   <owner>nhiroki@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/sync/enums.xml b/tools/metrics/histograms/metadata/sync/enums.xml
index a5a222a..40802034 100644
--- a/tools/metrics/histograms/metadata/sync/enums.xml
+++ b/tools/metrics/histograms/metadata/sync/enums.xml
@@ -460,6 +460,26 @@
   <int value="100248" label="ListenToThisPageEnabled"/>
   <int value="100249" label="IpProtectionEnabled"/>
   <int value="100250" label="AccessibilityReadAnythingLinksEnabled"/>
+  <int value="100251"
+      label="kProfileContentSettingsPartitionedExceptionsAntiAbuse"/>
+  <int value="100252"
+      label="kProfileContentSettingsPartitionedExceptionsAutomaticDownloads"/>
+  <int value="100253"
+      label="kProfileContentSettingsPartitionedExceptionsCookies"/>
+  <int value="100254"
+      label="kProfileContentSettingsPartitionedExceptionsGetDisplayMediaSetSelectAllScreens"/>
+  <int value="100255"
+      label="kProfileContentSettingsPartitionedExceptionsImages"/>
+  <int value="100256"
+      label="kProfileContentSettingsPartitionedExceptionsJavascript"/>
+  <int value="100257"
+      label="kProfileContentSettingsPartitionedExceptionsLocalFonts"/>
+  <int value="100258"
+      label="kProfileContentSettingsPartitionedExceptionsMouselock"/>
+  <int value="100259"
+      label="kProfileContentSettingsPartitionedExceptionsPopups"/>
+  <int value="100260"
+      label="kProfileContentSettingsPartitionedExceptionsWindowPlacement"/>
   <int value="200000" label="ArticlesForYouEnabled"/>
   <int value="200001" label="ContextualSearchEnabled_IOS"/>
   <int value="200002" label="DefaultCharset_IOS"/>
diff --git a/tools/metrics/histograms/metadata/v8/histograms.xml b/tools/metrics/histograms/metadata/v8/histograms.xml
index bf5b2a0..b8d5879 100644
--- a/tools/metrics/histograms/metadata/v8/histograms.xml
+++ b/tools/metrics/histograms/metadata/v8/histograms.xml
@@ -1271,13 +1271,16 @@
   </summary>
 </histogram>
 
-<histogram name="V8.ProduceCodeCache" units="ms" expires_after="2024-06-30">
-  <owner>chikamune@chromium.org</owner>
+<histogram name="V8.ProduceCodeCacheMicroseconds" units="microseconds"
+    expires_after="2024-06-30">
+  <owner>sisidovski@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
   <summary>
     Time spent serializing and persisting code (mojo call) for V8 code caching.
     Recorded when ProduceCacheInternal() is called. Only recorded when producing
     a code cache is required.
+
+    This histogram only records metrics on machines with high-resolution clocks.
   </summary>
 </histogram>
 
diff --git a/ui/file_manager/integration_tests/file_manager/file_transfer_connector.js b/ui/file_manager/integration_tests/file_manager/file_transfer_connector.js
index 5dbb2c9..d23b5c08 100644
--- a/ui/file_manager/integration_tests/file_manager/file_transfer_connector.js
+++ b/ui/file_manager/integration_tests/file_manager/file_transfer_connector.js
@@ -431,6 +431,9 @@
 const SINGLE_FILE_WARN_MESSAGE = 'c_warned.jpg may contain sensitive content';
 const TWO_FILES_WARN_MESSAGE = '2 files may contain sensitive content';
 
+const COPY_OUT_OF_SPACE_ERROR_MESSAGE =
+    'Copy operation failed. There is not enough space.';
+
 /**
  * Opens a Files app's main window and creates the source and destination
  * entries.
@@ -570,19 +573,7 @@
  */
 async function transferBetweenVolumes(
     transferInfo, entryTestSet, expectedFinalMsg, expectedWarnMsg = '') {
-  // Setup volumes
-  if (transferInfo.source.volumeName === 'usb' ||
-      transferInfo.destination.volumeName === 'usb') {
-    await sendTestMessage({name: 'mountFakeUsbEmpty'});
-  }
-  if (transferInfo.source.volumeName === 'smbfs' ||
-      transferInfo.destination.volumeName === 'smbfs') {
-    await sendTestMessage({name: 'mountSmbfs'});
-  }
-  if (transferInfo.source.volumeName === 'mtp' ||
-      transferInfo.destination.volumeName === 'mtp') {
-    await sendTestMessage({name: 'mountFakeMtpEmpty'});
-  }
+  await setupVolumes(transferInfo);
 
   // Setup policy.
   await sendTestMessage({
@@ -609,12 +600,95 @@
         entryTestSet.filter(entry => !entry.targetPath.includes('/')).length,
   });
 
+  const appId = await openFilesAppAndInitTransfer(transferInfo, entryTestSet);
+
+  const reportOnly =
+      await sendTestMessage({name: 'isReportOnlyFileTransferConnector'}) ===
+      'true';
+  if (reportOnly) {
+    await verifyAfterPasteReportOnly(appId, transferInfo, entryTestSet);
+  } else {
+    await verifyAfterPasteBlocking(
+        appId, transferInfo, entryTestSet, expectedFinalMsg, expectedWarnMsg);
+  }
+}
+
+/**
+ * Test function to copy from the specified source to the specified destination.
+ * @param {!TransferInfo} transferInfo Options for the transfer.
+ * @param {!Array<!TestEntryInfo>} entryTestSet The set of file and directory
+ *     entries to be used for the test.
+ * @param {string} expectedFinalMsg The final message to expect at the progress
+ *     center.
+ */
+async function transferBetweenVolumesNoSpace(
+    transferInfo, entryTestSet, expectedFinalMsg) {
+  // Ensure reportOnly is set, as the no-space behavior is special for
+  // report-only mode.
+  const reportOnly =
+      await sendTestMessage({name: 'isReportOnlyFileTransferConnector'}) ===
+      'true';
+  chrome.test.assertTrue(reportOnly);
+
+
+  await setupVolumes(transferInfo);
+
+  // Setup policy.
+  await sendTestMessage({
+    name: 'setupFileTransferPolicy',
+    source: transferInfo.source.enterpriseConnectorsVolumeIdentifier,
+    destination: transferInfo.destination.enterpriseConnectorsVolumeIdentifier,
+  });
+
+  await sendTestMessage({
+    name: 'mockIOTaskDestinationNoSpace',
+  });
+
+  // Setup the scanning closure to be able to wait for the scanning to be
+  // complete. There should only be one delegate, as all other delegates aren't
+  // initiated when an out of space error occurs.
+  await sendTestMessage({
+    name: 'setupScanningRunLoop',
+    number_of_expected_delegates: 1,
+  });
+
+  const appId = await openFilesAppAndInitTransfer(transferInfo, entryTestSet);
+
+  await verifyAfterPasteReportOnlyNoSpace(
+      appId, transferInfo, expectedFinalMsg, entryTestSet);
+}
+
+/**
+ * Mounts required volumes.
+ * @param {!TransferInfo} transferInfo Options for the transfer.
+ */
+async function setupVolumes(transferInfo) {
+  if (transferInfo.source.volumeName === 'usb' ||
+      transferInfo.destination.volumeName === 'usb') {
+    await sendTestMessage({name: 'mountFakeUsbEmpty'});
+  }
+  if (transferInfo.source.volumeName === 'smbfs' ||
+      transferInfo.destination.volumeName === 'smbfs') {
+    await sendTestMessage({name: 'mountSmbfs'});
+  }
+  if (transferInfo.source.volumeName === 'mtp' ||
+      transferInfo.destination.volumeName === 'mtp') {
+    await sendTestMessage({name: 'mountFakeMtpEmpty'});
+  }
+}
+
+/**
+ * Opens Files app and initiates source with entryTestSet and destination
+ * with [ENTRIES.hello].
+ * The destination is populated to prevent flakes (we can wait for the `hello`
+ * file to appear).
+ * @param {!TransferInfo} transferInfo Options for the transfer.
+ * @param {!Array<!TestEntryInfo>} entryTestSet The set of file and directory
+ *     entries to be used for the test.
+ */
+async function openFilesAppAndInitTransfer(transferInfo, entryTestSet) {
   const dstContents = TestEntryInfo.getExpectedRows([ENTRIES.hello]);
 
-  // Opens Files app and initiates source with entryTestSet and destination
-  // with [ENTRIES.hello].
-  // The destination is populated to prevent flakes (we can wait for the `hello`
-  // file to appear).
   const appId = await setupForFileTransferConnector(
       transferInfo, entryTestSet, [ENTRIES.hello]);
 
@@ -657,16 +731,7 @@
   // This will execute the actual paste.
   chrome.test.assertTrue(
       await remoteCall.callRemoteTestUtil('execCommand', appId, ['paste']));
-
-  const reportOnly =
-      await sendTestMessage({name: 'isReportOnlyFileTransferConnector'}) ===
-      'true';
-  if (reportOnly) {
-    await verifyAfterPasteReportOnly(appId, transferInfo, entryTestSet);
-  } else {
-    await verifyAfterPasteBlocking(
-        appId, transferInfo, entryTestSet, expectedFinalMsg, expectedWarnMsg);
-  }
+  return appId;
 }
 
 /**
@@ -869,6 +934,50 @@
 }
 
 /**
+ * Verify what happens after a paste in the case of report-only scans if
+ * there's a no space error.
+ *
+ * @param {string} appId The app id of the files app window.
+ * @param {!TransferInfo} transferInfo Options for the transfer.
+ * @param {string} expectedFinalMsg The final message to expect at the progress
+ *     center.
+ * @param {!Array<!TestEntryInfo>} entryTestSet The set of file and directory
+ *     entries to be used for the test.
+ */
+async function verifyAfterPasteReportOnlyNoSpace(
+    appId, transferInfo, expectedFinalMsg, entryTestSet) {
+  // No check for scanning label, as there shouldn't be one.
+
+  // Wait for the expected files to appear in the file list.
+  // Only the hello file should appear, as the destination is assumed to be out
+  // of space.
+  const expectedEntries = [ENTRIES.hello];
+  await verifyDirectoryRecursively(
+      appId, expectedEntries, transferInfo.destination.breadcrumbsPath);
+
+  // Verify contents of the source directory.
+  const directoryTree = await DirectoryTreePageObject.create(appId, remoteCall);
+  await directoryTree.navigateToPath(transferInfo.source.breadcrumbsPath);
+  // The source entries should be unchanged.
+  const expectedSourceEntries = entryTestSet;
+  // Wait for the expected files to appear in the file list.
+  await verifyDirectoryRecursively(
+      appId, expectedSourceEntries, transferInfo.source.breadcrumbsPath);
+
+  // Check that only one line of text is shown.
+  await remoteCall.waitForFeedbackPanelItem(
+      appId, new RegExp(`^${expectedFinalMsg}$`), new RegExp(`^$`));
+
+  // After the transfer completed, we issue scanning responses.
+  // This ensures that scanning does not impact the transfer.
+  await sendTestMessage({name: 'issueFileTransferResponses'});
+
+  // We have to wait for the scanning to be completed to fulfill the report
+  // expectations.
+  await sendTestMessage({name: 'waitForFileTransferScanningToComplete'});
+}
+
+/**
  * Tests copying from android_files to Downloads.
  */
 testcase.transferConnectorFromAndroidFilesToDownloadsDeep = () => {
@@ -939,6 +1048,18 @@
       OLD_COPY_FAIL_MESSAGE,
   );
 };
+testcase
+    .transferConnectorFromDriveToDownloadsFlatDestinationNoSpaceForReportOnly =
+    () => {
+      return transferBetweenVolumesNoSpace(
+          new TransferInfo({
+            source: TRANSFER_LOCATIONS.drive,
+            destination: TRANSFER_LOCATIONS.downloads,
+          }),
+          CONNECTOR_ENTRIES_FLAT,
+          COPY_OUT_OF_SPACE_ERROR_MESSAGE,
+      );
+    };
 
 /**
  * Tests moving from Drive to Downloads.
diff --git a/ui/message_center/views/notification_view_base.h b/ui/message_center/views/notification_view_base.h
index b654822..e1083ac 100644
--- a/ui/message_center/views/notification_view_base.h
+++ b/ui/message_center/views/notification_view_base.h
@@ -126,6 +126,10 @@
   // Whether the notification view is showing `icon_view_`.
   virtual bool IsIconViewShown() const;
 
+  views::ProgressBar* progress_bar_view_for_testing() {
+    return progress_bar_view_;
+  }
+
  protected:
   explicit NotificationViewBase(const Notification& notification);
 
diff --git a/v8 b/v8
index 670e12f..d945cbe 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit 670e12fa6ee88250bc5c7070ffcc7483159d94a4
+Subproject commit d945cbe39f0a270cc44e56fc263c0953c575e366