diff --git a/DEPS b/DEPS
index 017b1be..29a7fdc 100644
--- a/DEPS
+++ b/DEPS
@@ -285,7 +285,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '7a0879961df5581fa4ae6dcaf2ab49a14fb56d14',
+  'skia_revision': 'a4965132249fccdb385396b0ae70feb1d6526453',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -297,7 +297,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': 'c0e5813a9b7754690dbae7cd71ce35f21ca9d98c',
+  'swiftshader_revision': '23e97b79fb9193bf88e79c16c6a577c680edb2d6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -312,7 +312,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:12.20230424.2.1',
+  'fuchsia_version': 'version:12.20230425.2.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -412,7 +412,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'c1b3c7431680e8e67bfde55ae6dd9ff3b13a235c',
+  'dawn_revision': '41428ad681b574566150224df611e3e890bac45f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -782,7 +782,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '260272d28aaaf75169bce1d666416322490485c8',
+    '1e7addc3f992289974c43046d17b84b9e3ea0269',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1120,7 +1120,7 @@
     Var('boringssl_git') + '/boringssl.git' + '@' +  Var('boringssl_revision'),
 
   'src/third_party/breakpad/breakpad':
-    Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '9bf8d1ec526cec139b2d3fba148ce81ccf2cceab',
+    Var('chromium_git') + '/breakpad/breakpad.git' + '@' + 'bfde407de559c10d6cef861b3873ff287c24e761',
 
   'src/third_party/byte_buddy': {
       'packages': [
@@ -1212,7 +1212,7 @@
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '07920ea30a1582b3e725644314d18601a50c48b5',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '3f74ae65e59bc7d64cefde5b29d0199931d27926',
     'condition': 'checkout_src_internal',
   },
 
@@ -1450,7 +1450,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/kotlinc',
-              'version': 'Ly0WLNcc5HwMFsqSGLX4OrQ8nivZ9w8nSJyU7BsPIRkC',
+              'version': 'J3BAlA7yf4corBopDhlwuT9W4jR1Z9R55KD3BUTVldQC',
           },
       ],
       'condition': 'checkout_android',
@@ -1832,7 +1832,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@5af3991936547a33ed74d01ce0fa903f3c9b65eb',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@a52479099cf2862650df9dbc12e2e202e345901e',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1872,7 +1872,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '7d2d22292ce5af280c8c5849ed7f0679d7ab70e9',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '39e859901b6c071a75c164b41e6caf1601a9fae9',
+    Var('webrtc_git') + '/src.git' + '@' + 'df7df199abd619e75b9f1d9a7e12fc3f3f748775',
 
   # 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.
@@ -1962,7 +1962,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': Var('chrome_git') + '/chrome/src-internal.git@13c8322f8338ad718e59542055b60d60382c2fcb',
+    'url': Var('chrome_git') + '/chrome/src-internal.git@8019bd14d023941690da94e4eb019a1c6c639fed',
     'condition': 'checkout_src_internal',
   },
 
@@ -1992,7 +1992,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'PQZS77LjDYkFRUgKzXa2J1keoJrr_-9iu2O2ydWtS5cC',
+        'version': 'Ze_KerbEA1_oIFtFVPvdjcRK7adBzAsLMx_M7VSnFD4C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
index 679e7c3..b69831e5 100644
--- a/android_webview/browser/aw_browser_main_parts.cc
+++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -173,6 +173,14 @@
       AwWebUIControllerFactory::GetInstance());
   content::RenderFrameHost::AllowInjectingJavaScript();
   metrics_logger_ = std::make_unique<metrics::MemoryMetricsLogger>();
+
+  // Requesting the |OriginTrialsControllerDelegate| will initialize
+  // it if the feature is enabled.
+  //
+  // This should be done as soon as possible in the start-up process, in order
+  // to load the database from disk.
+  AwBrowserContext::GetDefault()->GetOriginTrialsControllerDelegate();
+
   return content::RESULT_CODE_NORMAL_EXIT;
 }
 
@@ -181,28 +189,12 @@
   NOTREACHED();
 }
 
-namespace {
-
-void LoadOriginTrialsControllerDelegateOnUiThread() {
-  // Requesting the |OriginTrialsControllerDelegate| will initialize
-  // it if the feature is enabled.
-  //
-  // This should be done as soon as possible in the start-up process, in order
-  // to load the database from disk.
-  AwBrowserContext::GetDefault()->GetOriginTrialsControllerDelegate();
-}
-
-}  // namespace
-
 void AwBrowserMainParts::PostCreateThreads() {
   heap_profiling::Mode mode = heap_profiling::GetModeForStartup();
   if (mode != heap_profiling::Mode::kNone)
     heap_profiling::Supervisor::GetInstance()->Start(base::NullCallback());
 
   MaybeSetupSystemTracing();
-
-  content::GetUIThreadTaskRunner({})->PostTask(
-      FROM_HERE, base::BindOnce(&LoadOriginTrialsControllerDelegateOnUiThread));
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 3356f33..42c3e6b 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -1102,7 +1102,14 @@
     const url::Origin* source_origin,
     const url::Origin* destination_origin,
     const url::Origin* reporting_origin) {
-  return false;
+  // WebView only supports OS-level attribution and not web-attribution.
+  return operation == AttributionReportingOperation::kAny ||
+         operation == AttributionReportingOperation::kOsSource ||
+         operation == AttributionReportingOperation::kOsTrigger;
+}
+
+bool AwContentBrowserClient::IsWebAttributionReportingAllowed() {
+  return false;  // WebView does not support web-only attribution.
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index 9ef948ad..2d57d80 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -257,6 +257,7 @@
       const url::Origin* source_origin,
       const url::Origin* destination_origin,
       const url::Origin* reporting_origin) override;
+  bool IsWebAttributionReportingAllowed() override;
 
   AwFeatureListCreator* aw_feature_list_creator() {
     return aw_feature_list_creator_;
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 82650848..7ca7cc6 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
@@ -419,6 +419,9 @@
                     "Enables converting trackpad click gestures to mouse events"
                             + " in order for them to be interpreted similar to a desktop"
                             + " experience (i.e. double-click to select word.)"),
+            Flag.baseFeature(NetworkServiceFeatures.ATTRIBUTION_REPORTING_CROSS_APP_WEB,
+                    "Enable attribution reporting to cross the app/web barrier by letting "
+                            + "the WebView use OS-level attribution."),
             // Add new commandline switches and features above. The final entry should have a
             // trailing comma for cleaner diffs.
     };
diff --git a/android_webview/tools/system_webview_shell/apk/AndroidManifest.xml b/android_webview/tools/system_webview_shell/apk/AndroidManifest.xml
index 72942df9..59ebf4c 100644
--- a/android_webview/tools/system_webview_shell/apk/AndroidManifest.xml
+++ b/android_webview/tools/system_webview_shell/apk/AndroidManifest.xml
@@ -16,6 +16,8 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
     <uses-permission android:name="android.permission.USE_CREDENTIALS"/>
+    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION"/>
+
 
     <!-- "Dangerous" permissions which require user prompt -->
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
diff --git a/ash/README.md b/ash/README.md
index 33863d5..3b5c8652 100644
--- a/ash/README.md
+++ b/ash/README.md
@@ -30,18 +30,6 @@
 same directory as the class under test (e.g. //ash/foo rather than //ash/test).
 Test code uses namespace ash; there is no special "test" namespace.
 
-base::raw_ptr<>
----------------
-Use of [base::raw_ptr<>](/base/memory/raw_ptr.md) is *allowed* but
-*not required* in //ash.
-
-Chromium's Windows and Android codebases were converted in mid-2022 to use
-base:raw_ptr<> for class and struct members as part of the "MiraclePtr" security
-project. ChromeOS code was not converted, hence //ash was not converted.
-
-Until //ash is bulk converted (no ETA yet), feel free to use traditional
-pointer members if that would be more consistent with surrounding code.
-
 Prefs
 -----
 Ash supports both per-user prefs and device-wide prefs. These are called
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 4f24c24..330dd2a 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -1672,7 +1672,7 @@
 // Determine should we display Beta badge for Eche.
 BASE_FEATURE(kPhoneHubAppStreamingBetaBadge,
              "kPhoneHubAppStreamingBetaBadge",
-             base::FEATURE_ENABLED_BY_DEFAULT);
+             base::FEATURE_DISABLED_BY_DEFAULT);
 
 // Enables the incoming/ongoing call notification feature in Phone Hub.
 BASE_FEATURE(kPhoneHubCallNotification,
diff --git a/ash/system/channel_indicator/channel_indicator_quick_settings_view.cc b/ash/system/channel_indicator/channel_indicator_quick_settings_view.cc
index 7543314..2a724e2 100644
--- a/ash/system/channel_indicator/channel_indicator_quick_settings_view.cc
+++ b/ash/system/channel_indicator/channel_indicator_quick_settings_view.cc
@@ -14,6 +14,7 @@
 #include "ash/style/ash_color_id.h"
 #include "ash/style/icon_button.h"
 #include "ash/style/style_util.h"
+#include "ash/style/typography.h"
 #include "ash/system/channel_indicator/channel_indicator_utils.h"
 #include "ash/system/model/system_tray_model.h"
 #include "ash/system/tray/tray_constants.h"
@@ -23,6 +24,7 @@
 #include "base/ranges/algorithm.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkScalar.h"
+#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rounded_corners_f.h"
@@ -272,10 +274,10 @@
  private:
   void SetBackgroundAndFont() {
     if (features::IsQsRevampEnabled()) {
-      // TODO(b/252873172): Revisit font style and color. For now use the
-      // default size (which is obviously too small).
-      SetEnabledTextColors(
-          GetColorProvider()->GetColor(kColorAshTextColorSecondary));
+      SetEnabledTextColorIds(cros_tokens::kCrosSysOnSurfaceVariant);
+      label()->SetFontList(
+          ash::TypographyProvider::Get()->ResolveTypographyToken(
+              ash::TypographyToken::kCrosBody2));
     } else {
       label()->SetFontList(
           gfx::FontList().DeriveWithWeight(gfx::Font::Weight::MEDIUM));
@@ -360,8 +362,7 @@
   void OnThemeChanged() override {
     auto* color_provider = GetColorProvider();
     if (features::IsQsRevampEnabled()) {
-      // TODO(b/252873172): Revisit icon color.
-      SetIconColor(color_provider->GetColor(kColorAshIconColorSecondary));
+      SetIconColorId(cros_tokens::kCrosSysOnSurfaceVariant);
 
       const SkColor ink_drop_base_color =
           color_provider->GetColor(kColorAshInkDropOpaqueColor);
diff --git a/ash/system/unified/feature_tile.cc b/ash/system/unified/feature_tile.cc
index 6a8631d2..18c2fb2 100644
--- a/ash/system/unified/feature_tile.cc
+++ b/ash/system/unified/feature_tile.cc
@@ -116,6 +116,8 @@
 
   label_ = title_container->AddChildView(std::make_unique<views::Label>());
   label_->SetAutoColorReadabilityEnabled(false);
+  label_->SetFontList(ash::TypographyProvider::Get()->ResolveTypographyToken(
+      ash::TypographyToken::kCrosButton2));
 
   if (is_compact) {
     label_->SetPreferredSize(kCompactTitleLabelSize);
@@ -123,16 +125,15 @@
     // clipping and center aligned.
     label_->SetMultiLine(true);
     label_->SetLineHeight(kCompactTitleLineHeight);
-    // TODO(b/252873172): update FontList.
-    label_->SetFontList(views::Label::GetDefaultFontList().Derive(
-        -1, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::NORMAL));
+    label_->SetFontList(ash::TypographyProvider::Get()->ResolveTypographyToken(
+        ash::TypographyToken::kCrosAnnotation2));
   } else {
     sub_label_ =
         title_container->AddChildView(std::make_unique<views::Label>());
     sub_label_->SetAutoColorReadabilityEnabled(false);
-    // TODO(b/252873172): update FontList.
-    sub_label_->SetFontList(views::Label::GetDefaultFontList().Derive(
-        -1, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::NORMAL));
+    sub_label_->SetFontList(
+        ash::TypographyProvider::Get()->ResolveTypographyToken(
+            ash::TypographyToken::kCrosAnnotation1));
     sub_label_->SetLineHeight(kPrimarySubtitleLineHeight);
     if (chromeos::features::IsJellyEnabled()) {
       TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosAnnotation1,
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 8f13e51..425cb0a 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2777,6 +2777,10 @@
     # build, only do stack trace perftest for unofficial build
     sources += [ "debug/stack_trace_perftest.cc" ]
   }
+
+  if (build_allocation_stack_trace_recorder) {
+    sources += [ "debug/allocation_trace_perftest.cc" ]
+  }
 }
 
 test("base_i18n_perftests") {
diff --git a/base/debug/allocation_trace_perftest.cc b/base/debug/allocation_trace_perftest.cc
new file mode 100644
index 0000000..78e348f
--- /dev/null
+++ b/base/debug/allocation_trace_perftest.cc
@@ -0,0 +1,211 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <thread>
+#include <vector>
+
+#include "base/debug/allocation_trace.h"
+#include "base/strings/stringprintf.h"
+#include "base/timer/lap_timer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/perf/perf_result_reporter.h"
+
+namespace base {
+namespace debug {
+namespace {
+// Change kTimeLimit to something higher if you need more time to capture a
+// trace.
+constexpr base::TimeDelta kTimeLimit = base::Seconds(3);
+constexpr int kWarmupRuns = 100;
+constexpr int kTimeCheckInterval = 1000;
+constexpr char kMetricStackTraceDuration[] = ".duration_per_run";
+constexpr char kMetricStackTraceThroughput[] = ".throughput";
+
+enum class HandlerFunctionSelector { OnAllocation, OnFree };
+
+// An executor to perform the actual notification of the recorder. The correct
+// handler function is selected using template specialization based on the
+// HandlerFunctionSelector.
+template <HandlerFunctionSelector HandlerFunction>
+struct HandlerFunctionExecutor {
+  void operator()(base::debug::tracer::AllocationTraceRecorder& recorder) const;
+};
+
+template <>
+struct HandlerFunctionExecutor<HandlerFunctionSelector::OnAllocation> {
+  void operator()(
+      base::debug::tracer::AllocationTraceRecorder& recorder) const {
+    // Since the recorder just stores the value, we can use any value for
+    // address and size that we want.
+    recorder.OnAllocation(
+        &recorder, sizeof(recorder),
+        base::allocator::dispatcher::AllocationSubsystem::kPartitionAllocator,
+        nullptr);
+  }
+};
+
+template <>
+struct HandlerFunctionExecutor<HandlerFunctionSelector::OnFree> {
+  void operator()(
+      base::debug::tracer::AllocationTraceRecorder& recorder) const {
+    recorder.OnFree(&recorder);
+  }
+};
+}  // namespace
+
+class AllocationTraceRecorderPerfTest
+    : public testing::TestWithParam<
+          std::tuple<HandlerFunctionSelector, size_t>> {
+ protected:
+  // The result data of a single thread. From the results of all the single
+  // threads the final results will be calculated.
+  struct ResultData {
+    TimeDelta time_per_lap;
+    float laps_per_second = 0.0;
+    int number_of_laps = 0;
+  };
+
+  // The data of a single test thread.
+  struct ThreadRunnerData {
+    std::thread thread;
+    ResultData result_data;
+  };
+
+  // Create and setup the result reporter.
+  const char* GetHandlerDescriptor(HandlerFunctionSelector handler_function);
+  perf_test::PerfResultReporter SetUpReporter(
+      HandlerFunctionSelector handler_function,
+      size_t number_of_allocating_threads);
+
+  // Select the correct test function which shall be used for the current test.
+  using TestFunction =
+      void (*)(base::debug::tracer::AllocationTraceRecorder& recorder,
+               ResultData& result_data);
+
+  static TestFunction GetTestFunction(HandlerFunctionSelector handler_function);
+  template <HandlerFunctionSelector HandlerFunction>
+  static void TestFunctionImplementation(
+      base::debug::tracer::AllocationTraceRecorder& recorder,
+      ResultData& result_data);
+
+  // The test management function. Using the the above auxiliary functions it is
+  // responsible to setup the result reporter, select the correct test function,
+  // spawn the specified number of worker threads and post process the results.
+  void PerformTest(HandlerFunctionSelector handler_function,
+                   size_t number_of_allocating_threads);
+};
+
+const char* AllocationTraceRecorderPerfTest::GetHandlerDescriptor(
+    HandlerFunctionSelector handler_function) {
+  switch (handler_function) {
+    case HandlerFunctionSelector::OnAllocation:
+      return "OnAllocation";
+    case HandlerFunctionSelector::OnFree:
+      return "OnFree";
+  }
+}
+
+perf_test::PerfResultReporter AllocationTraceRecorderPerfTest::SetUpReporter(
+    HandlerFunctionSelector handler_function,
+    size_t number_of_allocating_threads) {
+  const std::string story_name = base::StringPrintf(
+      "(%s;%zu-threads)", GetHandlerDescriptor(handler_function),
+      number_of_allocating_threads);
+
+  perf_test::PerfResultReporter reporter("AllocationRecorderPerf", story_name);
+  reporter.RegisterImportantMetric(kMetricStackTraceDuration, "ns");
+  reporter.RegisterImportantMetric(kMetricStackTraceThroughput, "runs/s");
+  return reporter;
+}
+
+AllocationTraceRecorderPerfTest::TestFunction
+AllocationTraceRecorderPerfTest::GetTestFunction(
+    HandlerFunctionSelector handler_function) {
+  switch (handler_function) {
+    case HandlerFunctionSelector::OnAllocation:
+      return TestFunctionImplementation<HandlerFunctionSelector::OnAllocation>;
+    case HandlerFunctionSelector::OnFree:
+      return TestFunctionImplementation<HandlerFunctionSelector::OnFree>;
+  }
+}
+
+void AllocationTraceRecorderPerfTest::PerformTest(
+    HandlerFunctionSelector handler_function,
+    size_t number_of_allocating_threads) {
+  perf_test::PerfResultReporter reporter =
+      SetUpReporter(handler_function, number_of_allocating_threads);
+
+  TestFunction test_function = GetTestFunction(handler_function);
+
+  base::debug::tracer::AllocationTraceRecorder the_recorder;
+
+  std::vector<ThreadRunnerData> notifying_threads;
+  notifying_threads.reserve(number_of_allocating_threads);
+
+  // Setup the threads. After creation, each thread immediately starts running.
+  // We expect the creation of the threads to be so quick that the delay from
+  // first to last thread is negligible.
+  for (size_t i = 0; i < number_of_allocating_threads; ++i) {
+    auto& last_item = notifying_threads.emplace_back();
+
+    last_item.thread = std::thread{test_function, std::ref(the_recorder),
+                                   std::ref(last_item.result_data)};
+  }
+
+  TimeDelta average_time_per_lap;
+  float average_laps_per_second = 0;
+
+  // Wait for each thread to finish and collect its result data.
+  for (auto& item : notifying_threads) {
+    item.thread.join();
+    // When finishing, each threads writes its results into result_data. So,
+    // from here we gather its performance statistics.
+    average_time_per_lap += item.result_data.time_per_lap;
+    average_laps_per_second += item.result_data.laps_per_second;
+  }
+
+  average_time_per_lap /= number_of_allocating_threads;
+  average_laps_per_second /= number_of_allocating_threads;
+
+  reporter.AddResult(kMetricStackTraceDuration, average_time_per_lap);
+  reporter.AddResult(kMetricStackTraceThroughput, average_laps_per_second);
+}
+
+template <HandlerFunctionSelector HandlerFunction>
+void AllocationTraceRecorderPerfTest::TestFunctionImplementation(
+    base::debug::tracer::AllocationTraceRecorder& recorder,
+    ResultData& result_data) {
+  LapTimer timer(kWarmupRuns, kTimeLimit, kTimeCheckInterval,
+                 LapTimer::TimerMethod::kUseTimeTicks);
+
+  HandlerFunctionExecutor<HandlerFunction> handler_executor;
+
+  timer.Start();
+  do {
+    handler_executor(recorder);
+
+    timer.NextLap();
+  } while (!timer.HasTimeLimitExpired());
+
+  result_data.time_per_lap = timer.TimePerLap();
+  result_data.laps_per_second = timer.LapsPerSecond();
+  result_data.number_of_laps = timer.NumLaps();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    AllocationTraceRecorderPerfTest,
+    ::testing::Combine(::testing::Values(HandlerFunctionSelector::OnAllocation,
+                                         HandlerFunctionSelector::OnFree),
+                       ::testing::Values(1, 5, 10, 20, 40, 80)));
+
+TEST_P(AllocationTraceRecorderPerfTest, TestNotification) {
+  const auto parameters = GetParam();
+  const HandlerFunctionSelector handler_function = std::get<0>(parameters);
+  const size_t number_of_threads = std::get<1>(parameters);
+  PerformTest(handler_function, number_of_threads);
+}
+
+}  // namespace debug
+}  // namespace base
diff --git a/base/fuchsia/startup_context.cc b/base/fuchsia/startup_context.cc
index e93634c..78210c5 100644
--- a/base/fuchsia/startup_context.cc
+++ b/base/fuchsia/startup_context.cc
@@ -49,40 +49,6 @@
 
 StartupContext::~StartupContext() = default;
 
-StartupContext::StartupContext(fuchsia::sys::StartupInfo startup_info) {
-  std::unique_ptr<sys::ServiceDirectory> incoming_services;
-
-  // Component manager generates |flat_namespace|, so things are horribly broken
-  // if |flat_namespace| is malformed.
-  CHECK_EQ(startup_info.flat_namespace.directories.size(),
-           startup_info.flat_namespace.paths.size());
-
-  // Find the /svc directory and wrap it into a sys::ServiceDirectory.
-  for (size_t i = 0; i < startup_info.flat_namespace.paths.size(); ++i) {
-    if (startup_info.flat_namespace.paths[i] == kServiceDirectoryPath) {
-      incoming_services = std::make_unique<sys::ServiceDirectory>(
-          std::move(startup_info.flat_namespace.directories[i]));
-      break;
-    }
-  }
-
-  if (!incoming_services) {
-    LOG(WARNING) << "Component started without a service directory";
-
-    // Create a dummy ServiceDirectory with a channel that's not
-    // connected on the other end.
-    fidl::InterfaceHandle<fuchsia::io::Directory> dummy_directory;
-    std::ignore = dummy_directory.NewRequest();
-    incoming_services =
-        std::make_unique<sys::ServiceDirectory>(std::move(dummy_directory));
-  }
-
-  component_context_ =
-      std::make_unique<sys::ComponentContext>(std::move(incoming_services));
-  outgoing_directory_request_ =
-      std::move(startup_info.launch_info.directory_request);
-}
-
 void StartupContext::ServeOutgoingDirectory() {
   DCHECK(outgoing_directory_request_);
   component_context_->outgoing()->Serve(std::move(outgoing_directory_request_));
diff --git a/base/fuchsia/startup_context.h b/base/fuchsia/startup_context.h
index 44c7236..fbe3f25c 100644
--- a/base/fuchsia/startup_context.h
+++ b/base/fuchsia/startup_context.h
@@ -7,7 +7,6 @@
 
 #include <fuchsia/component/runner/cpp/fidl.h>
 #include <fuchsia/io/cpp/fidl.h>
-#include <fuchsia/sys/cpp/fidl.h>
 #include <lib/sys/cpp/component_context.h>
 #include <lib/zx/channel.h>
 
@@ -22,7 +21,7 @@
 
 namespace base {
 
-// Helper for unpacking a fuchsia.sys.StartupInfo and creating convenience
+// Helper for unpacking component start info and creating convenience
 // wrappers for the various fields (e.g. the incoming & outgoing service
 // directories, resolve launch URL etc).
 // Embedders may derived from StartupContext to e.g. add bound pointers to
@@ -33,10 +32,6 @@
       ::fuchsia::component::runner::ComponentStartInfo start_info);
   ~StartupContext();
 
-  // TODO(https://crbug.com/1065707): Remove this overload once the CFv1
-  // Runner implementations are removed.
-  explicit StartupContext(::fuchsia::sys::StartupInfo startup_info);
-
   StartupContext(const StartupContext&) = delete;
   StartupContext& operator=(const StartupContext&) = delete;
 
diff --git a/base/message_loop/message_pump_glib_unittest.cc b/base/message_loop/message_pump_glib_unittest.cc
index 7b5406eb..77b5ca4 100644
--- a/base/message_loop/message_pump_glib_unittest.cc
+++ b/base/message_loop/message_pump_glib_unittest.cc
@@ -562,15 +562,7 @@
 
 }  // namespace
 
-// TODO(crbug.com/1434860): Re-enable this test
-#if BUILDFLAG(IS_LINUX) && defined(MEMORY_SANITIZER)
-#define MAYBE_TestNativeNestedLoopWithoutDoWork \
-  DISABLED_TestNativeNestedLoopWithoutDoWork
-#else
-#define MAYBE_TestNativeNestedLoopWithoutDoWork \
-  TestNativeNestedLoopWithoutDoWork
-#endif
-TEST_F(MessagePumpGLibTest, MAYBE_TestNativeNestedLoopWithoutDoWork) {
+TEST_F(MessagePumpGLibTest, TestNativeNestedLoopWithoutDoWork) {
   // Tests that nesting is triggered correctly if a message loop is run
   // from a native event (gtk event) outside of a work item (not in a posted
   // task).
diff --git a/base/strings/escape.cc b/base/strings/escape.cc
index d76bb6e2..d303ead9 100644
--- a/base/strings/escape.cc
+++ b/base/strings/escape.cc
@@ -543,9 +543,20 @@
   DCHECK(!(rules &
            ~(UnescapeRule::NORMAL | UnescapeRule::REPLACE_PLUS_WITH_SPACE)));
 
+  // It is not possible to read the feature state when this function is invoked
+  // before FeatureList initialization. In that case, fallback to the feature's
+  // default state.
+  //
+  // TODO(crbug.com/1321924): Cleanup this feature.
+  const bool optimize_data_urls_feature_is_enabled =
+      base::FeatureList::GetInstance()
+          ? base::FeatureList::IsEnabled(features::kOptimizeDataUrls)
+          : features::kOptimizeDataUrls.default_state ==
+                base::FEATURE_ENABLED_BY_DEFAULT;
+
   // If there are no '%' characters in the string, there will be nothing to
   // unescape, so we can take the fast path.
-  if (base::FeatureList::IsEnabled(features::kOptimizeDataUrls) &&
+  if (optimize_data_urls_feature_is_enabled &&
       escaped_text.find('%') == StringPiece::npos) {
     std::string unescaped_text(escaped_text);
     if (rules & UnescapeRule::REPLACE_PLUS_WITH_SPACE)
diff --git a/base/task/sequence_manager/thread_controller.h b/base/task/sequence_manager/thread_controller.h
index 692056d..138bdcd 100644
--- a/base/task/sequence_manager/thread_controller.h
+++ b/base/task/sequence_manager/thread_controller.h
@@ -362,7 +362,7 @@
       absl::optional<perfetto::Track> perfetto_track_;
 
       // True if tracing was enabled during the last pass of RecordTimeInPhase.
-      bool was_tracing_enabled_;
+      bool was_tracing_enabled_ = false;
 #endif
       const raw_ref<const RunLevelTracker> outer_;
     } time_keeper_{*this};
diff --git a/build/config/compiler/pgo/BUILD.gn b/build/config/compiler/pgo/BUILD.gn
index f2c61c21..86e76a4 100644
--- a/build/config/compiler/pgo/BUILD.gn
+++ b/build/config/compiler/pgo/BUILD.gn
@@ -56,6 +56,8 @@
     } else if (is_chromeos_lacros) {
       if (target_cpu == "arm") {
         _pgo_target = "lacros-arm"
+      } else if (target_cpu == "arm64") {
+        _pgo_target = "lacros-arm64"
       } else {
         _pgo_target = "lacros64"
       }
diff --git a/build/fuchsia/test/common.py b/build/fuchsia/test/common.py
index 4377956..32785f15 100644
--- a/build/fuchsia/test/common.py
+++ b/build/fuchsia/test/common.py
@@ -551,7 +551,6 @@
         'Booting with FFX to %s did not succeed. Attempting with DM', mode)
 
     # Fallback to SSH, with no retry if we tried with ffx.:
-    _boot_device_dm(target_id, serial_num, state, mode)
     state = _reboot(
         (lambda: _boot_device_dm(target_id, serial_num, state, mode)), state)
 
diff --git a/build/rust/rust_bindgen.gni b/build/rust/rust_bindgen.gni
index 5f8f873..9d72169 100644
--- a/build/rust/rust_bindgen.gni
+++ b/build/rust/rust_bindgen.gni
@@ -176,5 +176,18 @@
         "/clang:-fallow-editor-placeholders",
       ]
     }
+
+    if (!is_cfi) {
+      # LLVM searches for a default CFI ignorelist at (exactly)
+      # $(cwd)/lib/clang/$(llvm_version)/share/cfi_ignorelist.txt
+      # Even if we provide a custom -fsanitize-ignorelist, the absence
+      # of this default file will cause a fatal error. clang finds
+      # it within third_party/llvm-build, but for bindgen our cwd
+      # is the $out_dir. We _could_ create this file at the right
+      # location within the outdir using a "copy" target, but as
+      # we don't actually generate code within bindgen, the easier
+      # option is to tell bindgen to ignore all CFI ignorelists.
+      args += [ "-fno-sanitize-ignorelist" ]
+    }
   }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemRow.java
index 7de208b..7125615 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemRow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemRow.java
@@ -38,16 +38,16 @@
     public static BookmarkItemRow buildView(Context context, boolean isVisualRefreshEnabled) {
         BookmarkItemRow row = new BookmarkItemRow(context, null);
         BookmarkRow.buildView(row, context, isVisualRefreshEnabled);
-        row.setupIconProperties(isVisualRefreshEnabled);
+
         return row;
     }
 
     /** Constructor for inflating from XML. */
     public BookmarkItemRow(Context context, AttributeSet attrs) {
         super(context, attrs);
-    }
 
-    void setupIconProperties(boolean isVisualRefreshEnabled) {
+        boolean isVisualRefreshEnabled = BookmarkFeatures.isLegacyBookmarksVisualRefreshEnabled();
+
         mMinIconSize = getResources().getDimensionPixelSize(R.dimen.default_favicon_min_size);
         mDisplayedIconSize = getResources().getDimensionPixelSize(isVisualRefreshEnabled
                         ? R.dimen.bookmark_refresh_preferred_start_icon_size
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java
index d256f45a..ad4b3bf3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java
@@ -70,7 +70,7 @@
     public static PowerBookmarkShoppingItemRow buildView(
             Context context, boolean isVisualRefreshEnabled) {
         PowerBookmarkShoppingItemRow row = new PowerBookmarkShoppingItemRow(context, null);
-        BookmarkRow.buildView(row, context, isVisualRefreshEnabled);
+        BookmarkItemRow.buildView(row, context, isVisualRefreshEnabled);
         return row;
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRowTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRowTest.java
index 55b66d3..e5d48130 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRowTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRowTest.java
@@ -6,13 +6,13 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
 
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import androidx.test.filters.SmallTest;
 
@@ -27,30 +27,50 @@
 import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.Callback;
-import org.chromium.base.FeatureList;
-import org.chromium.chrome.R;
+import org.chromium.base.test.util.JniMocker;
+import org.chromium.chrome.browser.bookmarks.BookmarkRow.Location;
+import org.chromium.chrome.browser.commerce.PriceTrackingUtils;
+import org.chromium.chrome.browser.commerce.PriceTrackingUtilsJni;
 import org.chromium.chrome.browser.commerce.ShoppingFeatures;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.components.browser_ui.styles.SemanticColorUtils;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
+import org.chromium.components.bookmarks.BookmarkId;
+import org.chromium.components.bookmarks.BookmarkItem;
+import org.chromium.components.bookmarks.BookmarkType;
+import org.chromium.components.browser_ui.widget.RoundedIconGenerator;
+import org.chromium.components.browser_ui.widget.dragreorder.DragStateDelegate;
+import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate;
+import org.chromium.components.favicon.IconType;
+import org.chromium.components.favicon.LargeIconBridge;
 import org.chromium.components.image_fetcher.ImageFetcher;
 import org.chromium.components.payments.CurrencyFormatter;
+import org.chromium.components.power_bookmarks.PowerBookmarkMeta;
+import org.chromium.components.power_bookmarks.ShoppingSpecifics;
+import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.test.util.BlankUiTestActivityTestCase;
+import org.chromium.url.JUnitTestGURLs;
 
 /**
  * Tests for the Shopping power bookmarks experience.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
+@EnableFeatures(ChromeFeatureList.BOOKMARKS_REFRESH)
 public class PowerBookmarkShoppingItemRowTest extends BlankUiTestActivityTestCase {
     private static final long CURRENCY_MUTLIPLIER = 1000000;
+    private static final String TITLE = "PowerBookmarkShoppingItemRow";
 
     @Rule
     public MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Rule
+    public JniMocker mJniMocker = new JniMocker();
 
     @Mock
+    private PriceTrackingUtils.Natives mMockPriceTrackingUtilsJni;
+    @Mock
     private ImageFetcher mImageFetcher;
     @Mock
     private CurrencyFormatter mCurrencyFormatter;
@@ -60,23 +80,32 @@
     private SnackbarManager mSnackbarManager;
     @Mock
     private Profile mProfile;
+    @Mock
+    private BookmarkItem mBookmarkItem;
+    @Mock
+    private BookmarkDelegate mDelegate;
+    @Mock
+    private SelectionDelegate<BookmarkId> mSelectionDelegate;
+    @Mock
+    private DragStateDelegate mDragStateDelegate;
+    @Mock
+    private LargeIconBridge mLargeIconBridge;
+    @Mock
+    private RoundedIconGenerator mRoundedIconGenerator;
 
+    private BookmarkId mBookmarkId;
     private Bitmap mBitmap;
     private PowerBookmarkShoppingItemRow mPowerBookmarkShoppingItemRow;
     private ViewGroup mContentView;
 
-    public void setupFeatureOverrides() {
-        FeatureList.TestValues testValuesOverride = new FeatureList.TestValues();
-        testValuesOverride.addFeatureFlagOverride(ChromeFeatureList.BOOKMARKS_REFRESH, true);
-        ShoppingFeatures.setShoppingListEligibleForTesting(true);
-        FeatureList.setTestValues(testValuesOverride);
-    }
-
     @Override
     public void setUpTest() throws Exception {
         super.setUpTest();
         MockitoAnnotations.initMocks(this);
-        setupFeatureOverrides();
+        ShoppingFeatures.setShoppingListEligibleForTesting(true);
+
+        NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
+        mJniMocker.mock(PriceTrackingUtilsJni.TEST_HOOKS, mMockPriceTrackingUtilsJni);
 
         mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
         mBitmap.eraseColor(Color.GREEN);
@@ -86,6 +115,23 @@
                 .when(mCurrencyFormatter)
                 .format(currencyCaptor.capture());
 
+        PowerBookmarkMeta meta =
+                PowerBookmarkMeta.newBuilder()
+                        .setShoppingSpecifics(
+                                ShoppingSpecifics.newBuilder().setProductClusterId(1234L).build())
+                        .build();
+
+        mBookmarkId = new BookmarkId(1, BookmarkType.NORMAL);
+        doReturn(mBookmarkModel).when(mDelegate).getModel();
+        doReturn(mSelectionDelegate).when(mDelegate).getSelectionDelegate();
+        doReturn(mDragStateDelegate).when(mDelegate).getDragStateDelegate();
+        doReturn(mLargeIconBridge).when(mDelegate).getLargeIconBridge();
+        doReturn(TITLE).when(mBookmarkItem).getTitle();
+        doReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL)).when(mBookmarkItem).getUrl();
+        doReturn(JUnitTestGURLs.EXAMPLE_URL).when(mBookmarkItem).getUrlForDisplay();
+        doReturn(mBookmarkItem).when(mBookmarkModel).getBookmarkById(mBookmarkId);
+        doReturn(meta).when(mBookmarkModel).getPowerBookmarkMeta(mBookmarkId);
+
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mContentView = new LinearLayout(getActivity());
             mContentView.setBackgroundColor(Color.WHITE);
@@ -96,12 +142,8 @@
             getActivity().setContentView(mContentView, params);
             mPowerBookmarkShoppingItemRow =
                     BookmarkManagerCoordinator.buildShoppingItemView(mContentView);
-            mPowerBookmarkShoppingItemRow.setBackgroundColor(
-                    SemanticColorUtils.getDefaultBgColor(getActivity()));
-            ((TextView) mPowerBookmarkShoppingItemRow.findViewById(R.id.title))
-                    .setText("Test Bookmark");
-            ((TextView) mPowerBookmarkShoppingItemRow.findViewById(R.id.description))
-                    .setText("http://google.com");
+            mPowerBookmarkShoppingItemRow.setRoundedIconGeneratorForTesting(mRoundedIconGenerator);
+            mPowerBookmarkShoppingItemRow.onDelegateInitialized(mDelegate);
             mPowerBookmarkShoppingItemRow.init(
                     mImageFetcher, mBookmarkModel, mSnackbarManager, mProfile);
             mPowerBookmarkShoppingItemRow.setCurrencyFormatterForTesting(mCurrencyFormatter);
@@ -130,4 +172,15 @@
 
         Assert.assertFalse(mPowerBookmarkShoppingItemRow.getFaviconCancelledForTesting());
     }
-}
\ No newline at end of file
+
+    @Test
+    @SmallTest
+    public void testIconPropsAreInitialized() {
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mPowerBookmarkShoppingItemRow.setBookmarkId(mBookmarkId, Location.TOP, false);
+            // This will crash if the icon properties aren't initialized.
+            mPowerBookmarkShoppingItemRow.onLargeIconAvailable(
+                    mBitmap, Color.GREEN, false, IconType.FAVICON);
+        });
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
index 9f8ba3c..2cf8652f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
@@ -186,11 +186,12 @@
             new String[] {"clear_browsing_data_link", "clear_browsing_divider"};
     private static final String[] ANTI_ABUSE_PREF_KEYS = {"anti_abuse_when_on_header",
             "anti_abuse_when_on_section_one", "anti_abuse_when_on_section_two",
-            "anti_abuse_things_to_consider_header", "anti_abuse_things_to_consider_section_one"};
+            "anti_abuse_when_on_section_three", "anti_abuse_things_to_consider_header",
+            "anti_abuse_things_to_consider_section_one"};
     private static final String[] BINARY_TOGGLE_WITH_ANTI_ABUSE_PREF_KEYS = {"binary_toggle",
             "anti_abuse_when_on_header", "anti_abuse_when_on_section_one",
-            "anti_abuse_when_on_section_two", "anti_abuse_things_to_consider_header",
-            "anti_abuse_things_to_consider_section_one"};
+            "anti_abuse_when_on_section_two", "anti_abuse_when_on_section_three",
+            "anti_abuse_things_to_consider_header", "anti_abuse_things_to_consider_section_one"};
 
     @Before
     public void setUp() throws TimeoutException {
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 451de9d..58b24716 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -6161,15 +6161,6 @@
   <message name="IDS_ADD_SUPERVISION_PAGE_TITLE" desc="Title for the ChromeOS Add Supervision screen. Since the title bar is not visible, this string is only used by screen readers.">
     Set Up Parental Controls
   </message>
-  <message name="IDS_ADD_SUPERVISION_NETWORK_DOWN_HEADING" desc="Heading string shown in the Add Supervision page when the network is not available.">
-    Can’t connect to the internet
-  </message>
-  <message name="IDS_ADD_SUPERVISION_NETWORK_DOWN_DESCRIPTION" desc="Description shown in the Add Supervision page when the network is not available.">
-    Check your internet connection
-  </message>
-  <message name="IDS_ADD_SUPERVISION_NETWORK_DOWN_BUTTON_LABEL" desc="Label of the button shown on the Add Supervision page when the network is not available.">
-    Close
-  </message>
   <message name="IDS_ADD_SUPERVISION_EXIT_DIALOG_TITLE" desc="Title for the dialog shown when attempting to exit the Add Supervision screen.">
     Are you sure you want to exit?
   </message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index a71e739f..00f14bcc 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -14222,6 +14222,9 @@
     <message name="IDS_TAILORED_SECURITY_UNCONSENTED_MODAL_TITLE" desc="Title shown in the tab modal dialog when the account tailored security setting changes for an unconsented primary account">
       Also turn on Enhanced Safe Browsing for this Chrome profile?
     </message>
+    <message name="IDS_TAILORED_SECURITY_UNCONSENTED_MODAL_BODY" desc="Body shown in the tab modal dialog when the account tailored security setting changes for an unconsented primary account">
+      Chrome&#x2019;s strongest security does more to protect you against dangerous websites, downloads, and extensions
+    </message>
     <message name="IDS_TAILORED_SECURITY_UNCONSENTED_ACCEPT_BUTTON" desc="The text on the accept button in the tab modal dialog when the account tailored security setting changes for an unconsented primary account">
       Turn on
     </message>
@@ -14471,6 +14474,9 @@
     <message name="IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_NOTIFICATION_DESCRIPTION" desc="Description of notification prompting the user to enable Enhanced Safe Browsing after they have enabled account-level protections.">
       Enhanced protection does more to block phishing and malware
     </message>
+    <message name="IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_NOTIFICATION_DESCRIPTION_UPDATED" desc="Description of notification prompting the user to enable Enhanced Safe Browsing after they have enabled account-level protections.">
+      Enhanced Safe Browsing does more to protect you against dangerous websites, downloads, and extensions
+    </message>
     <if expr="use_titlecase">
       <message name="IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_NOTIFICATION_ACCEPT" desc="Accept button on notification prompting the user to enable Enhanced Safe Browsing after they have enabled account-level protections.">
         Continue
diff --git a/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_UNCONSENTED_MODAL_BODY.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_UNCONSENTED_MODAL_BODY.png.sha1
new file mode 100644
index 0000000..9493f61d
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_UNCONSENTED_MODAL_BODY.png.sha1
@@ -0,0 +1 @@
+9e2c082fe217c890378857d2a5fe8cbd4b440b00
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_NOTIFICATION_DESCRIPTION_UPDATED.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_NOTIFICATION_DESCRIPTION_UPDATED.png.sha1
new file mode 100644
index 0000000..9c4913e
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_NOTIFICATION_DESCRIPTION_UPDATED.png.sha1
@@ -0,0 +1 @@
+59de64f300936bc601818dc749ef9860d89a7a41
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 5250bf6a..f8bacfc 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -1812,17 +1812,20 @@
   <message name="IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_HEADER" desc="The header used for the section that informs users of the anti-abuse features.">
     When on
   </message>
-  <message name="IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_ONE" desc="A description that informs users how their browsing could be helped by the anti-abuse features.">
-    Browsing is faster because a site is less likely to ask you to verify you're a real person
+  <message name="IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_ONE" desc="A description that informs users that Chrome saves a small amount of data when the anti-abuse features are enabled.">
+    A site you visit can save a small amount of info with Chrome, mainly to validate you're not a bot
   </message>
-  <message name="IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_TWO" desc="A description that informs users that the anti-abuse features do not reveal their browsing history.">
-    This setting works without identifying you or allowing sites to see your browsing history
+  <message name="IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_TWO" desc="A description that informs users how the anti-abuse features work.">
+    As you keep browsing, sites can check with Chrome and verify with a previous site you've visited that you're likely a real person
+  </message>
+  <message name="IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_THREE" desc="A description that informs users how their browsing could be helped by the anti-abuse features.">
+    Browsing is faster because a site is less likely to ask you to verify you're a real person
   </message>
   <message name="IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER" desc="The header used for the section that informs users of additional things to consider when the anti-abuse features are enabled.">
     Things to consider
   </message>
-  <message name="IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE" desc="A description that informs users that site can save info with Chrome when the anti-abuse features are enabled.">
-    A site you visit can save info with Chrome that validates you're not a bot. As you keep browsing, sites can check with Chrome and verify with a previous site you've visited that you're likely a real person
+  <message name="IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE" desc="A description that informs users that the anti-abuse features do not reveal their browsing history.">
+    This setting works without identifying you or allowing sites to see your browsing history, though sites can share a small amount of info as part of the verification
   </message>
 
   <!-- Privacy Sandbox -->
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_DESCRIPTION.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_DESCRIPTION.png.sha1
index 9c7a6a0..f13a36d 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_DESCRIPTION.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_DESCRIPTION.png.sha1
@@ -1 +1 @@
-dac27d6ba179b620a3bfacdfd9eb9f6233a9d5d5
\ No newline at end of file
+3f5f358af7470d93884e82eea2e321252cdf9ce7
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER.png.sha1
index 9c7a6a0..f13a36d 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER.png.sha1
@@ -1 +1 @@
-dac27d6ba179b620a3bfacdfd9eb9f6233a9d5d5
\ No newline at end of file
+3f5f358af7470d93884e82eea2e321252cdf9ce7
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE.png.sha1
index 9c7a6a0..f13a36d 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE.png.sha1
@@ -1 +1 @@
-dac27d6ba179b620a3bfacdfd9eb9f6233a9d5d5
\ No newline at end of file
+3f5f358af7470d93884e82eea2e321252cdf9ce7
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_HEADER.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_HEADER.png.sha1
index 9c7a6a0..f13a36d 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_HEADER.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_HEADER.png.sha1
@@ -1 +1 @@
-dac27d6ba179b620a3bfacdfd9eb9f6233a9d5d5
\ No newline at end of file
+3f5f358af7470d93884e82eea2e321252cdf9ce7
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_ONE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_ONE.png.sha1
index 9c7a6a0..f13a36d 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_ONE.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_ONE.png.sha1
@@ -1 +1 @@
-dac27d6ba179b620a3bfacdfd9eb9f6233a9d5d5
\ No newline at end of file
+3f5f358af7470d93884e82eea2e321252cdf9ce7
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_THREE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_THREE.png.sha1
new file mode 100644
index 0000000..f13a36d
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_THREE.png.sha1
@@ -0,0 +1 @@
+3f5f358af7470d93884e82eea2e321252cdf9ce7
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_TWO.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_TWO.png.sha1
index 9c7a6a0..f13a36d 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_TWO.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_TWO.png.sha1
@@ -1 +1 @@
-dac27d6ba179b620a3bfacdfd9eb9f6233a9d5d5
\ No newline at end of file
+3f5f358af7470d93884e82eea2e321252cdf9ce7
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 6dc08a2f..6137981 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -263,6 +263,8 @@
     "browsing_topics/browsing_topics_service_factory.h",
     "cart/commerce_hint_service.cc",
     "cart/commerce_hint_service.h",
+    "chained_back_navigation_tracker.cc",
+    "chained_back_navigation_tracker.h",
     "child_process_host_flags.h",
     "chooser_controller/title_util.cc",
     "chooser_controller/title_util.h",
@@ -7457,6 +7459,8 @@
       "supervised_user/supervised_user_google_auth_navigation_throttle.h",
       "supervised_user/supervised_user_interstitial.cc",
       "supervised_user/supervised_user_interstitial.h",
+      "supervised_user/supervised_user_interstitial_tab_closer.cc",
+      "supervised_user/supervised_user_interstitial_tab_closer.h",
       "supervised_user/supervised_user_metrics_service_factory.cc",
       "supervised_user/supervised_user_metrics_service_factory.h",
       "supervised_user/supervised_user_navigation_observer.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 7330ba9..c58f508 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -9623,6 +9623,14 @@
          performance_manager::features::kHeuristicMemorySaver,
          kHeuristicMemorySaverVariations,
          "HeuristicMemorySaver")},
+
+    {"memory-saver-savings-reporting-improvements",
+     flag_descriptions::kHighEfficiencySavingsReportingImprovementsName,
+     flag_descriptions::kHighEfficiencySavingsReportingImprovementsDescription,
+     kOsDesktop,
+     FEATURE_VALUE_TYPE(
+         performance_manager::features::kMemorySavingsReportingImprovements)},
+
 #endif
 
 #if BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/ash/bruschetta/bruschetta_installer.h b/chrome/browser/ash/bruschetta/bruschetta_installer.h
index f74a68e4..d02429a2 100644
--- a/chrome/browser/ash/bruschetta/bruschetta_installer.h
+++ b/chrome/browser/ash/bruschetta/bruschetta_installer.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_INSTALLER_H_
 #define CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_INSTALLER_H_
 
-#include "base/guid.h"
+#include "base/uuid.h"
 #include "chromeos/ash/components/dbus/vm_concierge/concierge_service.pb.h"
 #include "components/download/public/background_service/download_metadata.h"
 
@@ -59,7 +59,7 @@
   virtual void Cancel() = 0;
   virtual void Install(std::string vm_name, std::string config_id) = 0;
 
-  virtual const base::GUID& GetDownloadGuid() const = 0;
+  virtual const base::Uuid& GetDownloadGuid() const = 0;
 
   virtual void DownloadStarted(
       const std::string& guid,
diff --git a/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc
index a77a13a..1ee1669 100644
--- a/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc
+++ b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc
@@ -223,7 +223,7 @@
 }
 
 void BruschettaInstallerImpl::DownloadFailed() {
-  download_guid_ = base::GUID();
+  download_guid_ = base::Uuid();
   download_callback_.Reset();
 
   if (MaybeClose()) {
@@ -236,7 +236,7 @@
 
 void BruschettaInstallerImpl::DownloadSucceeded(
     const download::CompletionInfo& completion_info) {
-  download_guid_ = base::GUID();
+  download_guid_ = base::Uuid();
   std::move(download_callback_).Run(completion_info);
 }
 
@@ -244,7 +244,7 @@
   VLOG(2) << "Downloading firmware";
   // We need to generate the download GUID before notifying because the tests
   // need it to set the response.
-  download_guid_ = base::GUID::GenerateRandomV4();
+  download_guid_ = base::Uuid::GenerateRandomV4();
   NotifyObserver(State::kFirmwareDownload);
 
   const std::string* url =
@@ -279,9 +279,9 @@
 
 void BruschettaInstallerImpl::DownloadBootDisk() {
   VLOG(2) << "Downloading boot disk";
-  // We need to generate the download GUID before notifying because the tests
+  // We need to generate the download UUID before notifying because the tests
   // need it to set the response.
-  download_guid_ = base::GUID::GenerateRandomV4();
+  download_guid_ = base::Uuid::GenerateRandomV4();
   NotifyObserver(State::kBootDiskDownload);
 
   const std::string* url = config_.FindDict(prefs::kPolicyImageKey)
@@ -316,9 +316,9 @@
 
 void BruschettaInstallerImpl::DownloadPflash() {
   VLOG(2) << "Downloading pflash";
-  // We need to generate the download GUID before notifying because the tests
+  // We need to generate the download UUID before notifying because the tests
   // need it to set the response.
-  download_guid_ = base::GUID::GenerateRandomV4();
+  download_guid_ = base::Uuid::GenerateRandomV4();
   NotifyObserver(State::kPflashDownload);
 
   const base::Value::Dict* pflash = config_.FindDict(prefs::kPolicyPflashKey);
@@ -647,7 +647,7 @@
   }
 }
 
-const base::GUID& BruschettaInstallerImpl::GetDownloadGuid() const {
+const base::Uuid& BruschettaInstallerImpl::GetDownloadGuid() const {
   return download_guid_;
 }
 
diff --git a/chrome/browser/ash/bruschetta/bruschetta_installer_impl.h b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.h
index dd6ca17..db80f94 100644
--- a/chrome/browser/ash/bruschetta/bruschetta_installer_impl.h
+++ b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.h
@@ -7,8 +7,8 @@
 
 #include <memory>
 
-#include "base/guid.h"
 #include "base/memory/raw_ptr.h"
+#include "base/uuid.h"
 #include "base/values.h"
 #include "chrome/browser/ash/bruschetta/bruschetta_installer.h"
 #include "chrome/browser/ash/bruschetta/bruschetta_util.h"
@@ -36,7 +36,7 @@
   void Cancel() override;
   void Install(std::string vm_name, std::string config_id) override;
 
-  const base::GUID& GetDownloadGuid() const override;
+  const base::Uuid& GetDownloadGuid() const override;
 
   void DownloadStarted(const std::string& guid,
                        download::DownloadParams::StartResult result) override;
@@ -86,7 +86,7 @@
   std::string config_id_;
   base::Value::Dict config_;
 
-  base::GUID download_guid_;
+  base::Uuid download_guid_;
   DownloadCallback download_callback_;
 
   base::FilePath firmware_path_;
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 02571c9..10c5c99 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -2602,9 +2602,11 @@
       CHECK(web_contents) << "Couldn't find the SWA WebContents without appId"
                           << " command data: " << *data;
     }
-    CHECK(ExecuteScriptAndExtractString(
-        web_contents,
-        base::StrCat({"test.swaTestMessageListener(", *data, ")"}), output));
+    *output = content::EvalJs(
+                  web_contents,
+                  base::StrCat({"test.swaTestMessageListener(", *data, ")"}),
+                  content::EXECUTE_SCRIPT_USE_MANUAL_REPLY)
+                  .ExtractString();
     return;
   }
 
@@ -2649,7 +2651,10 @@
                 ash::file_manager::kChromeUIFileManagerUntrustedURL) {
               const std::string* script = value.FindString("data");
               EXPECT_TRUE(script);
-              CHECK(ExecuteScriptAndExtractString(frame, *script, output));
+              *output =
+                  content::EvalJs(frame, *script,
+                                  content::EXECUTE_SCRIPT_USE_MANUAL_REPLY)
+                      .ExtractString();
               found = true;
               return content::RenderFrameHost::FrameIterationAction::kStop;
             }
@@ -3549,20 +3554,17 @@
     content::WebContents* web_contents) {
   CHECK(web_contents);
 
-  bool result;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-      web_contents, "test.swaLoadTestUtils()", &result));
-  ASSERT_TRUE(result);
+  ASSERT_EQ(true, content::EvalJs(web_contents, "test.swaLoadTestUtils()",
+                                  content::EXECUTE_SCRIPT_USE_MANUAL_REPLY));
 }
 
 std::string FileManagerBrowserTestBase::GetSwaAppId(
     content::WebContents* web_contents) {
   CHECK(web_contents);
 
-  std::string app_id;
-  CHECK(content::ExecuteScriptAndExtractString(web_contents,
-                                               "test.getSwaAppId()", &app_id));
-  return app_id;
+  return content::EvalJs(web_contents, "test.getSwaAppId()",
+                         content::EXECUTE_SCRIPT_USE_MANUAL_REPLY)
+      .ExtractString();
 }
 
 std::vector<content::WebContents*>
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_accelerator_browsertest.cc b/chrome/browser/ash/login/app_mode/test/kiosk_accelerator_browsertest.cc
index 59db22f7..93b3eb2c 100644
--- a/chrome/browser/ash/login/app_mode/test/kiosk_accelerator_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/kiosk_accelerator_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "ash/accelerators/accelerator_controller_impl.h"
 #include "ash/shell.h"
+#include "base/functional/bind.h"
 #include "base/run_loop.h"
 #include "chrome/browser/app_mode/test/accelerator_helpers.h"
 #include "chrome/browser/ash/app_mode/app_session_ash.h"
@@ -12,14 +13,36 @@
 #include "chrome/browser/ash/login/app_mode/test/ash_accelerator_helpers.h"
 #include "chrome/browser/ash/login/app_mode/test/test_browser_closed_waiter.h"
 #include "chrome/browser/ash/login/app_mode/test/web_kiosk_base_test.h"
+#include "chrome/browser/ash/login/test/test_predicate_waiter.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
 
-// Verify accelerators do not work in Kiosk sessions in Ash.
+namespace {
+
+int WindowWidth(content::WebContents* web_contents) {
+  return content::EvalJs(web_contents, "window.innerWidth").ExtractInt();
+}
+
+int WindowWidthAfterChange(content::WebContents* web_contents,
+                           int initial_width) {
+  test::TestPredicateWaiter(
+      base::BindRepeating(
+          [](content::WebContents* web_contents, int initial_width) {
+            return initial_width != WindowWidth(web_contents);
+          },
+          web_contents, initial_width))
+      .Wait();
+  return WindowWidth(web_contents);
+}
+
+}  // anonymous namespace
+
+// Verifies accelerator behavior in Kiosk sessions in Ash.
 class WebKioskAcceleratorTest : public WebKioskBaseTest {};
 
 IN_PROC_BROWSER_TEST_F(WebKioskAcceleratorTest, AcceleratorsDontCloseSession) {
@@ -35,7 +58,38 @@
   ASSERT_FALSE(WebKioskAppManager::Get()->app_session()->is_shutting_down());
 }
 
-// Verify accelerators work in regular non-kiosk sessions in Ash.
+IN_PROC_BROWSER_TEST_F(WebKioskAcceleratorTest, ZoomAccelerators) {
+  InitializeRegularOnlineKiosk();
+  SelectFirstBrowser();
+
+  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
+  ASSERT_NE(browser_view, nullptr);
+  content::WebContents* web_contents = browser_view->GetActiveWebContents();
+  ASSERT_NE(web_contents, nullptr);
+
+  int initial_width = WindowWidthAfterChange(web_contents, 0);
+  ASSERT_GT(initial_width, 0);
+
+  // Zoom in, content becomes larger and window width becomes smaller.
+  browser_view->AcceleratorPressed(
+      ui::Accelerator(ui::VKEY_ADD, ui::EF_CONTROL_DOWN));
+  int zoomed_in_width = WindowWidthAfterChange(web_contents, initial_width);
+  ASSERT_LT(zoomed_in_width, initial_width);
+
+  // Restore zoom, window width becomes |initial_width|.
+  browser_view->AcceleratorPressed(
+      ui::Accelerator(ui::VKEY_0, ui::EF_CONTROL_DOWN));
+  int restored_width = WindowWidthAfterChange(web_contents, zoomed_in_width);
+  ASSERT_EQ(restored_width, initial_width);
+
+  // Zoom out, content becomes smaller and window width becomes larger.
+  browser_view->AcceleratorPressed(
+      ui::Accelerator(ui::VKEY_SUBTRACT, ui::EF_CONTROL_DOWN));
+  int zoomed_out_width = WindowWidthAfterChange(web_contents, zoomed_in_width);
+  ASSERT_GT(zoomed_out_width, initial_width);
+}
+
+// Verifies accelerators work in regular non-kiosk sessions in Ash.
 class NonKioskAcceleratorTest : public InProcessBrowserTest {};
 
 IN_PROC_BROWSER_TEST_F(NonKioskAcceleratorTest, CloseTabAccelerator) {
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc b/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc
index f51fe00b..d07b004c 100644
--- a/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc
@@ -266,72 +266,6 @@
   EXPECT_FALSE(ShelfTestApi().IsVisible());
 }
 
-IN_PROC_BROWSER_TEST_F(KioskDeviceOwnedTest, ZoomSupport) {
-  ExtensionTestMessageListener app_window_loaded_listener("appWindowLoaded");
-  StartAppLaunchFromLoginScreen(
-      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE);
-  EXPECT_TRUE(app_window_loaded_listener.WaitUntilSatisfied());
-
-  Profile* app_profile = ProfileManager::GetPrimaryUserProfile();
-  ASSERT_TRUE(app_profile);
-
-  extensions::AppWindowRegistry* app_window_registry =
-      extensions::AppWindowRegistry::Get(app_profile);
-  extensions::AppWindow* window =
-      apps::AppWindowWaiter(app_window_registry, test_app_id()).Wait();
-  ASSERT_TRUE(window);
-
-  test::JSChecker window_js(window->web_contents());
-  int original_width = window_js.GetInt("window.innerWidth");
-
-  content::DOMMessageQueue message_queue(window->web_contents());
-
-  // Inject window size observer that should notify this test when the app
-  // window size changes during zoom operations.
-  window_js.Evaluate(
-      base::StringPrintf("window.addEventListener('resize', function() {"
-                         "  window.domAutomationController.send({"
-                         "      'name': '%s',"
-                         "      'data': window.innerWidth"
-                         "  });"
-                         "});",
-                         kSizeChangedMessage));
-
-  native_app_window::NativeAppWindowViews* native_app_window_views =
-      static_cast<native_app_window::NativeAppWindowViews*>(
-          window->GetBaseWindow());
-  ui::AcceleratorTarget* accelerator_target =
-      static_cast<ui::AcceleratorTarget*>(native_app_window_views);
-
-  // Zoom in. Text is bigger and content window width becomes smaller.
-  accelerator_target->AcceleratorPressed(
-      ui::Accelerator(ui::VKEY_ADD, ui::EF_CONTROL_DOWN));
-
-  const int width_zoomed_in =
-      WaitForWidthChange(&message_queue, original_width);
-  ASSERT_LT(width_zoomed_in, original_width);
-
-  // Go back to normal. Window width is restored.
-  accelerator_target->AcceleratorPressed(
-      ui::Accelerator(ui::VKEY_0, ui::EF_CONTROL_DOWN));
-
-  const int width_zoom_normal =
-      WaitForWidthChange(&message_queue, width_zoomed_in);
-  ASSERT_EQ(width_zoom_normal, original_width);
-
-  // Zoom out. Text is smaller and content window width becomes larger.
-  accelerator_target->AcceleratorPressed(
-      ui::Accelerator(ui::VKEY_SUBTRACT, ui::EF_CONTROL_DOWN));
-
-  const int width_zoomed_out =
-      WaitForWidthChange(&message_queue, width_zoom_normal);
-  ASSERT_GT(width_zoomed_out, original_width);
-
-  // Terminate the app.
-  window->GetBaseWindow()->Close();
-  base::RunLoop().RunUntilIdle();
-}
-
 IN_PROC_BROWSER_TEST_F(KioskDeviceOwnedTest, NotSignedInWithGAIAAccount) {
   // Tests that the kiosk session is not considered to be logged in with a GAIA
   // account.
diff --git a/chrome/browser/ash/login/login_after_update_to_flex_browsertest.cc b/chrome/browser/ash/login/login_after_update_to_flex_browsertest.cc
index 6ef745a..8467e93e 100644
--- a/chrome/browser/ash/login/login_after_update_to_flex_browsertest.cc
+++ b/chrome/browser/ash/login/login_after_update_to_flex_browsertest.cc
@@ -109,7 +109,7 @@
   test::WaitForPrimaryUserSessionStart();
 }
 
-IN_PROC_BROWSER_TEST_F(LoginAfterUpdateToFlexTest, RegularUser) {
+IN_PROC_BROWSER_TEST_F(LoginAfterUpdateToFlexTest, DISABLED_RegularUser) {
   LoginUser(GetRegularAccountId());
   EXPECT_FALSE(ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean(
       prefs::kRevenOobeConsolidatedConsentAccepted));
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.cc b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.cc
index b5db71f6..4ea907b 100644
--- a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.cc
+++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.cc
@@ -74,6 +74,10 @@
   }
 }
 
+Connection::State Connection::GetState() {
+  return connection_state_;
+}
+
 void Connection::RequestWifiCredentials(
     int32_t session_id,
     RequestWifiCredentialsCallback callback) {
@@ -227,6 +231,7 @@
 
 void Connection::OnConnectionClosed() {
   // TODO (b/278898402): Handle other connection closed reasons.
+  connection_state_ = Connection::State::kClosed;
   std::move(on_connection_closed_)
       .Run(TargetDeviceConnectionBroker::ConnectionClosedReason::kComplete);
 }
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.h b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.h
index 6b50a0e..4bb27a02 100644
--- a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.h
+++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection.h
@@ -39,6 +39,14 @@
 
   using ConnectionClosedCallback = base::OnceCallback<void(
       TargetDeviceConnectionBroker::ConnectionClosedReason)>;
+
+  enum class State {
+    kOpen,     // The NearbyConnection is Open
+    kClosing,  // A close has been requested, but the connection is not yet
+               // closed
+    kClosed    // The connection is closed
+  };
+
   class Factory {
    public:
     Factory() = default;
@@ -77,6 +85,9 @@
   Connection& operator=(const Connection&) = delete;
   ~Connection() override;
 
+  // Get the state of the connection (open, closing, or closed)
+  State GetState();
+
   // Changes the connection state to authenticated and invokes the
   // ConnectionAuthenticatedCallback. The caller must ensure that the connection
   // is authenticated before calling this function.
@@ -141,6 +152,7 @@
   RandomSessionId random_session_id_;
   SharedSecret shared_secret_;
   SharedSecret secondary_shared_secret_;
+  State connection_state_ = State::kOpen;
   std::unique_ptr<NonceGenerator> nonce_generator_;
   ConnectionClosedCallback on_connection_closed_;
   bool authenticated_ = false;
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc
index 0681aa5..9ca307c 100644
--- a/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc
+++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/connection_unittest.cc
@@ -406,12 +406,14 @@
           /*on_connection_authenticated=*/base::DoNothing());
 
   ASSERT_FALSE(future.IsReady());
+  ASSERT_EQ(connection_under_test->GetState(), Connection::State::kOpen);
 
   fake_nearby_connection_->Close();
 
   ASSERT_TRUE(future.IsReady());
   ASSERT_EQ(future.Get(),
             TargetDeviceConnectionBroker::ConnectionClosedReason::kComplete);
+  ASSERT_EQ(connection_under_test->GetState(), Connection::State::kClosed);
 }
 
 TEST_F(ConnectionTest, InitiateHandshake) {
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_browsertest.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller_browsertest.cc
index 7d1a3642..f04455b 100644
--- a/chrome/browser/ash/policy/dlp/dlp_files_controller_browsertest.cc
+++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_browsertest.cc
@@ -30,6 +30,7 @@
 namespace {
 
 constexpr char kExampleUrl[] = "https://example.com";
+constexpr char kExampleUrl1[] = "https://example1.com";
 
 // A listener that compares the list of files chosen with files expected.
 class TestFileSelectListener : public content::FileSelectListener {
@@ -179,7 +180,8 @@
 
 // (b/273269211): This is a test for the crash that happens upon showing a
 // warning dialog when a file is moved to Google Drive.
-IN_PROC_BROWSER_TEST_F(DlpFilesControllerBrowserTest, WarningDialog) {
+IN_PROC_BROWSER_TEST_F(DlpFilesControllerBrowserTest,
+                       WarningDialog_ComponentDestination) {
   EXPECT_CALL(*mock_rules_manager_, GetReportingManager);
   EXPECT_CALL(*mock_rules_manager_,
               IsRestrictedComponent(
@@ -197,4 +199,25 @@
   EXPECT_NE(files_controller_->GetWarnDialogForTesting(), nullptr);
 }
 
+// (b/277594200): This is a test for the crash that happens upon showing a
+// warning dialog when a file is dragged to a webpage.
+IN_PROC_BROWSER_TEST_F(DlpFilesControllerBrowserTest,
+                       WarningDialog_UrlDestination) {
+  EXPECT_CALL(*mock_rules_manager_, GetReportingManager);
+  EXPECT_CALL(*mock_rules_manager_,
+              IsRestrictedDestination(GURL(kExampleUrl), GURL(kExampleUrl1),
+                                      DlpRulesManager::Restriction::kFiles,
+                                      testing::_, testing::_, testing::_))
+      .WillOnce(testing::Return(DlpRulesManager::Level::kWarn));
+
+  std::vector<DlpFilesController::FileDaemonInfo> transferred_files;
+  transferred_files.emplace_back(1234, base::FilePath("file1.txt"),
+                                 kExampleUrl);
+  EXPECT_EQ(files_controller_->GetWarnDialogForTesting(), nullptr);
+  files_controller_->IsFilesTransferRestricted(
+      transferred_files, DlpFileDestination(kExampleUrl1),
+      DlpFilesController::FileAction::kMove, base::DoNothing());
+  EXPECT_NE(files_controller_->GetWarnDialogForTesting(), nullptr);
+}
+
 }  // namespace policy
diff --git a/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc b/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc
index e67383f..3b0b868 100644
--- a/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc
+++ b/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc
@@ -61,6 +61,7 @@
 #include "components/user_manager/user.h"
 #include "content/public/browser/media_session_service.h"
 #include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/entry_info.h"
@@ -414,14 +415,11 @@
 
 // Runs the provided `script` in a non-isolated JS world that can access
 // variables defined in global scope (otherwise only DOM queries are allowed).
-// The script must call `domAutomationController.send(result)` to return, where
-// `result` is a string.
+// The script's completion value must be a string.
 std::string ExtractStringInGlobalScope(content::WebContents* web_ui,
                                        const std::string& script) {
-  std::string result;
   content::RenderFrameHost* app = MediaAppUiBrowserTest::GetAppFrame(web_ui);
-  EXPECT_TRUE(content::ExecuteScriptAndExtractString(app, script, &result));
-  return result;
+  return content::EvalJs(app, script).ExtractString();
 }
 
 // Waits for the "filetraversalenabled" attribute to show up in the MediaApp's
@@ -1478,8 +1476,8 @@
 
   constexpr char kScript[] =
       "lastLoadedReceivedFileList().item(0).deleteOriginalFile()"
-      ".then(() => domAutomationController.send('bad-success'))"
-      ".catch(e => domAutomationController.send(e.name));";
+      ".then(() => 'bad-success')"
+      ".catch(e => e.name);";
   EXPECT_EQ("InvalidModificationError",
             ExtractStringInGlobalScope(web_ui, kScript));
 
@@ -1586,7 +1584,7 @@
   constexpr char kToggleFullscreen[] = R"(
       (async function toggleFullscreen() {
         await customLaunchData.delegate.toggleBrowserFullscreenMode();
-        domAutomationController.send("success");
+        return "success";
       })();
   )";
 
@@ -1614,7 +1612,7 @@
   constexpr char kMaybeTriggerPdfHats[] = R"(
       (async function triggerPdfHats() {
         await customLaunchData.delegate.maybeTriggerPdfHats();
-        domAutomationController.send("success");
+        return "success";
       })();
   )";
 
@@ -1723,13 +1721,12 @@
           const blob = await response.blob();
 
           if (response.status === 200 && blob.size > 0) {
-            domAutomationController.send('success');
+            return 'success';
           } else {
-            domAutomationController.send(
-                `Failed: status:$${response.status} size:$${blob.size}`);
+            return `Failed: status:$${response.status} size:$${blob.size}`;
           }
         } catch (e) {
-          domAutomationController.send(`Failed: $${e}`);
+          return `Failed: $${e}`;
         }
       })();
   )";
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 12e05da..ffc4a917 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -204,7 +204,7 @@
         <include name="IDR_SYS_INTERNALS_IMAGE_MEMORY_SVG" file="resources\chromeos\sys_internals\img\memory.svg" type="BINDATA" />
         <include name="IDR_SYS_INTERNALS_IMAGE_ZRAM_SVG" file="resources\chromeos\sys_internals\img\zram.svg" type="BINDATA" />
         <include name="IDR_ADD_SUPERVISION_HTML" file="resources\chromeos\add_supervision\add_supervision.html" type="chrome_html" />
-        <include name="IDR_ADD_SUPERVISION_NETWORK_UNAVAILABLE_SVG" file="resources\chromeos\add_supervision\images\network_unavailable.svg" type="BINDATA" />
+        <include name="IDR_ADD_SUPERVISION_APP_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\add_supervision\add_supervision_app.js" use_base_dir="false" type="chrome_html" />
         <include name="IDR_ADD_SUPERVISION_UI_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\add_supervision\add_supervision_ui.js" use_base_dir="false" type="chrome_html" />
         <include name="IDR_ADD_SUPERVISION_API_SERVER_JS" file="resources\chromeos\add_supervision\add_supervision_api_server.js" type="BINDATA" />
         <include name="IDR_ADD_SUPERVISION_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\ash\add_supervision\add_supervision.mojom-lite.js" use_base_dir="false" type="BINDATA" />
diff --git a/chrome/browser/chained_back_navigation_tracker.cc b/chrome/browser/chained_back_navigation_tracker.cc
new file mode 100644
index 0000000..07a515bb
--- /dev/null
+++ b/chrome/browser/chained_back_navigation_tracker.cc
@@ -0,0 +1,81 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chained_back_navigation_tracker.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_handle.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h"
+#include "ui/base/page_transition_types.h"
+
+namespace chrome {
+
+ChainedBackNavigationTracker::ChainedBackNavigationTracker(
+    content::WebContents* contents)
+    : content::WebContentsObserver(contents),
+      content::WebContentsUserData<ChainedBackNavigationTracker>(*contents) {}
+
+ChainedBackNavigationTracker::~ChainedBackNavigationTracker() = default;
+
+void ChainedBackNavigationTracker::DidStartNavigation(
+    content::NavigationHandle* navigation) {
+  if (navigation->GetNavigationEntry() &&
+      (navigation->GetNavigationEntry()->GetTransitionType() &
+       ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK) &&
+      !navigation->IsRendererInitiated()) {
+    IncrementChainedBackNavigationCount();
+  } else {
+    ResetChainedBackNavigationCount();
+  }
+}
+
+void ChainedBackNavigationTracker::IncrementChainedBackNavigationCount() {
+  if (chained_back_navigation_count_ == 0 ||
+      (base::TimeTicks::Now() - last_back_navigation_time_).InMilliseconds() <=
+          kMaxChainedBackNavigationIntervalInMilliseconds) {
+    chained_back_navigation_count_++;
+  } else {
+    chained_back_navigation_count_ = 1u;
+  }
+  last_back_navigation_time_ = base::TimeTicks::Now();
+}
+
+void ChainedBackNavigationTracker::ResetChainedBackNavigationCount() {
+  chained_back_navigation_count_ = 0;
+  last_back_navigation_time_ = base::TimeTicks();
+}
+
+void ChainedBackNavigationTracker::
+    RecordBackButtonClickForChainedBackNavigation() {
+  if (chained_back_button_click_count_ == 0 ||
+      (base::TimeTicks::Now() - last_back_button_click_time_)
+              .InMilliseconds() <=
+          kMaxChainedBackNavigationIntervalInMilliseconds) {
+    chained_back_button_click_count_++;
+  } else {
+    chained_back_button_click_count_ = 1u;
+  }
+  last_back_button_click_time_ = base::TimeTicks::Now();
+}
+
+bool ChainedBackNavigationTracker::IsChainedBackNavigationRecentlyPerformed()
+    const {
+  return (base::TimeTicks::Now() - last_back_navigation_time_)
+                 .InMilliseconds() <=
+             kMaxChainedBackNavigationIntervalInMilliseconds &&
+         chained_back_navigation_count_ >= kMinimumChainedBackNavigationLength;
+}
+
+bool ChainedBackNavigationTracker::
+    IsBackButtonChainedBackNavigationRecentlyPerformed() const {
+  return IsChainedBackNavigationRecentlyPerformed() &&
+         (base::TimeTicks::Now() - last_back_button_click_time_)
+                 .InMilliseconds() <=
+             kMaxChainedBackNavigationIntervalInMilliseconds &&
+         chained_back_button_click_count_ >=
+             kMinimumChainedBackNavigationLength;
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(ChainedBackNavigationTracker);
+
+}  // namespace chrome
diff --git a/chrome/browser/chained_back_navigation_tracker.h b/chrome/browser/chained_back_navigation_tracker.h
new file mode 100644
index 0000000..46290d5d
--- /dev/null
+++ b/chrome/browser/chained_back_navigation_tracker.h
@@ -0,0 +1,84 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHAINED_BACK_NAVIGATION_TRACKER_H_
+#define CHROME_BROWSER_CHAINED_BACK_NAVIGATION_TRACKER_H_
+
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace chrome {
+
+// This class tracks chained back navigations (consecutive back navigations with
+// a short interval between them) by observing navigation events from
+// WebContents and providing functions to record back button clicks.
+class ChainedBackNavigationTracker
+    : public content::WebContentsObserver,
+      public content::WebContentsUserData<ChainedBackNavigationTracker> {
+ public:
+  ~ChainedBackNavigationTracker() override;
+
+  ChainedBackNavigationTracker(const ChainedBackNavigationTracker&) = delete;
+  ChainedBackNavigationTracker& operator=(const ChainedBackNavigationTracker&) =
+      delete;
+
+  // content::WebContentsObserver
+  void DidStartNavigation(content::NavigationHandle* navigation) override;
+
+  // Notifies the `ChainedBackNavigationTracker` that a back/forward button is
+  // clicked. This will be used to determined if a chained back navigation is
+  // performed by back button.
+  void RecordBackButtonClickForChainedBackNavigation();
+
+  // The two functions below should be called to determine if the relevant user
+  // education promotion (such as the one for back navigation menu) should be
+  // displayed according to the corresponding trigger condition.
+  // Returns if a chained back/forward navigation is performed no earlier that
+  // the `kMaxChainedBackNavigationIntervalInMilliseconds` ago.
+  bool IsChainedBackNavigationRecentlyPerformed() const;
+  // Returns if a chained back button click events that caused chained back
+  // navigation is performed no earlier than the
+  // `kMaxChainedBackNavigationIntervalInMilliseconds` ago.
+  bool IsBackButtonChainedBackNavigationRecentlyPerformed() const;
+
+  // The threshold for two back/forward navigation to be considered chained.
+  static const int64_t kMaxChainedBackNavigationIntervalInMilliseconds = 3000;
+  // The minimum number of back/forward navigations in a chain for the
+  // `ChainedBackNavigationTracker` to claim that a chained back navigation is
+  // performed.
+  static const uint32_t kMinimumChainedBackNavigationLength = 3u;
+
+ private:
+  friend class content::WebContentsUserData<ChainedBackNavigationTracker>;
+
+  FRIEND_TEST_ALL_PREFIXES(
+      ChainedBackNavigationTrackerTest,
+      ChainedBackNavigationStatus_ResetCountIfNonBackForwardNavigationHappens);
+
+  explicit ChainedBackNavigationTracker(content::WebContents* contents);
+
+  // Helper functions that modify the `last_back_navigation_time_` and
+  // `chained_back_navigation_count_`.
+  // The chained back navigation count should increment when a back/forward
+  // navigation is performed and the interval between the current time tick and
+  // the last recorded time tick is smaller than the threshold.
+  void IncrementChainedBackNavigationCount();
+  // The chained back navigation count should be reset to 0 if a
+  // non-back/forward navigation is performed.
+  void ResetChainedBackNavigationCount();
+
+  // Chained back navigation variables that are used to record the number of
+  // consecutive back navigation and back button click events with interval
+  // shorter than some threshold.
+  uint32_t chained_back_navigation_count_ = 0;
+  uint32_t chained_back_button_click_count_ = 0;
+  base::TimeTicks last_back_navigation_time_;
+  base::TimeTicks last_back_button_click_time_;
+
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+};
+
+}  // namespace chrome
+
+#endif  // CHROME_BROWSER_CHAINED_BACK_NAVIGATION_TRACKER_H_
diff --git a/chrome/browser/chained_back_navigation_tracker_unittest.cc b/chrome/browser/chained_back_navigation_tracker_unittest.cc
new file mode 100644
index 0000000..7f1ee35
--- /dev/null
+++ b/chrome/browser/chained_back_navigation_tracker_unittest.cc
@@ -0,0 +1,184 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chained_back_navigation_tracker.h"
+
+#include "base/test/bind.h"
+#include "base/test/task_environment.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/navigation_simulator.h"
+
+namespace chrome {
+
+class ChainedBackNavigationTrackerTest
+    : public ChromeRenderViewHostTestHarness {
+ public:
+  ChainedBackNavigationTrackerTest()
+      : ChromeRenderViewHostTestHarness(
+            base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+
+ protected:
+  const uint32_t min_navigation_cnt_ =
+      ChainedBackNavigationTracker::kMinimumChainedBackNavigationLength;
+  const int64_t max_navigation_interval_ = ChainedBackNavigationTracker::
+      kMaxChainedBackNavigationIntervalInMilliseconds;
+};
+
+TEST_F(ChainedBackNavigationTrackerTest, ChainedBackNavigationStatus) {
+  std::vector<const GURL> urls;
+  for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) {
+    urls.push_back(GURL("http://foo/" + base::NumberToString(i)));
+  }
+  for (const GURL& url : urls) {
+    NavigateAndCommit(url);
+  }
+
+  ChainedBackNavigationTracker::CreateForWebContents(web_contents());
+  const ChainedBackNavigationTracker* tracker =
+      ChainedBackNavigationTracker::FromWebContents(web_contents());
+  ASSERT_TRUE(tracker);
+
+  // Before any back navigation, the return value for these two checker
+  // functions should be false.
+  ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
+  ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+
+  for (uint32_t i = 1; i < urls.size(); ++i) {
+    content::NavigationSimulator::GoBack(web_contents());
+    // Since `RecordBackButtonClickForChainedBackNavigation()` is never called,
+    // `IsBackButtonChainedBackNavigationRecentlyPerformed()` should always
+    // returns false.
+    ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+    // The check should only return true when the number of consecutive back
+    // navigation is smaller than `kMinimumChainedBackNavigationLength`.
+    if (i < min_navigation_cnt_) {
+      ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
+    } else {
+      ASSERT_TRUE(tracker->IsChainedBackNavigationRecentlyPerformed());
+    }
+  }
+}
+
+TEST_F(ChainedBackNavigationTrackerTest,
+       ChainedBackNavigationStatus_ResetCountIfIntervalIsTooLong) {
+  std::vector<const GURL> urls;
+  for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) {
+    urls.push_back(GURL("http://foo/" + base::NumberToString(i)));
+  }
+  for (const GURL& url : urls) {
+    NavigateAndCommit(url);
+  }
+
+  ChainedBackNavigationTracker::CreateForWebContents(web_contents());
+  const ChainedBackNavigationTracker* tracker =
+      ChainedBackNavigationTracker::FromWebContents(web_contents());
+  ASSERT_TRUE(tracker);
+
+  // Before any back navigation, the return value for these two checker
+  // functions should be false.
+  ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
+  ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+
+  for (uint32_t i = 1; i < min_navigation_cnt_; ++i) {
+    content::NavigationSimulator::GoBack(web_contents());
+    // The checks should always return false since the number of consecutive
+    // back navigation is smaller than `kMinimumChainedBackNavigationLength`.
+    ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
+    ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+  }
+
+  // After waiting for sufficiently long interval, the counter should be reset
+  // so the checks should always return false.
+  task_environment()->FastForwardBy(
+      base::Milliseconds(max_navigation_interval_ * 2));
+  ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
+  ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+
+  for (uint32_t i = 1; i < min_navigation_cnt_; ++i) {
+    content::NavigationSimulator::GoBack(web_contents());
+    ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+    ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
+  }
+}
+
+TEST_F(
+    ChainedBackNavigationTrackerTest,
+    ChainedBackNavigationStatus_ResetCountIfNonBackForwardNavigationHappens) {
+  std::vector<const GURL> urls;
+  for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) {
+    urls.push_back(GURL("http://foo/" + base::NumberToString(i)));
+  }
+  for (const GURL& url : urls) {
+    NavigateAndCommit(url);
+  }
+
+  ChainedBackNavigationTracker::CreateForWebContents(web_contents());
+  const ChainedBackNavigationTracker* tracker =
+      ChainedBackNavigationTracker::FromWebContents(web_contents());
+  ASSERT_TRUE(tracker);
+
+  // Before any back navigation, the return value for these two checker
+  // functions should be false.
+  ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
+  ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+
+  for (uint32_t i = 1; i < min_navigation_cnt_; ++i) {
+    content::NavigationSimulator::GoBack(web_contents());
+    ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+    ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
+  }
+
+  // After performing another non history navigation, the counter should be
+  // reset so the checks should always return false.
+  NavigateAndCommit(GURL("http://bar/1"));
+  ASSERT_EQ(0u, tracker->chained_back_navigation_count_);
+
+  for (uint32_t i = 1; i < min_navigation_cnt_; ++i) {
+    content::NavigationSimulator::GoBack(web_contents());
+    ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+    ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
+  }
+}
+
+TEST_F(ChainedBackNavigationTrackerTest,
+       ChainedBackNavigationStatus_BackButtonClicked) {
+  std::vector<const GURL> urls;
+  for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) {
+    urls.push_back(GURL("http://foo/" + base::NumberToString(i)));
+  }
+  for (const GURL& url : urls) {
+    NavigateAndCommit(url);
+  }
+
+  ChainedBackNavigationTracker::CreateForWebContents(web_contents());
+  ChainedBackNavigationTracker* tracker =
+      ChainedBackNavigationTracker::FromWebContents(web_contents());
+  ASSERT_TRUE(tracker);
+
+  // Before any back navigation, the return value for these two checker
+  // functions should be false.
+  ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
+  ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+
+  for (uint32_t i = 1; i < urls.size(); ++i) {
+    tracker->RecordBackButtonClickForChainedBackNavigation();
+    content::NavigationSimulator::GoBack(web_contents());
+    // The checks should only return true when the number of consecutive back
+    // navigation is greater than or equal to
+    // `kMinimumChainedBackNavigationLength`.
+    if (i >= min_navigation_cnt_) {
+      ASSERT_TRUE(tracker->IsChainedBackNavigationRecentlyPerformed());
+      ASSERT_TRUE(
+          tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+    } else {
+      ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
+      ASSERT_FALSE(
+          tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
+    }
+  }
+}
+
+}  // namespace chrome
diff --git a/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc b/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc
index 7031d48..59355e3 100644
--- a/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc
+++ b/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc
@@ -194,7 +194,7 @@
                           "fetch($1).then(response => response.ok)",
                           https_server().GetURL("b.com", "/cors-ok.txt"))));
 
-  CheckCounter(WebFeature::kPrivateNetworkAccessIgnoredPreflightError, 1);
+  CheckCounter(WebFeature::kPrivateNetworkAccessPreflightWarning, 1);
   CheckCounter(
       WebFeature::kPrivateNetworkAccessIgnoredCrossOriginPreflightError, 1);
   CheckCounter(WebFeature::kPrivateNetworkAccessIgnoredCrossSitePreflightError,
@@ -216,7 +216,7 @@
                                       https_server().GetURL("subdomain.a.com",
                                                             "/cors-ok.txt"))));
 
-  CheckCounter(WebFeature::kPrivateNetworkAccessIgnoredPreflightError, 1);
+  CheckCounter(WebFeature::kPrivateNetworkAccessPreflightWarning, 1);
   CheckCounter(
       WebFeature::kPrivateNetworkAccessIgnoredCrossOriginPreflightError, 1);
   CheckCounter(WebFeature::kPrivateNetworkAccessIgnoredCrossSitePreflightError,
@@ -237,7 +237,7 @@
                           "fetch($1).then(response => response.ok)",
                           https_server().GetURL("a.com", "/cors-ok.txt"))));
 
-  CheckCounter(WebFeature::kPrivateNetworkAccessIgnoredPreflightError, 1);
+  CheckCounter(WebFeature::kPrivateNetworkAccessPreflightWarning, 1);
   CheckCounter(
       WebFeature::kPrivateNetworkAccessIgnoredCrossOriginPreflightError, 0);
   CheckCounter(WebFeature::kPrivateNetworkAccessIgnoredCrossSitePreflightError,
diff --git a/chrome/browser/chromeos/arc/start_smart_selection_action_menu.cc b/chrome/browser/chromeos/arc/start_smart_selection_action_menu.cc
index adb0f846..d52b556 100644
--- a/chrome/browser/chromeos/arc/start_smart_selection_action_menu.cc
+++ b/chrome/browser/chromeos/arc/start_smart_selection_action_menu.cc
@@ -103,7 +103,7 @@
   }
 
   if (!delegate_->RequestTextSelectionActions(
-          converted_text, ui::GetSupportedResourceScaleFactors().back(),
+          converted_text, ui::GetMaxSupportedResourceScaleFactor(),
           base::BindOnce(
               &StartSmartSelectionActionMenu::HandleTextSelectionActions,
               weak_ptr_factory_.GetWeakPtr()))) {
diff --git a/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc b/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc
index 6576a0ef..afebfff 100644
--- a/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc
+++ b/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc
@@ -182,13 +182,11 @@
       message_id = IDS_POLICY_DLP_FILES_UPLOAD_WARN_MESSAGE;
       break;
     case DlpFilesController::FileAction::kCopy:
-      // TODO(b/273521961): Handle urls.
-      destination_str = GetDestinationComponent(destination_);
+      destination_str = GetDestination(destination_);
       message_id = IDS_POLICY_DLP_FILES_COPY_WARN_MESSAGE;
       break;
     case DlpFilesController::FileAction::kMove:
-      // TODO(b/273521961): Handle urls.
-      destination_str = GetDestinationComponent(destination_);
+      destination_str = GetDestination(destination_);
       message_id = IDS_POLICY_DLP_FILES_MOVE_WARN_MESSAGE;
       break;
     case DlpFilesController::FileAction::kOpen:
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java
index 0e4496f..9fd873b9 100644
--- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java
+++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java
@@ -14,6 +14,7 @@
 import android.view.ViewGroup.LayoutParams;
 import android.widget.FrameLayout;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
@@ -27,6 +28,7 @@
 import org.chromium.chrome.browser.feed.FeedListContentManager;
 import org.chromium.chrome.browser.feed.FeedListContentManager.FeedContent;
 import org.chromium.chrome.browser.feed.FeedStream;
+import org.chromium.chrome.browser.feed.FeedStreamViewResizer;
 import org.chromium.chrome.browser.feed.FeedSurfaceScopeDependencyProviderImpl;
 import org.chromium.chrome.browser.feed.FeedSurfaceTracker;
 import org.chromium.chrome.browser.feed.NativeViewListRenderer;
@@ -54,6 +56,7 @@
 import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver;
 import org.chromium.components.browser_ui.styles.SemanticColorUtils;
 import org.chromium.components.browser_ui.widget.RoundedIconGenerator;
+import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
 import org.chromium.components.embedder_support.view.ContentView;
 import org.chromium.components.url_formatter.UrlFormatter;
@@ -86,6 +89,7 @@
     private CreatorTabMediator mTabMediator;
     private Activity mActivity;
     private FeedListContentManager mContentManager;
+    private UiConfig mUiConfig;
     private RecyclerView mRecyclerView;
     private View mProfileView;
     private ViewGroup mLayoutView;
@@ -122,6 +126,8 @@
     private GURL mBottomSheetUrl;
     private int mEntryPoint;
 
+    private @Nullable FeedStreamViewResizer mStreamViewResizer;
+
     private static final String CREATOR_PROFILE_ID = "CreatorProfileView";
     private static final String CREATOR_PRIVACY_ID = "CreatorPrivacyId";
 
@@ -169,6 +175,9 @@
         mCreatorViewGroup =
                 (ViewGroup) LayoutInflater.from(mActivity).inflate(R.layout.creator_activity, null);
         mLayoutView = mCreatorViewGroup.findViewById(R.id.creator_layout);
+        mUiConfig = new UiConfig(mLayoutView);
+        mStreamViewResizer =
+                FeedStreamViewResizer.createAndAttach(mActivity, mRecyclerView, mUiConfig);
         mLayoutView.addView(mRecyclerView);
 
         // Generate Creator Model
diff --git a/chrome/browser/devtools/BUILD.gn b/chrome/browser/devtools/BUILD.gn
index 86565d7..5267be4 100644
--- a/chrome/browser/devtools/BUILD.gn
+++ b/chrome/browser/devtools/BUILD.gn
@@ -28,6 +28,8 @@
     "protocol/protocol.h",
     "protocol/security.cc",
     "protocol/security.h",
+    "protocol/storage.cc",
+    "protocol/storage.h",
     "protocol/target.cc",
     "protocol/target.h",
   ]
@@ -257,6 +259,8 @@
       "protocol/page_handler.h",
       "protocol/security_handler.cc",
       "protocol/security_handler.h",
+      "protocol/storage_handler.cc",
+      "protocol/storage_handler.h",
       "protocol/target_handler.cc",
       "protocol/target_handler.h",
     ]
diff --git a/chrome/browser/devtools/chrome_devtools_session.cc b/chrome/browser/devtools/chrome_devtools_session.cc
index e83425d..5b7deb7d 100644
--- a/chrome/browser/devtools/chrome_devtools_session.cc
+++ b/chrome/browser/devtools/chrome_devtools_session.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/devtools/protocol/emulation_handler.h"
 #include "chrome/browser/devtools/protocol/page_handler.h"
 #include "chrome/browser/devtools/protocol/security_handler.h"
+#include "chrome/browser/devtools/protocol/storage_handler.h"
 #include "chrome/browser/devtools/protocol/target_handler.h"
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/devtools_agent_host_client.h"
@@ -58,6 +59,11 @@
       cast_handler_ = std::make_unique<CastHandler>(
           agent_host->GetWebContents(), &dispatcher_);
     }
+    if (IsDomainAvailableToUntrustedClient<StorageHandler>() ||
+        channel->GetClient()->IsTrusted()) {
+      storage_handler_ = std::make_unique<StorageHandler>(
+          agent_host->GetWebContents(), &dispatcher_);
+    }
   }
   if (IsDomainAvailableToUntrustedClient<EmulationHandler>() ||
       channel->GetClient()->IsTrusted()) {
diff --git a/chrome/browser/devtools/chrome_devtools_session.h b/chrome/browser/devtools/chrome_devtools_session.h
index 87090e9..95692f0 100644
--- a/chrome/browser/devtools/chrome_devtools_session.h
+++ b/chrome/browser/devtools/chrome_devtools_session.h
@@ -11,6 +11,7 @@
 #include "base/containers/span.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/devtools/protocol/protocol.h"
+#include "chrome/browser/devtools/protocol/storage_handler.h"
 #include "content/public/browser/devtools_manager_delegate.h"
 
 namespace content {
@@ -22,6 +23,7 @@
 class CastHandler;
 class PageHandler;
 class SecurityHandler;
+class StorageHandler;
 class TargetHandler;
 class WindowManagerHandler;
 
@@ -62,6 +64,7 @@
   std::unique_ptr<EmulationHandler> emulation_handler_;
   std::unique_ptr<PageHandler> page_handler_;
   std::unique_ptr<SecurityHandler> security_handler_;
+  std::unique_ptr<StorageHandler> storage_handler_;
   std::unique_ptr<TargetHandler> target_handler_;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<WindowManagerHandler> window_manager_handler_;
diff --git a/chrome/browser/devtools/inspector_protocol_config.json b/chrome/browser/devtools/inspector_protocol_config.json
index 9ee8d176..b35655e 100644
--- a/chrome/browser/devtools/inspector_protocol_config.json
+++ b/chrome/browser/devtools/inspector_protocol_config.json
@@ -37,6 +37,11 @@
                 "domain": "Security",
                 "include": [ "enable", "disable" ],
                 "include_events": [ "visibleSecurityStateChanged" ]
+            },
+            {
+                "domain": "Storage",
+                "include": ["runBounceTrackingMitigations"],
+                "async": ["runBounceTrackingMitigations"]
             }
         ]
     },
diff --git a/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 7af1f3c..db208a5 100644
--- a/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -21,6 +21,9 @@
 #include "chrome/browser/data_saver/data_saver.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/devtools/protocol/devtools_protocol_test_support.h"
+#include "chrome/browser/dips/dips_features.h"
+#include "chrome/browser/dips/dips_service.h"
+#include "chrome/browser/dips/dips_storage.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/extensions/unpacked_installer.h"
@@ -332,6 +335,55 @@
             registry->registration_mode());
 }
 
+class DevToolsProtocolTest_BounceTrackingMitigations
+    : public DevToolsProtocolTest {
+ protected:
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        dips::kFeature,
+        {{"delete", "true"}, {"triggering_action", "stateful_bounce"}});
+
+    DevToolsProtocolTest::SetUp();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest_BounceTrackingMitigations,
+                       RunBounceTrackingMitigations) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  const GURL url(embedded_test_server()->GetURL("/empty.html"));
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+  Attach();
+
+  const GURL bouncer(
+      embedded_test_server()->GetURL("example.test", "/title1.html"));
+
+  // Get DIPS Service
+  DIPSService* dips_service = DIPSService::Get(browser()->profile());
+  dips_service->WaitForInitCompleteForTesting();
+
+  // Record a stateful bounce for `bouncer`.
+  dips_service->storage()
+      ->AsyncCall(&DIPSStorage::RecordBounce)
+      .WithArgs(bouncer, base::Time::Now(), true);
+  dips_service->storage()->FlushPostedTasksForTesting();
+
+  SendCommandSync("Storage.runBounceTrackingMitigations");
+
+  const base::Value::List* deleted_sites_list =
+      result()->FindList("deletedSites");
+  ASSERT_TRUE(deleted_sites_list);
+
+  std::vector<std::string> deleted_sites;
+  for (const auto& site : *deleted_sites_list) {
+    deleted_sites.push_back(site.GetString());
+  }
+
+  EXPECT_THAT(deleted_sites, testing::ElementsAre("example.test"));
+}
+
 using DevToolsProtocolTest_AppId = DevToolsProtocolTest;
 
 IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest_AppId, ReturnsManifestAppId) {
diff --git a/chrome/browser/devtools/protocol/storage_handler.cc b/chrome/browser/devtools/protocol/storage_handler.cc
new file mode 100644
index 0000000..f230115
--- /dev/null
+++ b/chrome/browser/devtools/protocol/storage_handler.cc
@@ -0,0 +1,41 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/devtools/protocol/storage_handler.h"
+
+#include "chrome/browser/dips/dips_service.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+
+StorageHandler::StorageHandler(content::WebContents* web_contents,
+                               protocol::UberDispatcher* dispatcher)
+    : web_contents_(web_contents->GetWeakPtr()) {
+  protocol::Storage::Dispatcher::wire(dispatcher, this);
+}
+
+StorageHandler::~StorageHandler() = default;
+
+void StorageHandler::RunBounceTrackingMitigations(
+    std::unique_ptr<RunBounceTrackingMitigationsCallback> callback) {
+  DIPSService* dips_service =
+      web_contents_ ? DIPSService::Get(web_contents_->GetBrowserContext())
+                    : nullptr;
+
+  if (!dips_service) {
+    callback->sendFailure(protocol::Response::ServerError("No DIPSService"));
+    return;
+  }
+
+  dips_service->DeleteEligibleSitesImmediately(
+      base::BindOnce(&StorageHandler::GotDeletedSites, std::move(callback)));
+}
+
+/* static */
+void StorageHandler::GotDeletedSites(
+    std::unique_ptr<RunBounceTrackingMitigationsCallback> callback,
+    const std::vector<std::string>& sites) {
+  auto deleted_sites =
+      std::make_unique<protocol::Array<protocol::String>>(sites);
+  callback->sendSuccess(std::move(deleted_sites));
+}
diff --git a/chrome/browser/devtools/protocol/storage_handler.h b/chrome/browser/devtools/protocol/storage_handler.h
new file mode 100644
index 0000000..64777a8
--- /dev/null
+++ b/chrome/browser/devtools/protocol/storage_handler.h
@@ -0,0 +1,36 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DEVTOOLS_PROTOCOL_STORAGE_HANDLER_H_
+#define CHROME_BROWSER_DEVTOOLS_PROTOCOL_STORAGE_HANDLER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/devtools/protocol/storage.h"
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+class StorageHandler : public protocol::Storage::Backend {
+ public:
+  StorageHandler(content::WebContents* web_contents,
+                 protocol::UberDispatcher* dispatcher);
+
+  StorageHandler(const StorageHandler&) = delete;
+  StorageHandler& operator=(const StorageHandler&) = delete;
+
+  ~StorageHandler() override;
+
+ private:
+  void RunBounceTrackingMitigations(
+      std::unique_ptr<RunBounceTrackingMitigationsCallback> callback) override;
+
+  static void GotDeletedSites(
+      std::unique_ptr<RunBounceTrackingMitigationsCallback> callback,
+      const std::vector<std::string>& sites);
+
+  base::WeakPtr<content::WebContents> web_contents_;
+};
+
+#endif  // CHROME_BROWSER_DEVTOOLS_PROTOCOL_STORAGE_HANDLER_H_
diff --git a/chrome/browser/dips/dips_service.cc b/chrome/browser/dips/dips_service.cc
index 8852ddf2..7a16364 100644
--- a/chrome/browser/dips/dips_service.cc
+++ b/chrome/browser/dips/dips_service.cc
@@ -9,6 +9,8 @@
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/functional/bind.h"
+#include "base/functional/callback_forward.h"
+#include "base/functional/callback_helpers.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/strcat.h"
@@ -100,6 +102,12 @@
                                  base::Time::Now() - deletion_start);
 }
 
+void OnDeletionFinished(base::OnceClosure finished_callback,
+                        base::Time deletion_start) {
+  UmaHistogramDeletionLatency(deletion_start);
+  std::move(finished_callback).Run();
+}
+
 class StateClearer : public content::BrowsingDataRemover::Observer {
  public:
   StateClearer(const StateClearer&) = delete;
@@ -387,19 +395,23 @@
   storage_.AsyncCall(&DIPSStorage::GetSitesToClear)
       .WithArgs(absl::nullopt)
       .Then(base::BindOnce(&DIPSService::DeleteDIPSEligibleState,
-                           weak_factory_.GetWeakPtr(), start));
+                           weak_factory_.GetWeakPtr(), base::DoNothing(),
+                           start));
 }
 
-void DIPSService::DeleteEligibleSitesImmediately() {
+void DIPSService::DeleteEligibleSitesImmediately(
+    DeletedSitesCallback callback) {
   base::Time start = base::Time::Now();
   // Storage init should be finished by now, so no need to delay until then.
   storage_.AsyncCall(&DIPSStorage::GetSitesToClear)
       .WithArgs(base::Seconds(0))
       .Then(base::BindOnce(&DIPSService::DeleteDIPSEligibleState,
-                           weak_factory_.GetWeakPtr(), start));
+                           weak_factory_.GetWeakPtr(), std::move(callback),
+                           start));
 }
 
 void DIPSService::DeleteDIPSEligibleState(
+    DeletedSitesCallback callback,
     base::Time deletion_start,
     std::vector<std::string> sites_to_clear) {
   base::UmaHistogramCounts1000(
@@ -408,6 +420,7 @@
       sites_to_clear.size());
 
   if (sites_to_clear.empty()) {
+    std::move(callback).Run(std::vector<std::string>());
     return;
   }
 
@@ -418,6 +431,8 @@
         ukm::UkmRecorder::Get());
   }
 
+  base::OnceClosure finish_callback;
+
   if (ShouldBlockThirdPartyCookies() && dips::kDeletionEnabled.Get()) {
     if (IsShuttingDown()) {
       return;
@@ -434,25 +449,35 @@
       }
     }
 
+    finish_callback = base::BindOnce(
+        std::move(callback), std::vector<std::string>(non_excepted_sites));
+
     if (excepted_sites.empty()) {
-      PostDeletionTaskToUIThread(deletion_start, std::move(non_excepted_sites));
+      PostDeletionTaskToUIThread(std::move(finish_callback), deletion_start,
+                                 std::move(non_excepted_sites));
     } else {
       // Storage init should be finished by now, so no need to delay until then.
       storage_.AsyncCall(&DIPSStorage::RemoveRows)
           .WithArgs(std::move(excepted_sites))
           .Then(base::BindOnce(&DIPSService::PostDeletionTaskToUIThread,
-                               weak_factory_.GetWeakPtr(), deletion_start,
+                               weak_factory_.GetWeakPtr(),
+                               std::move(finish_callback), deletion_start,
                                std::move(non_excepted_sites)));
     }
   } else {
+    finish_callback = base::BindOnce(std::move(callback),
+                                     std::vector<std::string>(sites_to_clear));
+
     // Storage init should be finished by now, so no need to delay until then.
     storage_.AsyncCall(&DIPSStorage::RemoveRows)
         .WithArgs(std::move(sites_to_clear))
-        .Then(base::BindOnce(&UmaHistogramDeletionLatency, deletion_start));
+        .Then(base::BindOnce(&OnDeletionFinished, std::move(finish_callback),
+                             deletion_start));
   }
 }
 
-void DIPSService::PostDeletionTaskToUIThread(base::Time deletion_start,
+void DIPSService::PostDeletionTaskToUIThread(base::OnceClosure callback,
+                                             base::Time deletion_start,
                                              std::vector<std::string> sites) {
   std::unique_ptr<content::BrowsingDataFilterBuilder> filter =
       content::BrowsingDataFilterBuilder::Create(
@@ -462,10 +487,11 @@
   }
 
   content::GetUIThreadTaskRunner({})->PostTask(
-      FROM_HERE, base::BindOnce(&DIPSService::RunDeletionTaskOnUIThread,
-                                weak_factory_.GetWeakPtr(), std::move(filter),
-                                base::BindOnce(&UmaHistogramDeletionLatency,
-                                               deletion_start)));
+      FROM_HERE,
+      base::BindOnce(&DIPSService::RunDeletionTaskOnUIThread,
+                     weak_factory_.GetWeakPtr(), std::move(filter),
+                     base::BindOnce(&OnDeletionFinished, std::move(callback),
+                                    deletion_start)));
 }
 
 void DIPSService::RunDeletionTaskOnUIThread(
diff --git a/chrome/browser/dips/dips_service.h b/chrome/browser/dips/dips_service.h
index 833da83..67a0abb 100644
--- a/chrome/browser/dips/dips_service.h
+++ b/chrome/browser/dips/dips_service.h
@@ -38,6 +38,8 @@
  public:
   using RecordBounceCallback = base::RepeatingCallback<
       void(const GURL& url, base::Time time, bool stateful)>;
+  using DeletedSitesCallback =
+      base::OnceCallback<void(const std::vector<std::string>& sites)>;
 
   ~DIPSService() override;
 
@@ -59,7 +61,7 @@
 
   // This allows for deletion of state for sites deemed eligible when evaluated
   // with no grace period.
-  void DeleteEligibleSitesImmediately();
+  void DeleteEligibleSitesImmediately(DeletedSitesCallback callback);
 
   void HandleRedirectChain(std::vector<DIPSRedirectInfoPtr> redirects,
                            DIPSRedirectChainInfoPtr chain);
@@ -111,9 +113,11 @@
 
   void OnStorageInitialized();
   void OnTimerFired();
-  void DeleteDIPSEligibleState(base::Time deletion_start,
+  void DeleteDIPSEligibleState(DeletedSitesCallback callback,
+                               base::Time deletion_start,
                                std::vector<std::string> sites_to_clear);
-  void PostDeletionTaskToUIThread(base::Time deletion_start,
+  void PostDeletionTaskToUIThread(base::OnceClosure callback,
+                                  base::Time deletion_start,
                                   std::vector<std::string> sites_to_clear);
   void RunDeletionTaskOnUIThread(
       std::unique_ptr<content::BrowsingDataFilterBuilder> filter,
diff --git a/chrome/browser/dips/dips_service_unittest.cc b/chrome/browser/dips/dips_service_unittest.cc
index 60b8e8e0..d5e2c88 100644
--- a/chrome/browser/dips/dips_service_unittest.cc
+++ b/chrome/browser/dips/dips_service_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_util.h"
 #include "base/memory/raw_ptr.h"
+#include "base/run_loop.h"
 #include "base/strings/string_piece_forward.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
@@ -421,9 +422,19 @@
           content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
       filter_builder.get());
 
-  // Perform immediate enforcement of deletion, without regard for grace period.
-  GetService()->DeleteEligibleSitesImmediately();
+  // Perform immediate enforcement of deletion, without regard for grace period
+  // and verify `url` is returned the `DeletedSitesCallback`.
+  base::RunLoop run_loop;
+  base::OnceCallback<void(const std::vector<std::string>& sites)> callback =
+      base::BindLambdaForTesting(
+          [&](const std::vector<std::string>& deleted_sites) {
+            EXPECT_THAT(deleted_sites,
+                        testing::UnorderedElementsAre(GetSiteForDIPS(url)));
+            run_loop.Quit();
+          });
+  GetService()->DeleteEligibleSitesImmediately(std::move(callback));
   task_environment_.RunUntilIdle();
+  run_loop.Run();
 
   // Verify that a removal task was posted to the BrowsingDataRemover(Delegate)
   // for 'url'.
diff --git a/chrome/browser/extensions/api/notifications/notifications_api.cc b/chrome/browser/extensions/api/notifications/notifications_api.cc
index 9d9aa16..0a850ca 100644
--- a/chrome/browser/extensions/api/notifications/notifications_api.cc
+++ b/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -220,7 +220,7 @@
   NotificationBitmapSizes bitmap_sizes = GetNotificationBitmapSizes();
 
   float image_scale = ui::GetScaleForResourceScaleFactor(
-      ui::GetSupportedResourceScaleFactors().back());
+      ui::GetMaxSupportedResourceScaleFactor());
 
   // Extract required fields: type, title, message, and icon.
   message_center::NotificationType type =
@@ -378,7 +378,7 @@
 
   NotificationBitmapSizes bitmap_sizes = GetNotificationBitmapSizes();
   float image_scale = ui::GetScaleForResourceScaleFactor(
-      ui::GetSupportedResourceScaleFactors().back());
+      ui::GetMaxSupportedResourceScaleFactor());
 
   // Update optional fields if provided.
   if (options->type != api::notifications::TEMPLATE_TYPE_NONE)
diff --git a/chrome/browser/extensions/process_map_browsertest.cc b/chrome/browser/extensions/process_map_browsertest.cc
index 0f454ad..447829c 100644
--- a/chrome/browser/extensions/process_map_browsertest.cc
+++ b/chrome/browser/extensions/process_map_browsertest.cc
@@ -16,6 +16,9 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "extensions/browser/app_window/app_window.h"
+#include "extensions/browser/app_window/app_window_registry.h"
+#include "extensions/browser/guest_view/web_view/web_view_guest.h"
 #include "extensions/browser/process_map.h"
 #include "extensions/common/constants.h"
 #include "extensions/test/extension_test_message_listener.h"
@@ -118,6 +121,89 @@
     return extension;
   }
 
+  const Extension* AddExtensionWithWebViewAndOpen() {
+    static constexpr char kManifest[] =
+        R"({
+             "name": "Web View",
+             "manifest_version": 2,
+             "version": "0.1",
+             "app": {
+               "background": { "scripts": ["background.js"] }
+             },
+             "webview": {
+               "partitions": [{
+                 "name": "foo",
+                 "accessible_resources": ["accessible.html"]
+               }]
+             },
+             "permissions": ["webview"]
+           })";
+    static constexpr char kBackgroundJs[] =
+        R"(chrome.app.runtime.onLaunched.addListener(() => {
+             chrome.app.window.create('embedder.html', {}, function () {});
+           });)";
+    static constexpr char kEmbedderHtml[] =
+        R"(<html>
+           <body>
+             <webview partition="foo"></webview>
+             <script src="embedder.js"></script>
+           </body>
+           </html>)";
+    static constexpr char kEmbedderJs[] =
+        R"(onload = () => {
+             let webview = document.querySelector('webview');
+             webview.addEventListener('loadstop', () => {
+               chrome.test.sendMessage('webview loaded');
+             });
+             webview.addEventListener('loadabort', (e) => {
+               console.error('Webview aborted load: ' + e.toString());
+             });
+             webview.src = 'accessible.html';
+           };)";
+    auto extension_dir = std::make_unique<TestExtensionDir>();
+    extension_dir->WriteManifest(kManifest);
+    extension_dir->WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundJs);
+    extension_dir->WriteFile(FILE_PATH_LITERAL("embedder.html"), kEmbedderHtml);
+    extension_dir->WriteFile(FILE_PATH_LITERAL("embedder.js"), kEmbedderJs);
+    extension_dir->WriteFile(FILE_PATH_LITERAL("accessible.html"), "hello");
+
+    ExtensionTestMessageListener webview_listener("webview loaded");
+    const Extension* extension = LoadAndLaunchApp(extension_dir->UnpackedPath(),
+                                                  /*uses_guest_view=*/true);
+    extension_dirs_.push_back(std::move(extension_dir));
+    EXPECT_TRUE(webview_listener.WaitUntilSatisfied());
+
+    return extension;
+  }
+
+  content::WebContents* GetAppWindowContents() {
+    AppWindowRegistry* registry = AppWindowRegistry::Get(profile());
+    if (registry->app_windows().size() != 1) {
+      ADD_FAILURE() << "Incorrect number of app windows: "
+                    << registry->app_windows().size();
+      return nullptr;
+    }
+
+    return (*registry->app_windows().begin())->web_contents();
+  }
+
+  content::WebContents* GetWebViewFromEmbedder(content::WebContents* embedder) {
+    std::vector<content::WebContents*> inner_web_contents =
+        embedder->GetInnerWebContents();
+    if (inner_web_contents.size() != 1) {
+      ADD_FAILURE() << "Unexpected number of inner web contents: "
+                    << inner_web_contents.size();
+      return nullptr;
+    }
+
+    content::WebContents* inner_contents = inner_web_contents[0];
+    if (!WebViewGuest::FromWebContents(inner_contents)) {
+      return nullptr;
+    }
+
+    return inner_contents;
+  }
+
   // Opens a new tab to the given `domain`.
   void OpenDomain(base::StringPiece domain) {
     ASSERT_TRUE(ui_test_utils::NavigateToURL(
@@ -168,6 +254,43 @@
     return is_sandboxed;
   }
 
+  // Iterates over every context type and checks if it could be hosted given the
+  // pairing of `extension` and `process_id`, expecting it to be allowed if and
+  // only if the context type is in `allowed_contexts`. `debug_string` is used
+  // in a scoped trace to make test failures more meaningful.
+  void RunCanProcessHostContextTypeChecks(
+      const Extension* extension,
+      int process_id,
+      const std::vector<Feature::Context>& allowed_contexts,
+      base::StringPiece debug_string) {
+    std::vector<Feature::Context> all_types = {
+        Feature::UNSPECIFIED_CONTEXT,
+        Feature::BLESSED_EXTENSION_CONTEXT,
+        Feature::UNBLESSED_EXTENSION_CONTEXT,
+        Feature::CONTENT_SCRIPT_CONTEXT,
+        Feature::WEB_PAGE_CONTEXT,
+        Feature::BLESSED_WEB_PAGE_CONTEXT,
+        Feature::WEBUI_CONTEXT,
+        Feature::WEBUI_UNTRUSTED_CONTEXT,
+        Feature::LOCK_SCREEN_EXTENSION_CONTEXT,
+        Feature::OFFSCREEN_EXTENSION_CONTEXT,
+        Feature::USER_SCRIPT_CONTEXT,
+    };
+
+    for (auto context_type : all_types) {
+      SCOPED_TRACE(testing::Message()
+                   << "Testing Context Type: " << context_type
+                   << ", Extension: "
+                   << (extension ? extension->name() : "<no extension>")
+                   << ", Debug String: " << debug_string);
+      bool expected_to_be_allowed =
+          base::Contains(allowed_contexts, context_type);
+      EXPECT_EQ(expected_to_be_allowed,
+                process_map()->CanProcessHostContextType(extension, process_id,
+                                                         context_type));
+    }
+  }
+
   ProcessMap* process_map() { return ProcessMap::Get(profile()); }
 
  private:
@@ -192,6 +315,28 @@
       *extension, GetActiveMainFrameProcessID()));
 }
 
+// Tests the type of contexts that can be hosted in web page processes.
+IN_PROC_BROWSER_TEST_F(ProcessMapBrowserTest, CanHostContextType_WebPages) {
+  // For fun, make sure an extension with access to the given web page is
+  // loaded (just to validate we're not doing anything related to
+  // extension permissions in our calculations).
+  const Extension* extension =
+      AddExtensionWithHostPermission("test", "*://example.com/*");
+  ASSERT_TRUE(extension);
+
+  OpenDomain("example.com");
+  int web_page_process_id = GetActiveMainFrameProcessID();
+
+  RunCanProcessHostContextTypeChecks(
+      extension, web_page_process_id,
+      {Feature::CONTENT_SCRIPT_CONTEXT, Feature::USER_SCRIPT_CONTEXT},
+      "web page with extension passed");
+  RunCanProcessHostContextTypeChecks(
+      nullptr, web_page_process_id,
+      {Feature::WEB_PAGE_CONTEXT, Feature::WEBUI_UNTRUSTED_CONTEXT},
+      "web page without extension passed");
+}
+
 // Tests that web ui pages are not considered privileged extension processes.
 IN_PROC_BROWSER_TEST_F(ProcessMapBrowserTest,
                        IsPrivilegedExtensionProcess_WebUiPages) {
@@ -205,6 +350,24 @@
       *extension, GetActiveMainFrameProcessID()));
 }
 
+// Tests the type of processes that can be hosted in web ui processes.
+IN_PROC_BROWSER_TEST_F(ProcessMapBrowserTest, CanHostContextType_WebUiPages) {
+  const Extension* extension =
+      AddExtensionWithHostPermission("test", "*://example.com/*");
+  ASSERT_TRUE(extension);
+
+  OpenWebUi();
+  int webui_process_id = GetActiveMainFrameProcessID();
+
+  RunCanProcessHostContextTypeChecks(
+      extension, webui_process_id,
+      {Feature::CONTENT_SCRIPT_CONTEXT, Feature::USER_SCRIPT_CONTEXT},
+      "webui page with extension passed");
+  RunCanProcessHostContextTypeChecks(nullptr, webui_process_id,
+                                     {Feature::WEBUI_CONTEXT},
+                                     "webui page without extension passed");
+}
+
 // Tests that normal extension pages are considered privileged extension
 // processes.
 IN_PROC_BROWSER_TEST_F(ProcessMapBrowserTest,
@@ -234,6 +397,60 @@
       *extension2, GetActiveMainFrameProcessID()));
 }
 
+// Tests the type of contexts that can be hosted in regular extension processes.
+IN_PROC_BROWSER_TEST_F(ProcessMapBrowserTest,
+                       CanHostContextType_ExtensionPages) {
+  // Load up two extensions, each with the same permissions.
+  const Extension* extension1 =
+      AddExtensionWithHostPermission("test1", "*://example.com/*");
+  const Extension* extension2 =
+      AddExtensionWithHostPermission("test2", "*://example.com/*");
+  ASSERT_TRUE(extension1);
+  ASSERT_TRUE(extension2);
+
+  // Navigate to a page within the first extension. It should be a privileged
+  // page for that extension, but not the other.
+  OpenExtensionPage(*extension1);
+
+  int extension1_process_id =
+      GetActiveTab()->GetPrimaryMainFrame()->GetProcess()->GetID();
+
+  RunCanProcessHostContextTypeChecks(
+      extension1, extension1_process_id,
+      {Feature::CONTENT_SCRIPT_CONTEXT, Feature::USER_SCRIPT_CONTEXT,
+       Feature::BLESSED_EXTENSION_CONTEXT,
+       Feature::OFFSCREEN_EXTENSION_CONTEXT},
+      "extension1 page with extension1 passed");
+  RunCanProcessHostContextTypeChecks(
+      extension2, extension1_process_id,
+      {Feature::CONTENT_SCRIPT_CONTEXT, Feature::USER_SCRIPT_CONTEXT},
+      "extension1 page with extension2 passed");
+  RunCanProcessHostContextTypeChecks(
+      nullptr, extension1_process_id, {},
+      "extension1 page without extension passed");
+
+  // Inversion: Navigate to the page of the second extension. It should be a
+  // privileged page in the second, but not the first.
+  OpenExtensionPage(*extension2);
+
+  int extension2_process_id =
+      GetActiveTab()->GetPrimaryMainFrame()->GetProcess()->GetID();
+
+  RunCanProcessHostContextTypeChecks(
+      extension2, extension2_process_id,
+      {Feature::CONTENT_SCRIPT_CONTEXT, Feature::USER_SCRIPT_CONTEXT,
+       Feature::BLESSED_EXTENSION_CONTEXT,
+       Feature::OFFSCREEN_EXTENSION_CONTEXT},
+      "extension2 page with extension2 passed");
+  RunCanProcessHostContextTypeChecks(
+      extension1, extension2_process_id,
+      {Feature::CONTENT_SCRIPT_CONTEXT, Feature::USER_SCRIPT_CONTEXT},
+      "extension2 page with extension1 passed");
+  RunCanProcessHostContextTypeChecks(
+      nullptr, extension2_process_id, {},
+      "extension2 page without extension passed");
+}
+
 // Tests that a web page with injected content scripts is not considered a
 // privileged extension process.
 IN_PROC_BROWSER_TEST_F(
@@ -250,6 +467,28 @@
       *extension, GetActiveMainFrameProcessID()));
 }
 
+// Tests the type of contexts that can be hosted in a web page process that has
+// had a content script injected in it.
+IN_PROC_BROWSER_TEST_F(ProcessMapBrowserTest,
+                       CanHostContextType_WebPagesWithContentScripts) {
+  const Extension* extension =
+      AddExtensionWithContentScript("test", "*://example.com/*");
+  ASSERT_TRUE(extension);
+
+  // Navigate to a web page and wait for the content script to inject.
+  OpenDomainAndWaitForContentScript("example.com");
+  int page_process_id = GetActiveMainFrameProcessID();
+
+  RunCanProcessHostContextTypeChecks(
+      extension, page_process_id,
+      {Feature::CONTENT_SCRIPT_CONTEXT, Feature::USER_SCRIPT_CONTEXT},
+      "web page with extension passed");
+  RunCanProcessHostContextTypeChecks(
+      nullptr, page_process_id,
+      {Feature::WEB_PAGE_CONTEXT, Feature::WEBUI_UNTRUSTED_CONTEXT},
+      "web page without extension passed");
+}
+
 // Tests that sandboxed extension frames are considered privileged
 // extension processes, since they execute within the same process (even
 // though they don't have direct API access). This isn't a security bug
@@ -271,12 +510,112 @@
   EXPECT_FALSE(ExtensionFrameIsSandboxed(main_frame));
   EXPECT_TRUE(ExtensionFrameIsSandboxed(sandboxed_frame));
 
-  EXPECT_EQ(main_frame->GetProcess()->GetID(),
-            sandboxed_frame->GetProcess()->GetID());
+  int main_frame_process_id = main_frame->GetProcess()->GetID();
+  int sandboxed_frame_process_id = sandboxed_frame->GetProcess()->GetID();
+
+  EXPECT_EQ(main_frame_process_id, sandboxed_frame_process_id);
   EXPECT_TRUE(process_map()->IsPrivilegedExtensionProcess(
-      *extension, main_frame->GetProcess()->GetID()));
+      *extension, main_frame_process_id));
   EXPECT_TRUE(process_map()->IsPrivilegedExtensionProcess(
-      *extension, sandboxed_frame->GetProcess()->GetID()));
+      *extension, sandboxed_frame_process_id));
+}
+
+// Tests the type of contexts that can be hosted in extension processes with
+// a sandboxed process frame.
+IN_PROC_BROWSER_TEST_F(ProcessMapBrowserTest,
+                       CanHostContextType_SandboxedExtensionFrame) {
+  const Extension* extension = AddExtensionWithSandboxedFrame();
+  ASSERT_TRUE(extension);
+
+  OpenExtensionPageWithSandboxedFrame(*extension);
+
+  content::WebContents* web_contents = GetActiveTab();
+  content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame();
+  content::RenderFrameHost* sandboxed_frame =
+      content::ChildFrameAt(main_frame, 0);
+
+  EXPECT_FALSE(ExtensionFrameIsSandboxed(main_frame));
+  EXPECT_TRUE(ExtensionFrameIsSandboxed(sandboxed_frame));
+
+  int main_frame_process_id = main_frame->GetProcess()->GetID();
+  int sandboxed_frame_process_id = sandboxed_frame->GetProcess()->GetID();
+
+  EXPECT_EQ(main_frame_process_id, sandboxed_frame_process_id);
+
+  RunCanProcessHostContextTypeChecks(
+      extension, main_frame_process_id,
+      {Feature::CONTENT_SCRIPT_CONTEXT, Feature::USER_SCRIPT_CONTEXT,
+       Feature::BLESSED_EXTENSION_CONTEXT,
+       Feature::OFFSCREEN_EXTENSION_CONTEXT},
+      "main frame process with extension passed");
+  RunCanProcessHostContextTypeChecks(
+      nullptr, main_frame_process_id, {},
+      "main frame process without extension passed");
+
+  RunCanProcessHostContextTypeChecks(
+      extension, sandboxed_frame_process_id,
+      {Feature::CONTENT_SCRIPT_CONTEXT, Feature::USER_SCRIPT_CONTEXT,
+       Feature::BLESSED_EXTENSION_CONTEXT,
+       Feature::OFFSCREEN_EXTENSION_CONTEXT},
+      "sandboxed frame process with extension passed");
+  RunCanProcessHostContextTypeChecks(
+      nullptr, sandboxed_frame_process_id, {},
+      "sandboxed frame process without extension passed");
+}
+
+IN_PROC_BROWSER_TEST_F(ProcessMapBrowserTest,
+                       IsPrivilegedExtensionProcess_WebViews) {
+  const Extension* extension = AddExtensionWithWebViewAndOpen();
+  ASSERT_TRUE(extension);
+
+  content::WebContents* embedder = GetAppWindowContents();
+  ASSERT_TRUE(embedder);
+
+  content::WebContents* webview = GetWebViewFromEmbedder(embedder);
+  ASSERT_TRUE(webview);
+
+  // The embedder (the app window) should be a privileged extension process,
+  // but the webview should not.
+  EXPECT_TRUE(process_map()->IsPrivilegedExtensionProcess(
+      *extension, embedder->GetPrimaryMainFrame()->GetProcess()->GetID()));
+  EXPECT_FALSE(process_map()->IsPrivilegedExtensionProcess(
+      *extension, webview->GetPrimaryMainFrame()->GetProcess()->GetID()));
+}
+
+IN_PROC_BROWSER_TEST_F(ProcessMapBrowserTest, CanHostContextType_WebViews) {
+  const Extension* extension = AddExtensionWithWebViewAndOpen();
+  ASSERT_TRUE(extension);
+
+  content::WebContents* embedder = GetAppWindowContents();
+  ASSERT_TRUE(embedder);
+
+  content::WebContents* webview = GetWebViewFromEmbedder(embedder);
+  ASSERT_TRUE(webview);
+
+  // The embedder (the app window) can host any kind of extension context
+  // except an unblessed extension context (which is only available to
+  // webviews).
+  RunCanProcessHostContextTypeChecks(
+      extension, embedder->GetPrimaryMainFrame()->GetProcess()->GetID(),
+      {Feature::CONTENT_SCRIPT_CONTEXT, Feature::USER_SCRIPT_CONTEXT,
+       Feature::BLESSED_EXTENSION_CONTEXT,
+       Feature::OFFSCREEN_EXTENSION_CONTEXT},
+      "embedder process");
+
+  // The webview can only host content scripts, user scripts, and
+  // unblessed extension contexts (accessible resources).
+  RunCanProcessHostContextTypeChecks(
+      extension, webview->GetPrimaryMainFrame()->GetProcess()->GetID(),
+      {Feature::CONTENT_SCRIPT_CONTEXT, Feature::USER_SCRIPT_CONTEXT,
+       Feature::UNBLESSED_EXTENSION_CONTEXT},
+      "webview process with extension passed");
+
+  // If the extension isn't associated with the call, the webview could only
+  // possibly contain web pages and untrusted web ui.
+  RunCanProcessHostContextTypeChecks(
+      nullptr, webview->GetPrimaryMainFrame()->GetProcess()->GetID(),
+      {Feature::WEB_PAGE_CONTEXT, Feature::WEBUI_UNTRUSTED_CONTEXT},
+      "webview process without extension passed");
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 6dbf8c04..2e09030 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -760,11 +760,6 @@
     "expiry_milestone": 115
   },
   {
-    "name": "battery-saver-mode-available",
-    "owners": [ "chrome-performance-ui-team@google.com" ],
-    "expiry_milestone": 115
-  },
-  {
     "name": "binding-manager-connection-limit",
     "owners": ["ckitagawa", "yfriedman"],
     "expiry_milestone": 115
@@ -2861,11 +2856,6 @@
     "expiry_milestone": -1
   },
   {
-    "name": "enable-long-press-surrounding-text",
-    "owners": [ "erahmaoui@google.com", "djean@google.com", "bling-flags@google.com" ],
-    "expiry_milestone": 116
-  },
-  {
     "name": "enable-machine-learning-model-loader-web-platform-api",
     "owners": [ "honglinyu" ],
     "expiry_milestone": 130
@@ -3763,11 +3753,6 @@
     "expiry_milestone": 112
   },
   {
-    "name": "experience-kit-maps",
-    "owners": [ "djean@google.com", "erahmaoui@google.com", "bling-flags@google.com" ],
-    "expiry_milestone": 116
-  },
-  {
     "name": "experimental-web-app-profile-isolation",
     "owners": [ "lxj@google.com", "glenrob@chromium.org", "chromeos-web-apps-platform-syd@google.com"],
     "expiry_milestone": 120
@@ -4390,11 +4375,6 @@
     "expiry_milestone": 118
   },
   {
-    "name": "high-efficiency-mode-available",
-    "owners": [ "chrome-performance-ui-team@google.com" ],
-    "expiry_milestone": 115
-  },
-  {
     "name": "highlight-managed-pref-disclaimer-android",
     "owners": [ "ftirelo" ],
     "expiry_milestone": 115
@@ -5049,6 +5029,11 @@
     "expiry_milestone": -1
   },
   {
+    "name": "memory-saver-savings-reporting-improvements",
+    "owners": [ "chrome-performance-ui-team@google.com" ],
+    "expiry_milestone": 117
+  },
+  {
     "name": "messages-for-android-ads-blocked",
     "owners": [ "pavely", "aishwaryarj" ],
     "expiry_milestone": 99
@@ -7229,6 +7214,11 @@
     "expiry_milestone": 120
   },
   {
+    "name": "tab-grid-new-transitions",
+    "owners": [ "pakzhygitov", "bling-flags@google.com" ],
+    "expiry_milestone": 120
+  },
+  {
     "name": "tab-grid-recency-sort",
     "owners": [ "gambard", "bling-flags@google.com" ],
     "expiry_milestone": 120
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index d60ec63..8fd58d0 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -4503,12 +4503,6 @@
     "Allows global media controls to control when a Cast session is started "
     "or stopped instead of relying on the Cast dialog.";
 
-extern const char kHighEfficiencyModeAvailableName[] =
-    "Enable the high efficiency mode feature in the settings";
-extern const char kHighEfficiencyModeAvailableDescription[] =
-    "When enabled, shows the performance section in the performance settings "
-    "page";
-
 extern const char kHeuristicMemorySaverName[] =
     "Enable the heuristics-based policy for Memory Saver Mode.";
 extern const char kHeuristicMemorySaverDescription[] =
@@ -4516,6 +4510,12 @@
     "discarding a tab rather than doing it after a fixed amount of time in the "
     "background.";
 
+extern const char kHighEfficiencySavingsReportingImprovementsName[] =
+    "Enable improvements to how memory savings are reported.";
+extern const char kHighEfficiencySavingsReportingImprovementsDescription[] =
+    "When enabled, the Memory Saver page action chip and dialog will be used "
+    "to highlight memory savings.";
+
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
 extern const char kIOSPromoPasswordBubbleName[] =
     "Contextual Chrome for iOS promo in the password save/update bubble.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index afbb09ba..b9f6baa 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -2577,12 +2577,12 @@
 extern const char kGlobalMediaControlsCastStartStopName[];
 extern const char kGlobalMediaControlsCastStartStopDescription[];
 
-extern const char kHighEfficiencyModeAvailableName[];
-extern const char kHighEfficiencyModeAvailableDescription[];
-
 extern const char kHeuristicMemorySaverName[];
 extern const char kHeuristicMemorySaverDescription[];
 
+extern const char kHighEfficiencySavingsReportingImprovementsName[];
+extern const char kHighEfficiencySavingsReportingImprovementsDescription[];
+
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
 extern const char kIOSPromoPasswordBubbleName[];
 extern const char kIOSPromoPasswordBubbleDecription[];
diff --git a/chrome/browser/net/local_network_access_browsertest.cc b/chrome/browser/net/local_network_access_browsertest.cc
index 8b0ae756..e4db075 100644
--- a/chrome/browser/net/local_network_access_browsertest.cc
+++ b/chrome/browser/net/local_network_access_browsertest.cc
@@ -178,7 +178,6 @@
       WebFeature::kAddressSpacePublicNonSecureContextNavigatedToPrivate,
       WebFeature::kAddressSpaceUnknownSecureContextNavigatedToPrivate,
       WebFeature::kAddressSpaceUnknownNonSecureContextNavigatedToPrivate,
-      WebFeature::kPrivateNetworkAccessIgnoredPreflightError,
       WebFeature::kPrivateNetworkAccessFetchedWorkerScript,
       WebFeature::kPrivateNetworkAccessFetchedSubFrame,
       WebFeature::kPrivateNetworkAccessFetchedTopFrame,
@@ -423,7 +422,6 @@
       AllZeroFeatureCounts(AllAddressSpaceFeatures()),
       {
           {WebFeature::kAddressSpacePublicSecureContextEmbeddedLocal, 1},
-          {WebFeature::kPrivateNetworkAccessIgnoredPreflightError, 1},
           {WebFeature::kPrivateNetworkAccessPreflightWarning, 1},
       }));
 }
@@ -452,7 +450,6 @@
       AllZeroFeatureCounts(AllAddressSpaceFeatures()),
       {
           {WebFeature::kAddressSpacePublicSecureContextEmbeddedLocal, 1},
-          {WebFeature::kPrivateNetworkAccessIgnoredPreflightError, 1},
           {WebFeature::kPrivateNetworkAccessPreflightWarning, 1},
       }));
 }
@@ -965,7 +962,6 @@
       AllZeroFeatureCounts(AllAddressSpaceFeatures()),
       {
           {WebFeature::kPrivateNetworkAccessFetchedWorkerScript, 1},
-          {WebFeature::kPrivateNetworkAccessIgnoredPreflightError, 1},
           {WebFeature::kPrivateNetworkAccessPreflightWarning, 1},
       }));
 }
@@ -1103,7 +1099,6 @@
       AllZeroFeatureCounts(AllAddressSpaceFeatures()),
       {
           {WebFeature::kPrivateNetworkAccessFetchedWorkerScript, 1},
-          {WebFeature::kPrivateNetworkAccessIgnoredPreflightError, 1},
           {WebFeature::kPrivateNetworkAccessPreflightWarning, 1},
       }));
 }
@@ -1239,7 +1234,6 @@
       AllZeroFeatureCounts(AllAddressSpaceFeatures()),
       {
           {WebFeature::kPrivateNetworkAccessWithinWorker, 1},
-          {WebFeature::kPrivateNetworkAccessIgnoredPreflightError, 1},
           {WebFeature::kPrivateNetworkAccessPreflightWarning, 1},
       }));
 }
@@ -1282,9 +1276,6 @@
       AllZeroFeatureCounts(AllAddressSpaceFeatures()),
       {
           {WebFeature::kPrivateNetworkAccessWithinWorker, 1},
-          // `kPrivateNetworkAccessIgnoredPreflightError` is not recorded.
-          // TODO(https://crbug.com/1428688): Consider recording the usecounter
-          // correctly.
           {WebFeature::kPrivateNetworkAccessPreflightWarning, 1},
       }));
 }
diff --git a/chrome/browser/password_check/android/password_check_manager.cc b/chrome/browser/password_check/android/password_check_manager.cc
index d91d023..6e6e9f6 100644
--- a/chrome/browser/password_check/android/password_check_manager.cc
+++ b/chrome/browser/password_check/android/password_check_manager.cc
@@ -24,18 +24,7 @@
 #include "components/url_formatter/url_formatter.h"
 #include "ui/base/l10n/l10n_util.h"
 
-namespace {
-
 using password_manager::PasswordForm;
-
-std::u16string GetDisplayUsername(const std::u16string& username) {
-  return username.empty()
-             ? l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN)
-             : username;
-}
-
-}  // namespace
-
 using PasswordCheckUIStatus = password_manager::PasswordCheckUIStatus;
 using State = password_manager::BulkLeakCheckService::State;
 using SyncState = password_manager::SyncState;
@@ -284,7 +273,8 @@
         password_manager::CreateChangePasswordUrl(credential_facet.url).spec();
   }
 
-  ui_credential.display_username = GetDisplayUsername(credential.username);
+  ui_credential.display_username =
+      password_manager::ToUsernameString(credential.username);
 
   credential_facets.push_back(std::move(credential_facet));
   ui_credential.facets = std::move(credential_facets);
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordStoreAndroidBackendFactory.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordStoreAndroidBackendFactory.java
index b0ecd449..af4e1ca5 100644
--- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordStoreAndroidBackendFactory.java
+++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordStoreAndroidBackendFactory.java
@@ -23,8 +23,6 @@
      * @return The shared {@link PasswordStoreAndroidBackendFactory} instance.
      */
     public static PasswordStoreAndroidBackendFactory getInstance() {
-        // TODO(crbug.com/1394715): assert running on background thread once CanCreateBackend is
-        // updated to use non-UI thread.
         if (sInstance == null) sInstance = new PasswordStoreAndroidBackendFactoryImpl();
         return sInstance;
     }
diff --git a/chrome/browser/password_manager/android/password_store_android_backend_bridge_helper_impl.cc b/chrome/browser/password_manager/android/password_store_android_backend_bridge_helper_impl.cc
index 07848e9..695bdf44 100644
--- a/chrome/browser/password_manager/android/password_store_android_backend_bridge_helper_impl.cc
+++ b/chrome/browser/password_manager/android/password_store_android_backend_bridge_helper_impl.cc
@@ -30,8 +30,6 @@
 }
 
 bool PasswordStoreAndroidBackendBridgeHelper::CanCreateBackend() {
-  // TODO(crbug.com/1394715): Either move this call to the background thread or
-  // use cached GMS Core version from `BuildInfo.gmsVersionCode`.
   return PasswordStoreAndroidBackendDispatcherBridge::CanCreateBackend();
 }
 
diff --git a/chrome/browser/password_manager/chrome_webauthn_credentials_delegate_unittest.cc b/chrome/browser/password_manager/chrome_webauthn_credentials_delegate_unittest.cc
index f3434b3..defa2a7 100644
--- a/chrome/browser/password_manager/chrome_webauthn_credentials_delegate_unittest.cc
+++ b/chrome/browser/password_manager/chrome_webauthn_credentials_delegate_unittest.cc
@@ -21,6 +21,7 @@
 #include "components/strings/grit/components_strings.h"
 #include "content/public/test/web_contents_tester.h"
 #include "device/fido/discoverable_credential_metadata.h"
+#include "device/fido/fido_parsing_utils.h"
 #include "device/fido/public_key_credential_user_entity.h"
 #include "device/fido/test_callback_receiver.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -42,51 +43,19 @@
 
 namespace {
 
-constexpr uint8_t kUserId1[] = {'1', '2', '3', '4'};
-constexpr uint8_t kUserId2[] = {'5', '6', '7', '8'};
+constexpr uint8_t kUserId[] = {'1', '2', '3', '4'};
 constexpr char kUserName1[] = "John.Doe@example.com";
 constexpr char kUserName2[] = "Jane.Doe@example.com";
-constexpr char kDisplayName1[] = "John Doe";
-constexpr char kDisplayName2[] = "Jane Doe";
-constexpr char kCredId1[] = {'a', 'b', 'c', 'd'};
-constexpr char kCredId2[] = {'e', 'f', 'g', 'h'};
+constexpr uint8_t kCredId1[] = {'a', 'b', 'c', 'd'};
+constexpr uint8_t kCredId2[] = {'e', 'f', 'g', 'h'};
 constexpr char kRpId[] = "example.com";
 
-std::vector<uint8_t> UserId1() {
-  return std::vector<uint8_t>(std::begin(kUserId1), std::end(kUserId1));
-}
-std::vector<uint8_t> UserId2() {
-  return std::vector<uint8_t>(std::begin(kUserId2), std::end(kUserId2));
-}
-std::string UserName1() {
-  return std::string(kUserName1);
-}
-std::string UserName2() {
-  return std::string(kUserName2);
-}
-std::string DisplayName1() {
-  return std::string(kDisplayName1);
-}
-std::string DisplayName2() {
-  return std::string(kDisplayName2);
-}
-std::u16string DeviceName1() {
-  return u"Pixel 3a";
-}
-std::u16string DeviceName2() {
-  return u"Nexus 5";
-}
-std::vector<uint8_t> CredId1() {
-  return std::vector<uint8_t>(std::begin(kCredId1), std::end(kCredId1));
-}
-std::vector<uint8_t> CredId2() {
-  return std::vector<uint8_t>(std::begin(kCredId2), std::end(kCredId2));
-}
-std::string BackendId1() {
-  return base::Base64Encode(CredId1());
-}
-std::string BackendId2() {
-  return base::Base64Encode(CredId2());
+PasskeyCredential CreatePasskey(std::vector<uint8_t> cred_id,
+                                std::string username) {
+  return PasskeyCredential(PasskeyCredential::Source::kAndroidPhone,
+                           std::string(kRpId), std::move(cred_id),
+                           device::fido_parsing_utils::Materialize(kUserId),
+                           std::move(username));
 }
 
 }  // namespace
@@ -172,13 +141,11 @@
 // Testing retrieving passkeys when there are 2 public key credentials
 // present.
 TEST_F(ChromeWebAuthnCredentialsDelegateTest, RetrieveCredentials) {
-  std::vector<PasskeyCredential> credentials;
-  credentials.emplace_back(PasskeyCredential::Username(UserName1()),
-                           PasskeyCredential::DeviceName(DeviceName1()),
-                           PasskeyCredential::BackendId(BackendId1()));
-  credentials.emplace_back(PasskeyCredential::Username(UserName2()),
-                           PasskeyCredential::DeviceName(DeviceName2()),
-                           PasskeyCredential::BackendId(BackendId2()));
+  std::vector<PasskeyCredential> credentials{
+      CreatePasskey(device::fido_parsing_utils::Materialize(kCredId1),
+                    kUserName1),
+      CreatePasskey(device::fido_parsing_utils::Materialize(kCredId2),
+                    kUserName2)};
   credentials_delegate_->OnCredentialsReceived(credentials);
 
   auto passkeys = credentials_delegate_->GetPasskeys();
@@ -189,13 +156,11 @@
 // Testing retrieving suggestions when the credentials are not received until
 // afterward.
 TEST_F(ChromeWebAuthnCredentialsDelegateTest, RetrieveCredentialsDelayed) {
-  std::vector<PasskeyCredential> credentials;
-  credentials.emplace_back(PasskeyCredential::Username(UserName1()),
-                           PasskeyCredential::DeviceName(DeviceName1()),
-                           PasskeyCredential::BackendId(BackendId1()));
-  credentials.emplace_back(PasskeyCredential::Username(UserName2()),
-                           PasskeyCredential::DeviceName(DeviceName2()),
-                           PasskeyCredential::BackendId(BackendId2()));
+  std::vector<PasskeyCredential> credentials{
+      CreatePasskey(device::fido_parsing_utils::Materialize(kCredId1),
+                    kUserName1),
+      CreatePasskey(device::fido_parsing_utils::Materialize(kCredId2),
+                    kUserName2)};
   credentials_delegate_->OnCredentialsReceived(credentials);
 
   auto passkeys = credentials_delegate_->GetPasskeys();
@@ -214,47 +179,47 @@
 // Testing selection of a credential.
 TEST_F(ChromeWebAuthnCredentialsDelegateTest, SelectCredential) {
   std::vector<device::DiscoverableCredentialMetadata> users;
-  users.emplace_back(device::AuthenticatorType::kOther, kRpId, CredId1(),
+  users.emplace_back(device::AuthenticatorType::kOther, kRpId,
+                     device::fido_parsing_utils::Materialize(kCredId1),
                      device::PublicKeyCredentialUserEntity(
-                         UserId1(), UserName1(), DisplayName1()));
-  users.emplace_back(device::AuthenticatorType::kOther, kRpId, CredId2(),
+                         device::fido_parsing_utils::Materialize(kUserId),
+                         kUserName1, /*display_name=*/absl::nullopt));
+  users.emplace_back(device::AuthenticatorType::kOther, kRpId,
+                     device::fido_parsing_utils::Materialize(kCredId2),
                      device::PublicKeyCredentialUserEntity(
-                         UserId2(), UserName2(), DisplayName2()));
+                         device::fido_parsing_utils::Materialize(kUserId),
+                         kUserName2, /*display_name=*/absl::nullopt));
 
   SetCredList(users);
 
-  std::vector<PasskeyCredential> credentials;
-  credentials.emplace_back(PasskeyCredential::Username(UserName1()),
-                           PasskeyCredential::DeviceName(DeviceName1()),
-                           PasskeyCredential::BackendId(BackendId1()));
-  credentials.emplace_back(PasskeyCredential::Username(UserName2()),
-                           PasskeyCredential::DeviceName(DeviceName2()),
-                           PasskeyCredential::BackendId(BackendId2()));
+  std::vector<PasskeyCredential> credentials{
+      CreatePasskey(device::fido_parsing_utils::Materialize(kCredId1),
+                    kUserName1),
+      CreatePasskey(device::fido_parsing_utils::Materialize(kCredId2),
+                    kUserName2)};
   credentials_delegate_->OnCredentialsReceived(credentials);
 
 #if !BUILDFLAG(IS_ANDROID)
   base::RunLoop run_loop;
   dialog_model()->SetAccountPreselectedCallback(
       base::BindLambdaForTesting([&](std::vector<uint8_t> credential_id) {
-        EXPECT_EQ(credential_id, CredId2());
+        EXPECT_THAT(credential_id, testing::ElementsAreArray(kCredId2));
         run_loop.Quit();
       }));
 #endif
 
-  credentials_delegate_->SelectPasskey(base::Base64Encode(CredId2()));
+  credentials_delegate_->SelectPasskey(base::Base64Encode(kCredId2));
 
 #if BUILDFLAG(IS_ANDROID)
   auto credential_id = GetSelectedId();
-  EXPECT_EQ(credential_id, CredId2());
+  EXPECT_THAT(*credential_id, testing::ElementsAreArray(kCredId2));
 #endif
 }
 
 // Test aborting a request.
 TEST_F(ChromeWebAuthnCredentialsDelegateTest, AbortRequest) {
-  std::vector<PasskeyCredential> credentials;
-  credentials.emplace_back(PasskeyCredential::Username(UserName1()),
-                           PasskeyCredential::DeviceName(DeviceName1()),
-                           PasskeyCredential::BackendId(BackendId1()));
+  std::vector<PasskeyCredential> credentials{CreatePasskey(
+      device::fido_parsing_utils::Materialize(kCredId1), kUserName1)};
   credentials_delegate_->OnCredentialsReceived(credentials);
   credentials_delegate_->NotifyWebAuthnRequestAborted();
   EXPECT_FALSE(credentials_delegate_->GetPasskeys());
diff --git a/chrome/browser/performance_manager/metrics/metrics_provider.cc b/chrome/browser/performance_manager/metrics/metrics_provider.cc
index 5764f04..5bc3240c 100644
--- a/chrome/browser/performance_manager/metrics/metrics_provider.cc
+++ b/chrome/browser/performance_manager/metrics/metrics_provider.cc
@@ -5,12 +5,15 @@
 #include "chrome/browser/performance_manager/metrics/metrics_provider.h"
 
 #include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/process/process_metrics.h"
 #include "base/system/sys_info.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h"
 #include "components/performance_manager/public/user_tuning/prefs.h"
 #include "components/prefs/pref_service.h"
+#include "ui/accessibility/ax_mode.h"
+#include "ui/accessibility/platform/ax_platform_node.h"
 
 namespace performance_manager {
 
@@ -23,8 +26,45 @@
 #if BUILDFLAG(IS_MAC)
 uint64_t kKilobytesPerMb = 1024;
 #endif
+
+ui::AXMode::ModeFlagHistogramValue ModeFlagsToEnum(uint32_t mode_flags) {
+  switch (mode_flags) {
+    case ui::AXMode::kNativeAPIs:
+      return ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_NATIVE_APIS;
+    case ui::AXMode::kWebContents:
+      return ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_WEB_CONTENTS;
+    case ui::AXMode::kInlineTextBoxes:
+      return ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_INLINE_TEXT_BOXES;
+    case ui::AXMode::kScreenReader:
+      return ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_SCREEN_READER;
+    case ui::AXMode::kHTML:
+      return ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_HTML;
+    case ui::AXMode::kHTMLMetadata:
+      return ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_HTML_METADATA;
+    case ui::AXMode::kLabelImages:
+      return ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_LABEL_IMAGES;
+    case ui::AXMode::kPDF:
+      return ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_PDF;
+    case ui::AXMode::kPDFOcr:
+      return ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_PDF_OCR;
+    default:
+      return ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_MAX;
+  }
 }
 
+void MaybeRecordAccessibilityModeFlags(const ui::AXMode& mode,
+                                       uint32_t mode_flags) {
+  if (mode.has_mode(mode_flags)) {
+    ui::AXMode::ModeFlagHistogramValue mode_enum = ModeFlagsToEnum(mode_flags);
+    if (mode_enum != ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_MAX) {
+      UMA_HISTOGRAM_ENUMERATION(
+          "PerformanceManager.Experimental.AccessibilityModeFlag", mode_enum,
+          ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_MAX);
+    }
+  }
+}
+}  // namespace
+
 // static
 MetricsProvider* MetricsProvider::GetInstance() {
   DCHECK(g_metrics_provider);
@@ -54,6 +94,26 @@
   current_mode_ = ComputeCurrentMode();
 }
 
+void MetricsProvider::RecordA11yFlags() {
+  ui::AXMode mode = ui::AXPlatformNode::GetAccessibilityMode();
+  bool is_mode_on = !mode.is_mode_off();
+
+  UMA_HISTOGRAM_BOOLEAN(
+      "PerformanceManager.Experimental.HasAccessibilityModeFlag", is_mode_on);
+
+  if (is_mode_on) {
+    MaybeRecordAccessibilityModeFlags(mode, ui::AXMode::kNativeAPIs);
+    MaybeRecordAccessibilityModeFlags(mode, ui::AXMode::kWebContents);
+    MaybeRecordAccessibilityModeFlags(mode, ui::AXMode::kInlineTextBoxes);
+    MaybeRecordAccessibilityModeFlags(mode, ui::AXMode::kScreenReader);
+    MaybeRecordAccessibilityModeFlags(mode, ui::AXMode::kHTML);
+    MaybeRecordAccessibilityModeFlags(mode, ui::AXMode::kHTMLMetadata);
+    MaybeRecordAccessibilityModeFlags(mode, ui::AXMode::kLabelImages);
+    MaybeRecordAccessibilityModeFlags(mode, ui::AXMode::kPDF);
+    MaybeRecordAccessibilityModeFlags(mode, ui::AXMode::kPDFOcr);
+  }
+}
+
 void MetricsProvider::ProvideCurrentSessionData(
     metrics::ChromeUserMetricsExtension* uma_proto) {
   // It's valid for this to be called when `initialized_` is false if the finch
@@ -67,6 +127,8 @@
   // that this mode is what is adequately reported at the next report, unless it
   // changes in the meantime.
   current_mode_ = ComputeCurrentMode();
+
+  RecordA11yFlags();
 }
 
 MetricsProvider::MetricsProvider(PrefService* local_state)
diff --git a/chrome/browser/performance_manager/metrics/metrics_provider.h b/chrome/browser/performance_manager/metrics/metrics_provider.h
index 1cd8a98..a1e881ee 100644
--- a/chrome/browser/performance_manager/metrics/metrics_provider.h
+++ b/chrome/browser/performance_manager/metrics/metrics_provider.h
@@ -62,6 +62,8 @@
 
   void RecordAvailableMemoryMetrics();
 
+  void RecordA11yFlags();
+
   PrefChangeRegistrar pref_change_registrar_;
   const raw_ptr<PrefService> local_state_;
   EfficiencyMode current_mode_ = EfficiencyMode::kNormal;
diff --git a/chrome/browser/performance_manager/metrics/metrics_provider_unittest.cc b/chrome/browser/performance_manager/metrics/metrics_provider_unittest.cc
index fc56232..a605784 100644
--- a/chrome/browser/performance_manager/metrics/metrics_provider_unittest.cc
+++ b/chrome/browser/performance_manager/metrics/metrics_provider_unittest.cc
@@ -14,8 +14,21 @@
 #include "components/performance_manager/public/user_tuning/prefs.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/platform/ax_platform_node.h"
 
-#include "base/logging.h"
+class ScopedAXModeSetter {
+ public:
+  explicit ScopedAXModeSetter(ui::AXMode new_mode) {
+    previous_mode_ = ui::AXPlatformNode::GetAccessibilityMode();
+    ui::AXPlatformNode::SetAXMode(new_mode);
+  }
+  ~ScopedAXModeSetter() {
+    ui::AXPlatformNode::SetAXMode(previous_mode_.flags());
+  }
+
+ private:
+  ui::AXMode previous_mode_;
+};
 
 class FakeHighEfficiencyModeToggleDelegate
     : public performance_manager::user_tuning::UserPerformanceTuningManager::
@@ -220,3 +233,45 @@
         performance_manager::MetricsProvider::EfficiencyMode::kBatterySaver);
   }
 }
+
+TEST_F(PerformanceManagerMetricsProviderTest, A11yModeOff) {
+  InitProvider();
+
+  base::HistogramTester tester;
+  provider()->ProvideCurrentSessionData(nullptr);
+  tester.ExpectUniqueSample(
+      "PerformanceManager.Experimental.HasAccessibilityModeFlag", false, 1);
+}
+
+TEST_F(PerformanceManagerMetricsProviderTest, A11yModeOn) {
+  InitProvider();
+
+  ScopedAXModeSetter scoped_setter(ui::AXMode::kWebContents);
+
+  base::HistogramTester tester;
+  provider()->ProvideCurrentSessionData(nullptr);
+  tester.ExpectUniqueSample(
+      "PerformanceManager.Experimental.HasAccessibilityModeFlag", true, 1);
+  tester.ExpectUniqueSample(
+      "PerformanceManager.Experimental.AccessibilityModeFlag",
+      ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_WEB_CONTENTS, 1);
+}
+
+TEST_F(PerformanceManagerMetricsProviderTest, MultipleA11yModeFlags) {
+  InitProvider();
+
+  ScopedAXModeSetter scoped_setter(ui::AXMode::kWebContents |
+                                   ui::AXMode::kHTML);
+
+  base::HistogramTester tester;
+  provider()->ProvideCurrentSessionData(nullptr);
+  tester.ExpectUniqueSample(
+      "PerformanceManager.Experimental.HasAccessibilityModeFlag", true, 1);
+  // Each mode flag gets recorded in its own bucket
+  tester.ExpectBucketCount(
+      "PerformanceManager.Experimental.AccessibilityModeFlag",
+      ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_WEB_CONTENTS, 1);
+  tester.ExpectBucketCount(
+      "PerformanceManager.Experimental.AccessibilityModeFlag",
+      ui::AXMode::ModeFlagHistogramValue::UMA_AX_MODE_HTML, 1);
+}
diff --git a/chrome/browser/printing/printer_query_oop.h b/chrome/browser/printing/printer_query_oop.h
index 37049884..5b276c43 100644
--- a/chrome/browser/printing/printer_query_oop.h
+++ b/chrome/browser/printing/printer_query_oop.h
@@ -52,9 +52,10 @@
       std::unique_ptr<PrintSettings> new_settings,
       mojom::ResultCode result);
 #endif
-  void OnDidUpdatePrintSettings(const std::string& device_name,
-                                SettingsCallback callback,
-                                mojom::PrintSettingsResultPtr print_settings);
+  virtual void OnDidUpdatePrintSettings(
+      const std::string& device_name,
+      SettingsCallback callback,
+      mojom::PrintSettingsResultPtr print_settings);
 #if BUILDFLAG(IS_WIN)
   void OnDidGetPaperPrintableArea(PrintSettings* print_settings,
                                   OnDidUpdatePrintableAreaCallback callback,
diff --git a/chrome/browser/printing/system_access_process_print_browsertest.cc b/chrome/browser/printing/system_access_process_print_browsertest.cc
index 6e8c5ff2..83b5599 100644
--- a/chrome/browser/printing/system_access_process_print_browsertest.cc
+++ b/chrome/browser/printing/system_access_process_print_browsertest.cc
@@ -80,6 +80,8 @@
 using OnDidAskUserForSettingsCallback =
     base::RepeatingCallback<void(mojom::ResultCode result)>;
 #endif
+using OnDidUpdatePrintSettingsCallback =
+    base::RepeatingCallback<void(mojom::ResultCode result)>;
 using OnDidStartPrintingCallback =
     base::RepeatingCallback<void(mojom::ResultCode result)>;
 #if BUILDFLAG(IS_WIN)
@@ -143,6 +145,7 @@
 #if BUILDFLAG(ENABLE_OOP_BASIC_PRINT_DIALOG)
     OnDidAskUserForSettingsCallback did_ask_user_for_settings_callback;
 #endif
+    OnDidUpdatePrintSettingsCallback did_update_print_settings_callback;
     OnDidStartPrintingCallback did_start_printing_callback;
 #if BUILDFLAG(IS_WIN)
     OnDidRenderPrintedPageCallback did_render_printed_page_callback;
@@ -254,6 +257,20 @@
   }
 #endif  // BUILDFLAG(ENABLE_OOP_BASIC_PRINT_DIALOG)
 
+  void OnDidUpdatePrintSettings(
+      const std::string& device_name,
+      SettingsCallback callback,
+      mojom::PrintSettingsResultPtr print_settings) override {
+    DVLOG(1) << "Observed: update print settings";
+    mojom::ResultCode result = print_settings->is_result_code()
+                                   ? print_settings->get_result_code()
+                                   : mojom::ResultCode::kSuccess;
+    callbacks_->error_check_callback.Run(result);
+    PrinterQueryOop::OnDidUpdatePrintSettings(device_name, std::move(callback),
+                                              std::move(print_settings));
+    callbacks_->did_update_print_settings_callback.Run(result);
+  }
+
   std::unique_ptr<PrintJobWorkerOop> CreatePrintJobWorker(
       PrintJob* print_job) override {
     return std::make_unique<TestPrintJobWorkerOop>(
@@ -307,6 +324,10 @@
               &SystemAccessProcessPrintBrowserTestBase::OnDidAskUserForSettings,
               base::Unretained(this));
 #endif
+      test_print_job_worker_oop_callbacks_
+          .did_update_print_settings_callback = base::BindRepeating(
+          &SystemAccessProcessPrintBrowserTestBase::OnDidUpdatePrintSettings,
+          base::Unretained(this));
       test_print_job_worker_oop_callbacks_.did_start_printing_callback =
           base::BindRepeating(
               &SystemAccessProcessPrintBrowserTestBase::OnDidStartPrinting,
@@ -585,6 +606,10 @@
   }
 #endif
 
+  mojom::ResultCode update_print_settings_result() const {
+    return update_print_settings_result_;
+  }
+
   mojom::ResultCode start_printing_result() const {
     return start_printing_result_;
   }
@@ -671,6 +696,11 @@
   }
 #endif
 
+  void OnDidUpdatePrintSettings(mojom::ResultCode result) {
+    update_print_settings_result_ = result;
+    CheckForQuit();
+  }
+
   void OnDidStartPrinting(mojom::ResultCode result) {
     start_printing_result_ = result;
     CheckForQuit();
@@ -743,6 +773,7 @@
 #if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG)
   mojom::ResultCode ask_user_for_settings_result_ = mojom::ResultCode::kFailed;
 #endif
+  mojom::ResultCode update_print_settings_result_ = mojom::ResultCode::kFailed;
   mojom::ResultCode start_printing_result_ = mojom::ResultCode::kFailed;
 #if BUILDFLAG(IS_WIN)
   mojom::ResultCode render_printed_page_result_ = mojom::ResultCode::kFailed;
@@ -905,12 +936,13 @@
   SetUpPrintViewManager(web_contents);
 
   // The expected events for this are:
-  // 1.  A print job is started.
-  // 2.  Rendering for 1 page of document of content.
-  // 3.  Completes with document done.
-  // 4.  Wait for the one print job to be destroyed, to ensure printing
+  // 1.  Update print settings.
+  // 2.  A print job is started.
+  // 3.  Rendering for 1 page of document of content.
+  // 4.  Completes with document done.
+  // 5.  Wait for the one print job to be destroyed, to ensure printing
   //    finished cleanly before completing the test.
-  SetNumExpectedMessages(/*num=*/4);
+  SetNumExpectedMessages(/*num=*/5);
   PrintAfterPreviewIsReadyAndLoaded();
 
   EXPECT_EQ(start_printing_result(), mojom::ResultCode::kSuccess);
@@ -962,24 +994,26 @@
 #if BUILDFLAG(IS_WIN)
   // Windows GDI results in a callback for each rendered page.
   // The expected events for this are:
-  // 1.  A print job is started.
-  // 2.  First page is rendered.
-  // 3.  Second page is rendered.
-  // 4.  Third page is rendered.
-  // 5.  Completes with document done.
-  // 6.  Wait for the one print job to be destroyed, to ensure printing
+  // 1.  Update print settings.
+  // 2.  A print job is started.
+  // 3.  First page is rendered.
+  // 4.  Second page is rendered.
+  // 5.  Third page is rendered.
+  // 6.  Completes with document done.
+  // 7.  Wait for the one print job to be destroyed, to ensure printing
   //     finished cleanly before completing the test.
   // TODO(crbug.com/1008222)  Include Windows coverage of
   // RenderPrintedDocument() once XPS print pipeline is added.
-  SetNumExpectedMessages(/*num=*/6);
+  SetNumExpectedMessages(/*num=*/7);
 #else
   // The expected events for this are:
-  // 1.  A print job is started.
-  // 2.  Document is rendered.
-  // 3.  Completes with document done.
-  // 4.  Wait for the one print job to be destroyed, to ensure printing
+  // 1.  Update print settings.
+  // 2.  A print job is started.
+  // 3.  Document is rendered.
+  // 4.  Completes with document done.
+  // 5.  Wait for the one print job to be destroyed, to ensure printing
   //     finished cleanly before completing the test.
-  SetNumExpectedMessages(/*num=*/4);
+  SetNumExpectedMessages(/*num=*/5);
 #endif
   PrintAfterPreviewIsReadyAndLoaded();
 
@@ -1015,13 +1049,14 @@
   // No attempt to retry is made if a job has a shared memory error when trying
   // to spool a page/document fails on a shared memory error.  The test
   // sequence for this is:
-  // 1.  A print job is started.
-  // 2.  Spooling to send the render data will fail.  An error dialog is shown.
-  // 3.  The print job is canceled.  The callback from the service could occur
+  // 1.  Update print settings.
+  // 2.  A print job is started.
+  // 3.  Spooling to send the render data will fail.  An error dialog is shown.
+  // 4.  The print job is canceled.  The callback from the service could occur
   //     after the print job has been destroyed.
-  // 4.  Wait for the one print job to be destroyed, to ensure printing
+  // 5.  Wait for the one print job to be destroyed, to ensure printing
   //     finished cleanly before completing the test.
-  SetNumExpectedMessages(/*num=*/4);
+  SetNumExpectedMessages(/*num=*/5);
 
   PrintAfterPreviewIsReadyAndLoaded();
 
@@ -1063,13 +1098,14 @@
     SetNumExpectedMessages(/*num=*/2);
   } else {
     // The expected events for this are:
-    // 1.  A print job is started, but that fails.
-    // 2.  An error dialog is shown.
-    // 3.  The print job is canceled.  The callback from the service could occur
+    // 1.  Update print settings.
+    // 2.  A print job is started, but that fails.
+    // 3.  An error dialog is shown.
+    // 4.  The print job is canceled.  The callback from the service could occur
     //     after the print job has been destroyed.
-    // 4.  Wait for the one print job to be destroyed, to ensure printing
+    // 5.  Wait for the one print job to be destroyed, to ensure printing
     //     finished cleanly before completing the test.
-    SetNumExpectedMessages(/*num=*/4);
+    SetNumExpectedMessages(/*num=*/5);
   }
 
   PrintAfterPreviewIsReadyAndLoaded();
@@ -1106,11 +1142,12 @@
     SetNumExpectedMessages(/*num=*/1);
   } else {
     // The expected events for this are:
-    // 1.  A print job is started, but results in a cancel.
-    // 2.  The print job is canceled.
-    // 3.  Wait for the one print job to be destroyed, to ensure printing
+    // 1.  Update print settings.
+    // 2.  A print job is started, but results in a cancel.
+    // 3.  The print job is canceled.
+    // 4.  Wait for the one print job to be destroyed, to ensure printing
     //     finished cleanly before completing the test.
-    SetNumExpectedMessages(/*num=*/3);
+    SetNumExpectedMessages(/*num=*/4);
   }
 
   PrintAfterPreviewIsReadyAndLoaded();
@@ -1141,13 +1178,14 @@
   SetUpPrintViewManager(web_contents);
 
   // The expected events for this are:
-  // 1.  A print job is started, but has an access-denied error.
-  // 2.  A retry to start the print job with adjusted access will succeed.
-  // 3.  Rendering for 1 page of document of content.
-  // 4.  Completes with document done.
-  // 5.  Wait for the one print job to be destroyed, to ensure printing
+  // 1.  Update print settings.
+  // 2.  A print job is started, but has an access-denied error.
+  // 3.  A retry to start the print job with adjusted access will succeed.
+  // 4.  Rendering for 1 page of document of content.
+  // 5.  Completes with document done.
+  // 6.  Wait for the one print job to be destroyed, to ensure printing
   //     finished cleanly before completing the test.
-  SetNumExpectedMessages(/*num=*/5);
+  SetNumExpectedMessages(/*num=*/6);
 
   PrintAfterPreviewIsReadyAndLoaded();
 
@@ -1183,14 +1221,15 @@
 
   // Test of a misbehaving printer driver which only returns access-denied
   // errors.  The expected events for this are:
-  // 1.  A print job is started, but has an access-denied error.
-  // 2.  A retry to start the print job with adjusted access will still fail.
-  // 3.  An error dialog is shown.
-  // 4.  The print job is canceled.  The callback from the service could occur
+  // 1.  Update print settings.
+  // 2.  A print job is started, but has an access-denied error.
+  // 3.  A retry to start the print job with adjusted access will still fail.
+  // 4.  An error dialog is shown.
+  // 5.  The print job is canceled.  The callback from the service could occur
   //     after the print job has been destroyed.
-  // 5.  Wait for the one print job to be destroyed, to ensure printing
+  // 6.  Wait for the one print job to be destroyed, to ensure printing
   //     finished cleanly before completing the test.
-  SetNumExpectedMessages(/*num=*/5);
+  SetNumExpectedMessages(/*num=*/6);
 
   PrintAfterPreviewIsReadyAndLoaded();
 
@@ -1218,14 +1257,15 @@
 
   // No attempt to retry is made if an access-denied error occurs when trying
   // to render a page.  The expected events for this are:
-  // 1.  A print job is started.
-  // 2.  Rendering for 1 page of document of content fails with access denied.
-  // 3.  An error dialog is shown.
-  // 4.  The print job is canceled.  The callback from the service could occur
+  // 1.  Update print settings.
+  // 2.  A print job is started.
+  // 3.  Rendering for 1 page of document of content fails with access denied.
+  // 4.  An error dialog is shown.
+  // 5.  The print job is canceled.  The callback from the service could occur
   //     after the print job has been destroyed.
-  // 5.  Wait for the one print job to be destroyed, to ensure printing
+  // 6.  Wait for the one print job to be destroyed, to ensure printing
   //     finished cleanly before completing the test.
-  SetNumExpectedMessages(/*num=*/5);
+  SetNumExpectedMessages(/*num=*/6);
 
   PrintAfterPreviewIsReadyAndLoaded();
 
@@ -1258,19 +1298,20 @@
   SetUpPrintViewManager(web_contents);
 
   // The expected events for this are:
-  // 1.  Start the print job.
-  // 2.  First page render callback shows success.
-  // 3.  Second page render callback shows failure.  Will start failure
+  // 1.  Update print settings.
+  // 2.  Start the print job.
+  // 3.  First page render callback shows success.
+  // 4.  Second page render callback shows failure.  Will start failure
   //     processing to cancel the print job.
-  // 4.  A printing error dialog is displayed.
-  // 5.  Third page render callback will show it was canceled (due to prior
+  // 5.  A printing error dialog is displayed.
+  // 6.  Third page render callback will show it was canceled (due to prior
   //     failure).  This is disregarded by the browser, since the job has
   //     already been canceled.
-  // 6.  The print job is canceled.  The callback from the service could occur
+  // 7.  The print job is canceled.  The callback from the service could occur
   //     after the print job has been destroyed.
-  // 7.  Wait for the one print job to be destroyed, to ensure printing
+  // 8.  Wait for the one print job to be destroyed, to ensure printing
   //     finished cleanly before completing the test.
-  SetNumExpectedMessages(/*num=*/7);
+  SetNumExpectedMessages(/*num=*/8);
 
   PrintAfterPreviewIsReadyAndLoaded();
 
@@ -1304,14 +1345,15 @@
 
   // No attempt to retry is made if an access-denied error occurs when trying
   // to render a document.  The expected events for this are:
-  // 1.  A print job is started.
-  // 2.  Rendering for 1 page of document of content fails with access denied.
-  // 3.  An error dialog is shown.
-  // 4.  The print job is canceled.  The callback from the service could occur
+  // 1.  Update print settings.
+  // 2.  A print job is started.
+  // 3.  Rendering for 1 page of document of content fails with access denied.
+  // 4.  An error dialog is shown.
+  // 5.  The print job is canceled.  The callback from the service could occur
   //     after the print job has been destroyed.
-  // 5.  Wait for the one print job to be destroyed, to ensure printing
+  // 6.  Wait for the one print job to be destroyed, to ensure printing
   //     finished cleanly before completing the test.
-  SetNumExpectedMessages(/*num=*/5);
+  SetNumExpectedMessages(/*num=*/6);
 
   PrintAfterPreviewIsReadyAndLoaded();
 
@@ -1340,15 +1382,16 @@
 
   // No attempt to retry is made if an access-denied error occurs when trying
   // do wrap-up a rendered document.  The expected events are:
-  // 1.  A print job is started.
-  // 2.  Rendering for 1 page of document of content.
-  // 3.  Document done results in an access-denied error.
-  // 4.  An error dialog is shown.
-  // 5.  The print job is canceled.  The callback from the service could occur
+  // 1.  Update print settings.
+  // 2.  A print job is started.
+  // 3.  Rendering for 1 page of document of content.
+  // 4.  Document done results in an access-denied error.
+  // 5.  An error dialog is shown.
+  // 6.  The print job is canceled.  The callback from the service could occur
   //     after the print job has been destroyed.
-  // 6.  Wait for the one print job to be destroyed, to ensure printing
+  // 7.  Wait for the one print job to be destroyed, to ensure printing
   //     finished cleanly before completing the test.
-  SetNumExpectedMessages(/*num=*/6);
+  SetNumExpectedMessages(/*num=*/7);
 
   PrintAfterPreviewIsReadyAndLoaded();
 
@@ -1406,12 +1449,13 @@
 #if BUILDFLAG(IS_WIN)
     // Once the transition to system print is initiated, the expected events
     // are:
-    // 1.  A print job is started.
-    // 2.  Rendering for 1 page of document of content.
-    // 3.  Completes with document done.
-    // 4.  Wait for the one print job to be destroyed, to ensure printing
+    // 1.  Update print settings.
+    // 2.  A print job is started.
+    // 3.  Rendering for 1 page of document of content.
+    // 4.  Completes with document done.
+    // 5.  Wait for the one print job to be destroyed, to ensure printing
     //     finished cleanly before completing the test.
-    SetNumExpectedMessages(/*num=*/4);
+    SetNumExpectedMessages(/*num=*/5);
 #else
     // Once the transition to system print is initiated, the expected events
     // are:
@@ -1460,6 +1504,50 @@
   EXPECT_EQ(print_job_destruction_count(), 1);
 }
 
+#if BUILDFLAG(IS_WIN)
+// This test is Windows-only, since it is the only platform which can invoke
+// the system print dialog from within `PrintingContext::UpdatePrintSettings()`.
+// From that system dialog we can cause a cancel to occur.
+// TODO(crbug.com/809738):  Expand this to also cover in-browser, once an
+// appropriate signal is available to use for tracking expected events.
+// TODO(crbug.com/1435566):  Enable this once the CHECK failure in
+// PrintViewManagerBase::RegisterSystemPrintClient() is resolved.
+IN_PROC_BROWSER_TEST_F(SystemAccessProcessSandboxedServicePrintBrowserTest,
+                       DISABLED_SystemPrintFromPrintPreviewCancelRetry) {
+  AddPrinter("printer1");
+  SetPrinterNameForSubsequentContexts("printer1");
+  PrimeForCancelInAskUserForSettings();
+
+  ASSERT_TRUE(embedded_test_server()->Started());
+  GURL url(embedded_test_server()->GetURL("/printing/test3.html"));
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_TRUE(web_contents);
+  SetUpPrintViewManager(web_contents);
+
+  // The expected events for this are:
+  // 1.  Update the print settings, which indicates to cancel the print
+  //     request.  No further printing calls are made.
+  // No print job is created because of such an early cancel.
+  SetNumExpectedMessages(/*num=*/1);
+
+  SystemPrintFromPreviewOnceReadyAndLoaded(/*wait_for_callback=*/true);
+
+  EXPECT_EQ(update_print_settings_result(), mojom::ResultCode::kCanceled);
+  EXPECT_EQ(error_dialog_shown_count(), 0u);
+  EXPECT_EQ(print_job_destruction_count(), 0);
+
+  // Now try to initiate the system print from a Print Preview again.
+  // Same number of expected events.
+  SystemPrintFromPreviewOnceReadyAndLoaded(/*wait_for_callback=*/true);
+  EXPECT_EQ(update_print_settings_result(), mojom::ResultCode::kCanceled);
+  EXPECT_EQ(error_dialog_shown_count(), 0u);
+  EXPECT_EQ(print_job_destruction_count(), 0);
+}
+#endif  // BUILDFLAG(IS_WIN)
+
 IN_PROC_BROWSER_TEST_F(SystemAccessProcessSandboxedServicePrintBrowserTest,
                        StartBasicPrint) {
   AddPrinter("printer1");
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc
index d982b4e..c278562 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc
@@ -41,6 +41,26 @@
   return capability == signin::Tribool::kFalse;
 }
 
+bool PrivacySandboxRestrictedNoticeRequired(Profile* profile) {
+  auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
+
+  if (!identity_manager ||
+      !identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSignin)) {
+    // The user isn't signed in so we can't apply any capabilties-based
+    // restrictions.
+    return false;
+  }
+
+  const auto core_account_info =
+      identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin);
+  const AccountInfo account_info =
+      identity_manager->FindExtendedAccountInfo(core_account_info);
+  auto capability =
+      account_info.capabilities
+          .is_subject_to_chrome_privacy_sandbox_restricted_measurement_notice();
+  return capability == signin::Tribool::kTrue;
+}
+
 }  // namespace
 
 PrivacySandboxSettingsDelegate::PrivacySandboxSettingsDelegate(Profile* profile)
@@ -67,6 +87,14 @@
   return restricted_by_capability;
 }
 
+bool PrivacySandboxSettingsDelegate::IsSubjectToM1NoticeRestricted() const {
+  // If the feature is deactivated, the notice shouldn't be shown.
+  if (!privacy_sandbox::kPrivacySandboxSettings4RestrictedNotice.Get()) {
+    return false;
+  }
+  return PrivacySandboxRestrictedNoticeRequired(profile_);
+}
+
 bool PrivacySandboxSettingsDelegate::IsIncognitoProfile() const {
   return profile_->IsIncognitoProfile();
 }
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.h b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.h
index 6eea038..9e0dcb1 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.h
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.h
@@ -20,6 +20,7 @@
   bool IsPrivacySandboxRestricted() const override;
   bool IsIncognitoProfile() const override;
   bool HasAppropriateTopicsConsent() const override;
+  bool IsSubjectToM1NoticeRestricted() const override;
 
  private:
   raw_ptr<Profile> profile_;
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate_unittest.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate_unittest.cc
index fb6f78b..46a8882 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate_unittest.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate_unittest.cc
@@ -44,6 +44,18 @@
                                         account_info);
   }
 
+  void SetRestrictedNoticeCapability(const std::string& account, bool enabled) {
+    auto account_info = identity_test_env()
+                            ->identity_manager()
+                            ->FindExtendedAccountInfoByEmailAddress(kTestEmail);
+    AccountCapabilitiesTestMutator mutator(&account_info.capabilities);
+    mutator
+        .set_is_subject_to_chrome_privacy_sandbox_restricted_measurement_notice(
+            enabled);
+    signin::UpdateAccountInfoForAccount(identity_test_env()->identity_manager(),
+                                        account_info);
+  }
+
   PrivacySandboxSettingsDelegate* delegate() { return delegate_.get(); }
   base::test::ScopedFeatureList* feature_list() { return &feature_list_; }
   signin::IdentityTestEnvironment* identity_test_env() {
@@ -93,6 +105,56 @@
 }
 
 TEST_F(PrivacySandboxSettingsDelegateTest,
+       RestrictedNoticeRequiredForSignedInUser) {
+  feature_list()->InitAndEnableFeatureWithParameters(
+      privacy_sandbox::kPrivacySandboxSettings4,
+      {{privacy_sandbox::kPrivacySandboxSettings4RestrictedNotice.name,
+        "true"}});
+  // Sign the user in.
+  identity_test_env()->MakePrimaryAccountAvailable(
+      kTestEmail, signin::ConsentLevel::kSignin);
+
+  // Initially the account capability will be in an unknown state, which
+  // should be interpreted as no restriction.
+  EXPECT_FALSE(delegate()->IsSubjectToM1NoticeRestricted());
+
+  // Validate that the notice is not required when the account is not configured
+  // to show it.
+  SetRestrictedNoticeCapability(kTestEmail, false);
+  EXPECT_FALSE(delegate()->IsSubjectToM1NoticeRestricted());
+
+  // Validate that the notice is required when the account is configured to show
+  // it.
+  SetRestrictedNoticeCapability(kTestEmail, true);
+  EXPECT_TRUE(delegate()->IsSubjectToM1NoticeRestricted());
+}
+
+TEST_F(PrivacySandboxSettingsDelegateTest,
+       RestrictedNoticeRequiredForSignedOutUser) {
+  feature_list()->InitAndEnableFeatureWithParameters(
+      privacy_sandbox::kPrivacySandboxSettings4,
+      {{privacy_sandbox::kPrivacySandboxSettings4RestrictedNotice.name,
+        "true"}});
+  // If the user is not signed in to Chrome then we don't use any age signal and
+  // don't restrict the feature.
+  EXPECT_FALSE(delegate()->IsSubjectToM1NoticeRestricted());
+}
+
+TEST_F(PrivacySandboxSettingsDelegateTest,
+       RestrictedNoticeRequiredFeatureDisabled) {
+  feature_list()->InitAndEnableFeatureWithParameters(
+      privacy_sandbox::kPrivacySandboxSettings4,
+      {{privacy_sandbox::kPrivacySandboxSettings4RestrictedNotice.name,
+        "false"}});
+  identity_test_env()->MakePrimaryAccountAvailable(
+      kTestEmail, signin::ConsentLevel::kSignin);
+  SetRestrictedNoticeCapability(kTestEmail, true);
+  // Even if the user is signed in to Chrome, the feature being disabled means
+  // no notice should be shown.
+  EXPECT_FALSE(delegate()->IsSubjectToM1NoticeRestricted());
+}
+
+TEST_F(PrivacySandboxSettingsDelegateTest,
        AppropriateTopicsConsent_ConsentNotRequired) {
   // When the V4 consent required parameter is not present, Topics always has
   // an appropriate level of consent.
diff --git a/chrome/browser/profiles/renderer_updater.cc b/chrome/browser/profiles/renderer_updater.cc
index 10ff91ad..884e79c 100644
--- a/chrome/browser/profiles/renderer_updater.cc
+++ b/chrome/browser/profiles/renderer_updater.cc
@@ -135,9 +135,20 @@
       render_process_host,
       content_settings_manager.InitWithNewPipeAndPassReceiver(),
       std::make_unique<chrome::ContentSettingsManagerDelegate>());
+  mojo::PendingRemote<chrome::mojom::BoundSessionRequestThrottledListener>
+      bound_session_request_throttled_listener;
+#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS)
+  if (bound_session_cookie_refresh_service_) {
+    bound_session_cookie_refresh_service_
+        ->AddBoundSessionRequestThrottledListenerReceiver(
+            bound_session_request_throttled_listener
+                .InitWithNewPipeAndPassReceiver());
+  }
+#endif
   renderer_configuration->SetInitialConfiguration(
       is_off_the_record_, std::move(chromeos_listener_receiver),
-      std::move(content_settings_manager));
+      std::move(content_settings_manager),
+      std::move(bound_session_request_throttled_listener));
 
   renderer_configuration->SetConfiguration(CreateRendererDynamicParams());
 }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 61696a3d..15b3d1c 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -754,6 +754,8 @@
                        this,
                        &menu_model_,
                        base::BindRepeating(MenuItemMatchesParams, params_)),
+      current_url_(render_frame_host.GetLastCommittedURL()),
+      main_frame_url_(render_frame_host.GetMainFrame()->GetLastCommittedURL()),
       profile_link_submenu_model_(this),
       multiple_profiles_open_(false),
       protocol_handler_submenu_model_(this),
@@ -969,6 +971,7 @@
   ui::ScopedClipboardWriter scw(
       ui::ClipboardBuffer::kCopyPaste,
       CreateDataEndpoint(/*notify_if_restricted=*/true));
+  scw.SetDataSourceURL(main_frame_url_, current_url_);
   scw.WriteText(FormatURLForClipboard(url));
 }
 
@@ -2837,17 +2840,11 @@
     // back/forward entries. Session history may have changed while the context
     // menu was open. So we need to check `CanGoBack`/`CanGoForward` again.
     case IDC_BACK:
-      if (auto& controller = embedder_web_contents_->GetController();
-          controller.CanGoBack()) {
-        controller.GoBack();
-      }
+      chrome::GoBack(embedder_web_contents_);
       break;
 
     case IDC_FORWARD:
-      if (auto& controller = embedder_web_contents_->GetController();
-          controller.CanGoForward()) {
-        controller.GoForward();
-      }
+      chrome::GoForward(embedder_web_contents_);
       break;
 
     case IDC_SAVE_PAGE:
@@ -3727,6 +3724,7 @@
   ui::ScopedClipboardWriter scw(
       ui::ClipboardBuffer::kCopyPaste,
       CreateDataEndpoint(/*notify_if_restricted=*/true));
+  scw.SetDataSourceURL(main_frame_url_, current_url_);
   scw.WriteText(params_.link_text);
 }
 
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.h b/chrome/browser/renderer_context_menu/render_view_context_menu.h
index e6362794..b0505bb 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.h
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -372,6 +372,10 @@
   // a text selection.
   GURL selection_navigation_url_;
 
+  // URL of current page and current main frame url
+  GURL current_url_;
+  GURL main_frame_url_;
+
   ui::SimpleMenuModel profile_link_submenu_model_;
   std::vector<base::FilePath> profile_link_paths_;
   bool multiple_profiles_open_;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js
index 4c85505..c55a43f 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js
@@ -2361,9 +2361,8 @@
     });
 
 // Regression test that large text areas produce output.
-// Flaky test: https://crbug.com/1430387
 AX_TEST_F(
-    'ChromeVoxEditingTest', 'DISABLED_GiantTextAreaPerformance',
+    'ChromeVoxEditingTest', 'GiantTextAreaPerformance',
     async function() {
       const mockFeedback = this.createMockFeedback();
       const site = `
diff --git a/chrome/browser/resources/chromeos/add_supervision/BUILD.gn b/chrome/browser/resources/chromeos/add_supervision/BUILD.gn
index c64c2e3..71b42a3 100644
--- a/chrome/browser/resources/chromeos/add_supervision/BUILD.gn
+++ b/chrome/browser/resources/chromeos/add_supervision/BUILD.gn
@@ -9,6 +9,7 @@
   is_polymer3 = true
   deps = [
     ":add_supervision_api_server",
+    ":add_supervision_app",
     ":add_supervision_ui",
     "//ash/webui/common/resources/post_message_api:post_message_api_server",
   ]
@@ -21,6 +22,16 @@
   ]
 }
 
+js_library("add_supervision_app") {
+  deps = [
+    ":add_supervision_ui",
+    "//chrome/browser/resources/chromeos/supervision:supervised_user_error",
+    "//chrome/browser/resources/chromeos/supervision:supervised_user_offline",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+  externs_list = [ "//ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager_externs.js" ]
+}
+
 js_library("add_supervision_ui") {
   deps = [
     ":add_supervision_api_server",
@@ -34,5 +45,8 @@
 }
 
 html_to_js("web_components") {
-  js_files = [ "add_supervision_ui.js" ]
+  js_files = [
+    "add_supervision_app.js",
+    "add_supervision_ui.js",
+  ]
 }
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision.html b/chrome/browser/resources/chromeos/add_supervision/add_supervision.html
index 15611a2d..714a2a6 100644
--- a/chrome/browser/resources/chromeos/add_supervision/add_supervision.html
+++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision.html
@@ -7,9 +7,9 @@
     <script src="chrome/browser/ui/webui/ash/add_supervision/add_supervision.mojom-lite.js"></script>
   </head>
   <body>
-    <add-supervision-ui></add-supervision-ui>
+    <add-supervision-app></add-supervision-app>
     <link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
     <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
-    <script type="module" src="add_supervision_ui.js"></script>
+    <script type="module" src="add_supervision_app.js"></script>
   </body>
 </html>
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js b/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js
index 4256e3db..2fc8fab1 100644
--- a/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js
+++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js
@@ -4,6 +4,8 @@
 
 import {PostMessageAPIServer} from 'chrome://resources/ash/common/post_message_api/post_message_api_server.js';
 
+import {isLocalHostForTesting} from './add_supervision_ui.js';
+
 /**
  * Class that implements the server side of the AddSupervision postMessage
  * API.  In the case of this API, the Add Supervision WebUI is the server, and
@@ -13,6 +15,7 @@
 export class AddSupervisionAPIServer extends PostMessageAPIServer {
   /*
    * @constructor
+   * @param {!Element} ui  Polymer object add-supervision-ui
    * @param {!Element} webviewElement  The <webview> element to listen to as a
    *     client.
    * @param {string} targetURL  The target URL to use for outgoing messages.
@@ -20,9 +23,11 @@
    * @param {string} originURLPrefix  The URL prefix to use to filter incoming
    *     messages via the postMessage API.
    */
-  constructor(webviewElement, targetURL, originURLPrefix) {
+  constructor(ui, webviewElement, targetURL, originURLPrefix) {
     super(webviewElement, targetURL, originURLPrefix);
 
+    this.ui_ = ui;
+
     this.addSupervisionHandler_ =
         addSupervision.mojom.AddSupervisionHandler.getRemote();
 
@@ -36,8 +41,18 @@
   }
 
   /** @override */
+  initialize() {
+    // The server cannot communicate with the mock webview used
+    // in the browser test, so skip initialization during tests.
+    if (isLocalHostForTesting(this.targetURL())) {
+      return;
+    }
+    super.initialize();
+  }
+
+  /** @override */
   onInitializationError(origin) {
-    // TODO(): Trigger an error page to be shown in this case.
+    this.ui_.showErrorPage();
   }
 
   /**
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision_app.html b/chrome/browser/resources/chromeos/add_supervision/add_supervision_app.html
new file mode 100644
index 0000000..290f24a
--- /dev/null
+++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision_app.html
@@ -0,0 +1,8 @@
+<cr-view-manager id="viewManager">
+    <add-supervision-ui id="add-supervision-ui" slot="view">
+    </add-supervision-ui>
+    <supervised-user-error id="supervised-user-error" slot="view">
+    </supervised-user-error>
+    <supervised-user-offline id="supervised-user-offline" slot="view">
+    </supervised-user-offline>
+</cr-view-manager>
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision_app.js b/chrome/browser/resources/chromeos/add_supervision/add_supervision_app.js
new file mode 100644
index 0000000..ebd92e0
--- /dev/null
+++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision_app.js
@@ -0,0 +1,94 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import './add_supervision_ui.js';
+import './supervision/supervised_user_error.js';
+import './supervision/supervised_user_offline.js';
+import 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js';
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+
+/** @enum {string} */
+const Screens = {
+  /**
+   * ERROR: Shown permanently after an error event.
+   * OFFLINE: Shown when the device is offline.
+   * ONLINE: Shown when the device is online.
+   */
+  ERROR: 'supervised-user-error',
+  OFFLINE: 'supervised-user-offline',
+  ONLINE: 'add-supervision-ui',
+};
+
+class AddSupervisionApp extends PolymerElement {
+  static get is() {
+    return 'add-supervision-app';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  static get properties() {
+    return {
+      /**
+       * Specifies what the current screen is.
+       * @private {Screens}
+       */
+      currentScreen_: {
+        type: Screens,
+      },
+    };
+  }
+
+  /** @override */
+  ready() {
+    super.ready();
+    this.addEventListeners_();
+    this.switchToScreen_(navigator.onLine ? Screens.ONLINE : Screens.OFFLINE);
+  }
+
+  /** @private */
+  addEventListeners_() {
+    window.addEventListener('online', () => {
+      this.switchToScreen_(Screens.ONLINE);
+    });
+
+    window.addEventListener('offline', () => {
+      this.switchToScreen_(Screens.OFFLINE);
+    });
+
+    this.addEventListener('show-error', () => {
+      this.switchToScreen_(Screens.ERROR);
+    });
+  }
+
+  /**
+   * Switches to the specified screen.
+   * @param {Screens} screen
+   * @private
+   */
+  switchToScreen_(screen) {
+    if (this.isinvalidScreenSwitch_(screen)) {
+      return;
+    }
+    this.currentScreen_ = screen;
+    /** @type {CrViewManagerElement} */ (this.$.viewManager)
+        .switchView(this.currentScreen_);
+  }
+
+  /**
+   * Returns true if the app cannot navigate from the current screen to the
+   * screen provided.
+   * @param {Screens} screen
+   * @return {boolean}
+   * @private
+   */
+  isinvalidScreenSwitch_(screen) {
+    return this.currentScreen_ === screen ||
+        this.currentScreen_ === Screens.ERROR;
+  }
+}
+customElements.define(AddSupervisionApp.is, AddSupervisionApp);
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.html b/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.html
index b53cfcb..238022ab 100644
--- a/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.html
+++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.html
@@ -4,24 +4,6 @@
     height: 100%;
   }
 
-  .title {
-    color: var(--google-grey-900);
-    font-family: 'Google Sans', Roboto, sans-serif;
-    font-size: 28px;
-    padding-top: 20px;
-  }
-
-  .sub-title {
-    color: var(--google-grey-700);
-    font-family: Roboto;
-    font-size: 14px;
-    padding-top: 8px;
-  }
-
-  .error-icon {
-    fill: var(--google-blue-600);
-  }
-
   #webviewDiv {
     height: 100vh;
   }
@@ -30,40 +12,7 @@
     display: flex;
     height: 100%;
   }
-
-  #offlineContentDiv {
-    padding-inline-start: 32px;
-  }
-
-  #networkUnavailableDiv {
-    padding-inline-start: 190px;
-    padding-top: 50px;
-  }
-
-  #closeButtonDiv {
-    padding-inline-start: 632px;
-    padding-top: 116px;
-  }
 </style>
-<div id="offlineContentDiv" role="dialog" aria-modal="true"
-    aria-label="$i18n{pageTitle}">
-  <div>
-    <svg xmlns="http://www.w3.org/2000/svg" class="error-icon" width="32px" height="32px" viewBox="0 0 22 22">
-      <path d="M11 15h2v2h-2v-2zm0-8h2v6h-2V7zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z">
-      <path fill="none" d="M0 0h24v24H0V0z">
-    </svg>
-  </div>
-  <div class="title">$i18n{networkDownHeading}</div>
-  <div class="sub-title">$i18n{networkDownDescription}</div>
-  <div id="networkUnavailableDiv">
-    <img role="presentation" src="images/network_unavailable.svg">
-  </div>
-  <div id="closeButtonDiv">
-    <cr-button class="action-button" on-click="closeDialog_" tabindex="0">
-      $i18n{networkDownButtonLabel}
-    </cr-button>
-  </div>
-</div>
 <div id="webviewDiv" role="dialog" aria-modal="true"
     aria-label="$i18n{pageTitle}">
   <webview id="webview"></webview>
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.js b/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.js
index 4b7bd80..7aaa802 100644
--- a/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.js
+++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.js
@@ -35,19 +35,34 @@
 const INITIAL_FOCUS_DELAY_MS = 50;
 
 /**
- * Returns whether the provided request should be allowed, based on whether
- * its URL matches the list of allowed hosts.
+ * Returns true if the URL references an HTTP request to localhost.
+ * @param {URL} url
+ * @return {boolean}
+ */
+export function isLocalHostForTesting(url) {
+  return url.protocol == 'http:' && url.hostname == '127.0.0.1';
+}
+
+/**
+ * Returns true if the URL references one of the allowed hosts.
+ * @param {URL} url
+ * @return {boolean}
+ */
+function isAllowedHost(url) {
+  return url.protocol == 'https:' &&
+      ALLOWED_HOSTS.some(
+          (allowedHost) =>
+              url.host == allowedHost || url.host.endsWith('.' + allowedHost));
+}
+
+/**
+ * Returns true if the request should be allowed.
  * @param {!{url: string}} requestDetails Request that is issued by the webview.
- * @return {boolean} Whether the request should be allowed.
+ * @return {boolean}
  */
 function isAllowedRequest(requestDetails) {
   const requestUrl = new URL(requestDetails.url);
-
-  // Only allow HTTPS and hosts that are in the list (or subdomains).
-  return requestUrl.protocol == 'https:' &&
-      ALLOWED_HOSTS.some(
-          (allowedHost) => requestUrl.host == allowedHost ||
-              requestUrl.host.endsWith('.' + allowedHost));
+  return isLocalHostForTesting(requestUrl) || isAllowedHost(requestUrl);
 }
 
 const addSupervisionHandler =
@@ -58,31 +73,28 @@
 
   _template: html`{__html_template__}`,
 
-  /** Attempts to close the dialog */
+  /** Attempts to close the dialog. */
   closeDialog_() {
     this.server.requestClose();
   },
 
+  /** Triggers the error page. */
+  showErrorPage() {
+    this.dispatchEvent(new CustomEvent('show-error', {
+      bubbles: true,
+      composed: true,
+    }));
+  },
+
   /** @override */
   ready() {
-    // Initialize and listen for online/offline state.
-    this.webviewDiv = this.$.webviewDiv;
-    this.webviewDiv.hidden = !navigator.onLine;
-
-    this.offlineContentDiv = this.$.offlineContentDiv;
-    this.offlineContentDiv.hidden = navigator.onLine;
-
-    window.addEventListener('online', () => {
-      this.webviewDiv.hidden = false;
-      this.offlineContentDiv.hidden = true;
-    });
-
-    window.addEventListener('offline', () => {
-      this.webviewDiv.hidden = true;
-      this.offlineContentDiv.hidden = false;
-    });
-
     addSupervisionHandler.getOAuthToken().then((result) => {
+      // Setup should terminate early if OAuth Token fetching fails.
+      if (result.status === addSupervision.mojom.OAuthTokenFetchStatus.ERROR) {
+        this.showErrorPage();
+        return;
+      }
+
       const webviewUrl = loadTimeData.getString('webviewUrl');
       const eventOriginFilter = loadTimeData.getString('eventOriginFilter');
       const webview =
@@ -116,6 +128,10 @@
         setTimeout(() => webview.focus(), INITIAL_FOCUS_DELAY_MS);
       });
 
+      webview.addEventListener('loadabort', () => {
+        this.showErrorPage();
+      });
+
       // Block any requests to URLs other than one specified
       // by eventOriginFilter.
       webview.request.onBeforeRequest.addListener(function(details) {
@@ -126,7 +142,7 @@
 
       // Set up the server.
       this.server =
-          new AddSupervisionAPIServer(webview, url, eventOriginFilter);
+          new AddSupervisionAPIServer(this, webview, url, eventOriginFilter);
     });
   },
 });
diff --git a/chrome/browser/resources/chromeos/add_supervision/images/network_unavailable.svg b/chrome/browser/resources/chromeos/add_supervision/images/network_unavailable.svg
deleted file mode 100644
index 6b13b3f..0000000
--- a/chrome/browser/resources/chromeos/add_supervision/images/network_unavailable.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="264" height="264"><g fill="none" fill-rule="evenodd"><path fill="#EA4335" d="m171.605 82.336-6.413-6.413a2.268 2.268 0 0 1 0-3.206l6.413-6.413a2.267 2.267 0 0 1 3.207 0l6.412 6.413a2.266 2.266 0 0 1 0 3.206l-6.412 6.413a2.269 2.269 0 0 1-3.207 0"/><path fill="#FBBC04" d="m105.869 48.101-6.413-6.413a2.268 2.268 0 0 1 0-3.206l6.413-6.413a2.269 2.269 0 0 1 3.207 0l6.413 6.413a2.268 2.268 0 0 1 0 3.206l-6.413 6.413a2.269 2.269 0 0 1-3.207 0"/><path fill="#F1F3F4" d="m96.554 123.415 6.413-6.413a2.269 2.269 0 0 1 3.207 0l6.412 6.413a2.267 2.267 0 0 1 0 3.207l-6.412 6.412a2.267 2.267 0 0 1-3.207 0l-6.413-6.412a2.269 2.269 0 0 1 0-3.207"/><path fill="#4285F4" d="M129.012 65.68a5.667 5.667 0 0 1 0-8.017l4.81-4.81a5.67 5.67 0 0 1 8.016 8.016l-4.81 4.81a5.67 5.67 0 0 1-8.016 0"/><path fill="#F1F3F4" d="M133.766 102.358a5.667 5.667 0 0 1 0-8.016l4.81-4.81a5.67 5.67 0 0 1 8.016 8.016l-4.81 4.81a5.67 5.67 0 0 1-8.016 0"/><path fill="#FBBC04" d="m146.85 97.29.742-.742a5.667 5.667 0 1 0-8.016-8.016l-4.81 4.81a5.62 5.62 0 0 0-1.46 2.601c4.62.068 9.146.527 13.545 1.346"/><path fill="#34A853" d="m87.07 75.282 11.947 3.201c1.686.452 2.25 2.56 1.016 3.793l-8.745 8.746c-1.235 1.234-3.342.67-3.794-1.016L84.293 78.06c-.452-1.686 1.09-3.229 2.777-2.777"/><path fill="#F1F3F4" d="m151.384 118.925 11.947 3.2c1.686.453 2.25 2.56 1.016 3.794l-8.745 8.746c-1.235 1.234-3.342.67-3.794-1.016l-3.2-11.947c-.453-1.686 1.09-3.23 2.776-2.777"/><path fill="#34A853" d="M159 17a7 7 0 1 1-14 0 7 7 0 0 1 14 0"/><path fill="#DADCE0" d="M132 180.473c6.834 0 13.031 2.774 17.52 7.253l7.008-6.993c-6.284-6.27-14.96-10.154-24.528-10.154-9.568 0-18.244 3.884-24.528 10.154l7.008 6.993c4.489-4.479 10.686-7.253 17.52-7.253m10.517 14.24A14.843 14.843 0 0 0 132 190.368a14.843 14.843 0 0 0-10.517 4.347L132 205.208l10.517-10.494z"/><path fill="#DADCE0" d="M132 160.686c12.302 0 23.457 4.993 31.536 13.055l7.008-6.993c-9.875-9.853-23.509-15.956-38.544-15.956-15.035 0-28.669 6.103-38.544 15.956l7.008 6.993c8.079-8.062 19.234-13.055 31.536-13.055"/><path stroke="#DADCE0" stroke-width="4" d="M212 175c0 44.183-35.817 80-80 80s-80-35.817-80-80 35.817-80 80-80 80 35.817 80 80zM98 144l62 62"/></g></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/password_manager/dialogs/auth_timed_out_dialog.html b/chrome/browser/resources/password_manager/dialogs/auth_timed_out_dialog.html
index 32973716f..0ecc71b 100644
--- a/chrome/browser/resources/password_manager/dialogs/auth_timed_out_dialog.html
+++ b/chrome/browser/resources/password_manager/dialogs/auth_timed_out_dialog.html
@@ -4,7 +4,7 @@
     <div>$i18n{authTimedOutDescription}</div>
   </div>
   <div slot="button-container">
-    <cr-button class="action-button"
+    <cr-button class="action-button" autofocus
         on-click="onCloseButtonClick_">
       $i18n{gotIt}
     </cr-button>
diff --git a/chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.html b/chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.html
index 48eecc5..686cce4a 100644
--- a/chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.html
+++ b/chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.html
@@ -18,7 +18,8 @@
     </span>
   </div>
   <div slot="button-container">
-    <cr-button class="cancel-button" on-click="onCancelClick_" id="cancel">
+    <cr-button class="cancel-button" on-click="onCancelClick_" id="cancel"
+        autofocus>
       $i18n{cancel}
     </cr-button>
     <cr-button class="action-button" on-click="onDeleteClick_" id="delete">
diff --git a/chrome/browser/resources/password_manager/dialogs/edit_password_dialog.html b/chrome/browser/resources/password_manager/dialogs/edit_password_dialog.html
index bef81f3..eed479c 100644
--- a/chrome/browser/resources/password_manager/dialogs/edit_password_dialog.html
+++ b/chrome/browser/resources/password_manager/dialogs/edit_password_dialog.html
@@ -55,7 +55,7 @@
         </a>
       </div>
     </template>
-    <cr-input id="usernameInput" label="$i18n{usernameLabel}"
+    <cr-input id="usernameInput" label="$i18n{usernameLabel}" autofocus
         value="{{username_}}" error-message="[[usernameErrorMessage_]]"
         invalid="[[doesUsernameExistAlready_(usernameErrorMessage_)]]">
     </cr-input>
diff --git a/chrome/browser/resources/password_manager/dialogs/edit_password_disclaimer_dialog.html b/chrome/browser/resources/password_manager/dialogs/edit_password_disclaimer_dialog.html
index 40bf8a17..05c3e04 100644
--- a/chrome/browser/resources/password_manager/dialogs/edit_password_disclaimer_dialog.html
+++ b/chrome/browser/resources/password_manager/dialogs/edit_password_disclaimer_dialog.html
@@ -2,7 +2,8 @@
   <div slot="title">[[getDisclaimerTitle_(origin)]]</div>
   <div slot="body">[[getDisclaimerDescription_()]]</div>
   <div slot="button-container">
-    <cr-button id="cancel" class="cancel-button" on-click="onCancel_">
+    <cr-button id="cancel" class="cancel-button" on-click="onCancel_"
+        autofocus>
       $i18n{cancel}
     </cr-button>
     <cr-button id="edit" class="action-button" on-click="onEditClick_">
diff --git a/chrome/browser/resources/password_manager/dialogs/move_passwords_dialog.html b/chrome/browser/resources/password_manager/dialogs/move_passwords_dialog.html
index 2f19062..7f9efaab 100644
--- a/chrome/browser/resources/password_manager/dialogs/move_passwords_dialog.html
+++ b/chrome/browser/resources/password_manager/dialogs/move_passwords_dialog.html
@@ -28,7 +28,7 @@
     </div>
   </div>
   <div slot="button-container">
-    <cr-button id="cancel" class="cancel-button" on-click="onCancel_">
+    <cr-button id="cancel" class="cancel-button" on-click="onCancel_" autofocus>
       $i18n{cancel}
     </cr-button>
     <cr-button id="move" class="action-button" on-click="onMoveButtonClick_"
diff --git a/chrome/browser/resources/password_manager/dialogs/multi_store_delete_password_dialog.html b/chrome/browser/resources/password_manager/dialogs/multi_store_delete_password_dialog.html
index 620058c..6bee0290 100644
--- a/chrome/browser/resources/password_manager/dialogs/multi_store_delete_password_dialog.html
+++ b/chrome/browser/resources/password_manager/dialogs/multi_store_delete_password_dialog.html
@@ -42,7 +42,7 @@
   </div>
   <div slot="button-container">
     <cr-button class="cancel-button" id="cancelButton"
-        on-click="onCancelButtonClick_">
+        on-click="onCancelButtonClick_" autofocus>
       $i18n{cancel}
     </cr-button>
     <cr-button class="action-button" id="removeButton"
diff --git a/chrome/browser/resources/password_manager/passwords_exporter.html b/chrome/browser/resources/password_manager/passwords_exporter.html
index 7c010d6..984368c 100644
--- a/chrome/browser/resources/password_manager/passwords_exporter.html
+++ b/chrome/browser/resources/password_manager/passwords_exporter.html
@@ -43,7 +43,8 @@
       </ul>
     </div>
     <div slot="button-container">
-      <cr-button id="cancelButton" on-click="closePasswordsExportErrorDialog_">
+      <cr-button id="cancelButton" on-click="closePasswordsExportErrorDialog_"
+          autofocus>
         $i18n{cancel}
       </cr-button>
       <cr-button id="tryAgainButton" class="action-button"
diff --git a/chrome/browser/resources/password_manager/passwords_importer.html b/chrome/browser/resources/password_manager/passwords_importer.html
index 0b9f78f..0565c7d2 100644
--- a/chrome/browser/resources/password_manager/passwords_importer.html
+++ b/chrome/browser/resources/password_manager/passwords_importer.html
@@ -193,7 +193,7 @@
     </div>
     <div slot="button-container">
       <cr-button id="closeButton" class="cancel-button"
-          on-click="onCloseClick_">
+          on-click="onCloseClick_" autofocus>
         $i18n{close}
       </cr-button>
       <cr-button id="selectFileButton" class="action-button"
@@ -252,7 +252,7 @@
     </div>
     <div slot="button-container">
       <cr-button id="closeButton" class="cancel-button"
-          on-click="onCloseClick_">
+          on-click="onCloseClick_" autofocus>
         $i18n{close}
       </cr-button>
       <cr-button id="viewPasswordsButton" class="action-button"
@@ -274,7 +274,7 @@
     </div>
     <div slot="button-container">
       <cr-button id="closeButton" class="action-button"
-          on-click="onCloseClick_">
+          on-click="onCloseClick_" autofocus>
         $i18n{close}
       </cr-button>
     </div>
@@ -304,7 +304,7 @@
     </div>
     <div slot="button-container">
       <cr-button id="cancelButton" class="cancel-button flex-float-left"
-          on-click="onCloseClick_">
+          on-click="onCloseClick_" autofocus>
         $i18n{importPasswordsCancel}
       </cr-button>
       <cr-button id="skipButton" class="skip-button" on-click="onSkipClick_">
diff --git a/chrome/browser/resources/password_manager/promo_cards/promo_card.ts b/chrome/browser/resources/password_manager/promo_cards/promo_card.ts
index b6b9127..a5cdb563 100644
--- a/chrome/browser/resources/password_manager/promo_cards/promo_card.ts
+++ b/chrome/browser/resources/password_manager/promo_cards/promo_card.ts
@@ -28,6 +28,27 @@
   ACCESS_ON_ANY_DEVICE = 'access_on_any_device_promo',
 }
 
+/**
+ * These values are persisted to logs. Entries should not be renumbered and
+ * numeric values should never be reused.
+ *
+ * Needs to stay in sync with PromoCardType in promo_card.cc
+ */
+enum PromoCardMetricId {
+  CHECKUP = 0,
+  UNUSED_WEB_PASSWORD_MANAGER = 1,
+  SHORTCUT = 2,
+  UNUSED_ACCESS_ON_ANY_DEVICE = 3,
+  // Must be last.
+  COUNT = 4,
+}
+
+function recordPromoCardAction(card: PromoCardMetricId) {
+  chrome.metricsPrivate.recordEnumerationValue(
+      'PasswordManager.PromoCard.ActionButtonClicked', card,
+      PromoCardMetricId.COUNT);
+}
+
 export interface PromoCardElement {
   $: {
     actionButton: CrButtonElement,
@@ -64,9 +85,11 @@
         const params = new URLSearchParams();
         params.set(UrlParam.START_CHECK, 'true');
         Router.getInstance().navigateTo(Page.CHECKUP, null, params);
+        recordPromoCardAction(PromoCardMetricId.CHECKUP);
         break;
       case PromoCardId.SHORTCUT:
         PasswordManagerImpl.getInstance().showAddShortcutDialog();
+        recordPromoCardAction(PromoCardMetricId.SHORTCUT);
         break;
       default:
         assertNotReached();
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 2b8c416..8c34f24 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -111,7 +111,6 @@
     "controls/controlled_button.ts",
     "controls/controlled_radio_button.ts",
     "controls/settings_checkbox.ts",
-    "controls/settings_dropdown_menu.ts",
     "controls/settings_radio_group.ts",
     "controls/settings_slider.ts",
     "controls/settings_toggle_button.ts",
diff --git a/chrome/browser/resources/settings/a11y_page/captions_subpage.ts b/chrome/browser/resources/settings/a11y_page/captions_subpage.ts
index 5c16088..870fda3 100644
--- a/chrome/browser/resources/settings/a11y_page/captions_subpage.ts
+++ b/chrome/browser/resources/settings/a11y_page/captions_subpage.ts
@@ -17,9 +17,9 @@
 import {loadTimeData} from '//resources/js/load_time_data.js';
 import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {FontsBrowserProxyImpl, FontsData} from '/shared/settings/appearance_page/fonts_browser_proxy.js';
+import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
 
-import {DropdownMenuOptionList} from '../controls/settings_dropdown_menu.js';
 import {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js';
 
 import {getTemplate} from './captions_subpage.html.js';
diff --git a/chrome/browser/resources/settings/a11y_page/live_caption_section.ts b/chrome/browser/resources/settings/a11y_page/live_caption_section.ts
index ffa2f57..78ac693 100644
--- a/chrome/browser/resources/settings/a11y_page/live_caption_section.ts
+++ b/chrome/browser/resources/settings/a11y_page/live_caption_section.ts
@@ -27,7 +27,7 @@
 
 // clang-format off
 // <if expr="not is_chromeos">
-import '../controls/settings_dropdown_menu.js';
+import '/shared/settings/controls/settings_dropdown_menu.js';
 import './live_translate_section.js';
 import '../languages_page/add_languages_dialog.js';
 
@@ -37,9 +37,7 @@
 import {ListPropertyUpdateMixin} from 'chrome://resources/cr_elements/list_property_update_mixin.js';
 import {assert} from 'chrome://resources/js/assert_ts.js';
 import {focusWithoutInk} from 'chrome://resources/js/focus_without_ink.js';
-
-import {DropdownMenuOptionList} from '../controls/settings_dropdown_menu.js';
-
+import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {DomRepeatEvent} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 // </if>
 // clang-format on
diff --git a/chrome/browser/resources/settings/a11y_page/live_translate_section.ts b/chrome/browser/resources/settings/a11y_page/live_translate_section.ts
index 29256b2..f944d99 100644
--- a/chrome/browser/resources/settings/a11y_page/live_translate_section.ts
+++ b/chrome/browser/resources/settings/a11y_page/live_translate_section.ts
@@ -11,15 +11,15 @@
  */
 
 import '//resources/cr_elements/cr_shared_style.css.js';
-import '../controls/settings_dropdown_menu.js';
+import '/shared/settings/controls/settings_dropdown_menu.js';
 import '../controls/settings_toggle_button.js';
 import '../settings_shared.css.js';
 
 import {WebUiListenerMixin} from '//resources/cr_elements/web_ui_listener_mixin.js';
 import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
 
-import {DropdownMenuOptionList} from '../controls/settings_dropdown_menu.js';
 import {loadTimeData} from '../i18n_setup.js';
 import {LanguageHelper, LanguagesModel} from '../languages_page/languages_types.js';
 
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts
index 74a047cf..7453f30 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts
+++ b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts
@@ -6,15 +6,14 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import '../controls/settings_slider.js';
 import '../settings_shared.css.js';
-import '../controls/settings_dropdown_menu.js';
+import '/shared/settings/controls/settings_dropdown_menu.js';
 
 import {FontsBrowserProxy, FontsBrowserProxyImpl, FontsData} from '/shared/settings/appearance_page/fonts_browser_proxy.js';
+import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {SliderTick} from 'chrome://resources/cr_elements/cr_slider/cr_slider.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {DropdownMenuOptionList} from '../controls/settings_dropdown_menu.js';
-
 import {getTemplate} from './appearance_fonts_page.html.js';
 
 
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.ts b/chrome/browser/resources/settings/appearance_page/appearance_page.ts
index f208e489..0202c3c 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_page.ts
+++ b/chrome/browser/resources/settings/appearance_page/appearance_page.ts
@@ -16,15 +16,15 @@
 import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 import './home_url_input.js';
-import '../controls/settings_dropdown_menu.js';
+import '/shared/settings/controls/settings_dropdown_menu.js';
 
+import {DropdownMenuOptionList, SettingsDropdownMenuElement} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {assert} from 'chrome://resources/js/assert_ts.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {BaseMixin} from '../base_mixin.js';
-import {DropdownMenuOptionList, SettingsDropdownMenuElement} from '../controls/settings_dropdown_menu.js';
 import {loadTimeData} from '../i18n_setup.js';
 import {AppearancePageVisibility} from '../page_visibility.js';
 import {routes} from '../route.js';
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_import_dialog.html b/chrome/browser/resources/settings/autofill_page/passwords_import_dialog.html
index 195f65b2..a6bd1227 100644
--- a/chrome/browser/resources/settings/autofill_page/passwords_import_dialog.html
+++ b/chrome/browser/resources/settings/autofill_page/passwords_import_dialog.html
@@ -7,13 +7,15 @@
     display: flex;
   }
 
-  iron-icon,
-  site-favicon {
-    margin-inline-end: 10px;
+  iron-icon {
+    height: 16px;
+    padding-inline-end: 10px;
+    width: 24px;
   }
 
   site-favicon {
     margin-block: auto;
+    margin-inline-end: 10px;
   }
 
   .failed-row {
@@ -50,7 +52,6 @@
   }
 
   .error-icon {
-    height: 16px;
     margin-block: auto;
     --iron-icon-fill-color: var(--settings-error-color);
   }
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_import_dialog.ts b/chrome/browser/resources/settings/autofill_page/passwords_import_dialog.ts
index cd08772d..fc52e82 100644
--- a/chrome/browser/resources/settings/autofill_page/passwords_import_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/passwords_import_dialog.ts
@@ -336,7 +336,7 @@
                 this.results_.displayedEntries.length);
         this.conflicts_ = this.results_.displayedEntries;
         this.dialogState = ImportDialogState.CONFLICTS;
-        return;
+        break;
       case chrome.passwordsPrivate.ImportResultsStatus.MAX_FILE_SIZE:
         this.descriptionText_ =
             this.i18nAdvanced('importPasswordsFileSizeExceeded');
diff --git a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.ts b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.ts
index b65644a..4089814 100644
--- a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.ts
+++ b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.ts
@@ -7,15 +7,14 @@
  */
 
 import '../../settings_shared.css.js';
-import '../../controls/settings_dropdown_menu.js';
+import '/shared/settings/controls/settings_dropdown_menu.js';
 
+import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
 import {CrSettingsPrefs} from 'chrome://resources/cr_components/settings_prefs/prefs_types.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {DropdownMenuOptionList} from '../../controls/settings_dropdown_menu.js';
-
 import {TimeZoneBrowserProxyImpl} from './timezone_browser_proxy.js';
 import {getTemplate} from './timezone_selector.html.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.ts b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.ts
index 21ab1ab..22d7e4e 100644
--- a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.ts
+++ b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.ts
@@ -8,17 +8,17 @@
  */
 import 'chrome://resources/cr_components/settings_prefs/prefs.js';
 import '../../controls/controlled_radio_button.js';
-import '../../controls/settings_dropdown_menu.js';
+import '/shared/settings/controls/settings_dropdown_menu.js';
 import '../../controls/settings_radio_group.js';
 import '../../settings_shared.css.js';
 import './timezone_selector.js';
 
+import {SettingsDropdownMenuElement} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
 import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {SettingsDropdownMenuElement} from '../../controls/settings_dropdown_menu.js';
 import {DeepLinkingMixin} from '../deep_linking_mixin.js';
 import {Setting} from '../mojom-webui/setting.mojom-webui.js';
 import {routes} from '../os_settings_routes.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/display.ts b/chrome/browser/resources/settings/chromeos/device_page/display.ts
index 18cc0264..2f05ef7 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/display.ts
+++ b/chrome/browser/resources/settings/chromeos/device_page/display.ts
@@ -20,10 +20,11 @@
 import '../../controls/settings_slider.js';
 import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
-import '../../controls/settings_dropdown_menu.js';
+import '/shared/settings/controls/settings_dropdown_menu.js';
 import 'chrome://resources/cr_elements/cr_slider/cr_slider.js';
 import 'chrome://resources/cr_elements/cr_shared_style.css.js';
 
+import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
 import {CrCheckboxElement} from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js';
 import {CrSliderElement, SliderTick} from 'chrome://resources/cr_elements/cr_slider/cr_slider.js';
@@ -33,7 +34,6 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {flush, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {DropdownMenuOptionList} from '../../controls/settings_dropdown_menu.js';
 import {SettingsSliderElement} from '../../controls/settings_slider.js';
 import {assertExists, cast, castExists} from '../assert_extras.js';
 import {DeepLinkingMixin} from '../deep_linking_mixin.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts b/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts
index c19664c..dc5e8b4 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts
+++ b/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts
@@ -12,14 +12,14 @@
 import '../../controls/settings_slider.js';
 import '../../controls/settings_toggle_button.js';
 import '../../settings_shared.css.js';
-import '../../controls/settings_dropdown_menu.js';
+import '/shared/settings/controls/settings_dropdown_menu.js';
 
+import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
 import {focusWithoutInk} from 'chrome://resources/js/focus_without_ink.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {afterNextRender, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {DropdownMenuOptionList} from '../../controls/settings_dropdown_menu.js';
 import {castExists} from '../assert_extras.js';
 import {DeepLinkingMixin} from '../deep_linking_mixin.js';
 import {FocusConfig} from '../focus_config.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/keyboard_remap_modifier_key_row.ts b/chrome/browser/resources/settings/chromeos/device_page/keyboard_remap_modifier_key_row.ts
index 0b7dee46..95eebf2 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/keyboard_remap_modifier_key_row.ts
+++ b/chrome/browser/resources/settings/chromeos/device_page/keyboard_remap_modifier_key_row.ts
@@ -11,17 +11,16 @@
 import 'chrome://resources/cr_components/settings_prefs/prefs.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import '../../settings_shared.css.js';
-import '../../controls/settings_dropdown_menu.js';
+import '/shared/settings/controls/settings_dropdown_menu.js';
 import '../../settings_shared.css.js';
 import '../os_settings_icons.html.js';
 
+import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {assertNotReached} from 'chrome://resources/js/assert_ts.js';
 import {PolymerElementProperties} from 'chrome://resources/polymer/v3_0/polymer/interfaces.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {DropdownMenuOptionList} from '../../controls/settings_dropdown_menu.js';
-
 import {MetaKey, ModifierKey} from './input_device_settings_types.js';
 import {getTemplate} from './keyboard_remap_modifier_key_row.html.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts b/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts
index 624c03e..85406e3d 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts
+++ b/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_components/settings_prefs/prefs.js';
 import '../../icons.html.js';
 import '../../settings_shared.css.js';
-import '../../controls/settings_dropdown_menu.js';
+import '/shared/settings/controls/settings_dropdown_menu.js';
 import './input_device_settings_shared.css.js';
 import './keyboard_remap_modifier_key_row.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/bluetooth_braille_display_ui.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/bluetooth_braille_display_ui.ts
index 51497df..a75da982 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/bluetooth_braille_display_ui.ts
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/bluetooth_braille_display_ui.ts
@@ -11,6 +11,7 @@
 import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
 import '../../settings_shared.css.js';
 
+import {DropdownMenuOptionList, SettingsDropdownMenuElement} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
 import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js';
@@ -19,7 +20,6 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {DropdownMenuOptionList, SettingsDropdownMenuElement} from '../../controls/settings_dropdown_menu.js';
 import {DeepLinkingMixin} from '../deep_linking_mixin.js';
 
 import {BluetoothBrailleDisplayListener, BluetoothBrailleDisplayManager} from './bluetooth_braille_display_manager.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/chromevox_subpage.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/chromevox_subpage.ts
index 57e36c4d..9aa30b0 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/chromevox_subpage.ts
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/chromevox_subpage.ts
@@ -13,6 +13,7 @@
 import '../../settings_shared.css.js';
 import './bluetooth_braille_display_ui.js';
 
+import {DropdownMenuOptionList, SettingsDropdownMenuElement} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
 import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
@@ -20,7 +21,6 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {DropdownMenuOptionList, SettingsDropdownMenuElement} from '../../controls/settings_dropdown_menu.js';
 import {SettingsToggleButtonElement} from '../../controls/settings_toggle_button.js';
 import {DeepLinkingMixin} from '../deep_linking_mixin.js';
 import {routes} from '../os_settings_routes.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/select_to_speak_subpage.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/select_to_speak_subpage.ts
index d8474e4..7b141983 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/select_to_speak_subpage.ts
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/select_to_speak_subpage.ts
@@ -12,13 +12,13 @@
 import '../../settings_shared.css.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 
+import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {DropdownMenuOptionList} from '../../controls/settings_dropdown_menu.js';
 import {SettingsToggleButtonElement} from '../../controls/settings_toggle_button.js';
 import {DeepLinkingMixin} from '../deep_linking_mixin.js';
 import {Setting} from '../mojom-webui/setting.mojom-webui.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.ts b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.ts
index 97d4f72..73f3e158 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.ts
@@ -15,7 +15,7 @@
 import 'chrome://resources/cr_elements/policy/cr_policy_pref_indicator.js';
 import '../os_settings_page/os_settings_animated_pages.js';
 import '../os_settings_page/os_settings_subpage.js';
-import '../../controls/settings_dropdown_menu.js';
+import '/shared/settings/controls/settings_dropdown_menu.js';
 import '../../settings_shared.css.js';
 import '../../settings_shared.css.js';
 import '../guest_os/guest_os_shared_usb_devices.js';
@@ -25,6 +25,7 @@
 import './app_management_page/app_management_page.js';
 import './app_management_page/app_detail_view.js';
 
+import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {App} from 'chrome://resources/cr_components/app_management/app_management.mojom-webui.js';
 import {AppManagementEntryPoint, AppManagementEntryPointsHistogramName} from 'chrome://resources/cr_components/app_management/constants.js';
 import {getAppIcon, getSelectedApp} from 'chrome://resources/cr_components/app_management/util.js';
@@ -34,7 +35,6 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {DropdownMenuOptionList} from '../../controls/settings_dropdown_menu.js';
 import {DeepLinkingMixin} from '../deep_linking_mixin.js';
 import {App as AppWithNotifications, AppNotificationsHandlerInterface, AppNotificationsObserverReceiver, Readiness} from '../mojom-webui/app_notification_handler.mojom-webui.js';
 import {Setting} from '../mojom-webui/setting.mojom-webui.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni
index d21a0d0..8319a21 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.gni
+++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -256,7 +256,6 @@
   "controls/controlled_button.ts",
   "controls/controlled_radio_button.ts",
   "controls/password_prompt_dialog.ts",
-  "controls/settings_dropdown_menu.ts",
   "controls/settings_radio_group.ts",
   "controls/settings_slider.ts",
   "controls/settings_toggle_button.ts",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.ts b/chrome/browser/resources/settings/chromeos/os_settings.ts
index 09d0fab..1c286ac 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.ts
+++ b/chrome/browser/resources/settings/chromeos/os_settings.ts
@@ -97,6 +97,7 @@
 export * as nearbyShareMojom from '/shared/nearby_share.mojom-webui.js';
 export {getNearbyShareSettings, observeNearbyShareSettings, setNearbyShareSettingsForTesting} from '/shared/nearby_share_settings.js';
 export {NearbySettings, NearbyShareSettingsMixin} from '/shared/nearby_share_settings_mixin.js';
+export {SettingsDropdownMenuElement} from '/shared/settings/controls/settings_dropdown_menu.js';
 export {LifetimeBrowserProxyImpl} from '/shared/settings/lifetime_browser_proxy.js';
 export {ProfileInfoBrowserProxyImpl} from '/shared/settings/people_page/profile_info_browser_proxy.js';
 export {PageStatus, StatusAction, StoredAccount, SyncBrowserProxy, SyncBrowserProxyImpl, SyncPrefs, SyncStatus} from '/shared/settings/people_page/sync_browser_proxy.js';
@@ -106,7 +107,6 @@
 export {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 export {CrToggleElement} from 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js';
 export {OpenWindowProxyImpl} from 'chrome://resources/js/open_window_proxy.js';
-export {SettingsDropdownMenuElement} from '../controls/settings_dropdown_menu.js';
 export {SettingsSliderElement} from '../controls/settings_slider.js';
 export {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js';
 export {setCrosAudioConfigForTesting} from './device_page/cros_audio_config.js';
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts
index 613d7a7..d2104610 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts
@@ -20,6 +20,7 @@
 import '../settings_shared.css.js';
 
 import {PrefControlMixinInterface} from '/shared/settings/controls/pref_control_mixin.js';
+import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js';
 import {StatusAction, SyncBrowserProxy, SyncBrowserProxyImpl, SyncStatus} from '/shared/settings/people_page/sync_browser_proxy.js';
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
@@ -32,7 +33,6 @@
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {SettingsCheckboxElement} from '../controls/settings_checkbox.js';
-import {DropdownMenuOptionList} from '../controls/settings_dropdown_menu.js';
 import {loadTimeData} from '../i18n_setup.js';
 import {routes} from '../route.js';
 import {Route, RouteObserverMixin, Router} from '../router.js';
diff --git a/chrome/browser/resources/settings/icons.html b/chrome/browser/resources/settings/icons.html
index 01ae72dd..064f1ab 100644
--- a/chrome/browser/resources/settings/icons.html
+++ b/chrome/browser/resources/settings/icons.html
@@ -8,6 +8,7 @@
       <g id="account-attention"><path d="M15.0714 6.66667V3.5H16.5V7.38889H15.0714V6.66667ZM15.0714 9.83333H16.5V8.38889H15.0714V9.83333ZM9.71429 10.9444C11.6214 10.9444 15.4286 11.9122 15.4286 13.8333V16H4V13.8333C4 11.9122 7.80714 10.9444 9.71429 10.9444ZM9.71429 4.44444C10.472 4.44444 11.1988 4.74881 11.7346 5.29058C12.2704 5.83235 12.5714 6.56715 12.5714 7.33333C12.5714 8.09951 12.2704 8.83431 11.7346 9.37609C11.1988 9.91786 10.472 10.2222 9.71429 10.2222C8.95652 10.2222 8.2298 9.91786 7.69398 9.37609C7.15816 8.83431 6.85714 8.09951 6.85714 7.33333C6.85714 6.56715 7.15816 5.83235 7.69398 5.29058C8.2298 4.74881 8.95652 4.44444 9.71429 4.44444ZM9.71429 12.3167C7.59286 12.3167 5.35714 13.3711 5.35714 13.8333V14.6278H14.0714V13.8333C14.0714 13.3711 11.8357 12.3167 9.71429 12.3167ZM9.71429 5.81667C9.31646 5.81667 8.93493 5.97646 8.65363 6.26089C8.37232 6.54532 8.21429 6.93109 8.21429 7.33333C8.21429 7.73558 8.37232 8.12135 8.65363 8.40578C8.93493 8.69021 9.31646 8.85 9.71429 8.85C10.1121 8.85 10.4936 8.69021 10.7749 8.40578C11.0563 8.12135 11.2143 7.73558 11.2143 7.33333C11.2143 6.93109 11.0563 6.54532 10.7749 6.26089C10.4936 5.97646 10.1121 5.81667 9.71429 5.81667Z"></path></g>
       <g id="account-circle"><path fill-rule="evenodd" clip-rule="evenodd" d="M10 1.667A8.336 8.336 0 0 0 1.667 10c0 4.6 3.733 8.333 8.333 8.333S18.333 14.6 18.333 10 14.6 1.667 10 1.667zM5.89 15.233c.359-.75 2.542-1.483 4.109-1.483 1.566 0 3.758.733 4.108 1.483A6.578 6.578 0 0 1 10 16.667a6.577 6.577 0 0 1-4.109-1.434zM10 12.083c1.216 0 4.108.492 5.3 1.942A6.625 6.625 0 0 0 16.666 10 6.676 6.676 0 0 0 10 3.333 6.676 6.676 0 0 0 3.333 10c0 1.517.517 2.908 1.367 4.025 1.191-1.45 4.083-1.942 5.3-1.942zM10 5a2.91 2.91 0 0 0-2.917 2.917A2.91 2.91 0 0 0 10 10.833a2.91 2.91 0 0 0 2.916-2.916A2.91 2.91 0 0 0 10 5zM8.75 7.917c0 .691.558 1.25 1.25 1.25.691 0 1.25-.559 1.25-1.25 0-.692-.559-1.25-1.25-1.25-.692 0-1.25.558-1.25 1.25z"></path></g>
       <g id="ads-click"><path d="M10 15q-2.083 0-3.542-1.458Q5 12.083 5 10q0-2.083 1.458-3.542Q7.917 5 10 5q2.083 0 3.542 1.458Q15 7.917 15 10l-1.521-.5q-.187-1.292-1.177-2.146Q11.312 6.5 10 6.5q-1.458 0-2.479 1.021Q6.5 8.542 6.5 10q0 1.312.854 2.302T9.5 13.479Zm.917 2.938q-.229.041-.459.052-.229.01-.458.01-1.646 0-3.104-.625-1.458-.625-2.552-1.719t-1.719-2.552Q2 11.646 2 10q0-1.667.625-3.115.625-1.447 1.719-2.541Q5.438 3.25 6.896 2.625T10 2q1.667 0 3.115.625 1.447.625 2.541 1.719 1.094 1.094 1.719 2.541Q18 8.333 18 10q0 .229-.01.458-.011.23-.032.459l-1.458-.459V10q0-2.708-1.896-4.604T10 3.5q-2.708 0-4.604 1.896T3.5 10q0 2.708 1.896 4.604T10 16.5q.104 0 .229-.01.125-.011.229-.011Zm6.166.562-3.458-3.479L12.5 18 10 10l8 2.5-2.979 1.104 3.479 3.479Z"></path></g>
+      <g id="archive"><path d="M4.5 17C4.08333 17 3.72917 16.8542 3.4375 16.5625C3.14583 16.2708 3 15.9167 3 15.5V5.625C3 5.43055 3.03472 5.24306 3.10417 5.0625C3.1875 4.86805 3.29861 4.70139 3.4375 4.5625L4.5625 3.4375C4.70139 3.29861 4.86111 3.19444 5.04167 3.125C5.23611 3.04167 5.43056 3 5.625 3H14.375C14.5694 3 14.7569 3.04167 14.9375 3.125C15.1319 3.19444 15.2986 3.29861 15.4375 3.4375L16.5625 4.5625C16.7014 4.70139 16.8056 4.86805 16.875 5.0625C16.9583 5.24306 17 5.43055 17 5.625V15.5C17 15.9167 16.8542 16.2708 16.5625 16.5625C16.2708 16.8542 15.9167 17 15.5 17H4.5ZM4.625 5.5H15.375L14.375 4.5H5.625L4.625 5.5ZM4.5 7V15.5H15.5V7H4.5ZM10 14.25L13 11.25L11.9375 10.1875L10.75 11.375V8.25H9.25V11.375L8.0625 10.1875L7 11.25L10 14.25ZM4.5 15.5H15.5H4.5Z"></path></g>
       <g id="auto-delete"><path d="M6.5 5.5v10ZM9.396 17H6.5q-.625 0-1.062-.438Q5 16.125 5 15.5v-10H4V4h4V3h4v1h4v1.5h-1v3.104q-.375-.062-.75-.094-.375-.031-.75.011V5.5h-7v10h2.208q.104.396.282.771.177.375.406.729ZM8 14h.5q0-1.458.5-2.312l.5-.855V7H8Zm2.5-4.25q.292-.229.677-.469.385-.239.823-.406V7h-1.5ZM14 18q-1.667 0-2.833-1.167Q10 15.667 10 14q0-1.667 1.167-2.833Q12.333 10 14 10q1.667 0 2.833 1.167Q18 12.333 18 14q0 1.667-1.167 2.833Q15.667 18 14 18Zm1.146-2.146.708-.708-1.354-1.354V12h-1v2.208Z"></path></g>
       <g id="background-replace"><path d="M3 8.104V6.333L6.333 3h1.792Zm0-3.896V3h1.208Zm10.188 1.521Q13 5.5 12.76 5.281q-.239-.219-.51-.385L14.167 3h1.791Zm-8.73 6.938 2.063-2.042q.167.25.364.458.198.209.365.375l-.25.25q-.625.146-1.312.407-.688.26-1.23.552Zm9.667-3.979q0-.021.021-.136.021-.114.021-.156 0-.354-.052-.688-.053-.333-.157-.625L17 4.062v1.771Zm-5.354-4.23L10.271 3h1.771l-1.313 1.312q-.187-.041-.364-.052-.177-.01-.344-.01-.354 0-.667.052-.312.052-.583.156Zm-5.729 7.521v-1.771l3.062-3.041q-.104.291-.166.604-.063.312-.063.625 0 .166.01.333.011.167.053.354Zm13.729 1.833q-.167-.25-.365-.479-.198-.229-.489-.416L17 11.854v1.75ZM14.5 12.188q-.125-.042-.292-.105-.166-.062-.312-.104-.167-.062-.354-.114-.188-.053-.375-.094L17 7.938v1.791Zm-4.479-.688q-1.313 0-2.219-.917-.906-.916-.906-2.187 0-1.292.906-2.208.906-.917 2.219-.917 1.291 0 2.198.917.906.916.906 2.208 0 1.271-.906 2.187-.907.917-2.198.917Zm0-1.5q.667 0 1.135-.469.469-.469.469-1.135 0-.667-.469-1.146-.468-.479-1.135-.479t-1.146.479q-.479.479-.479 1.146 0 .666.479 1.135t1.146.469ZM4 17v-1.5q0-.604.323-1.125t.865-.813q1.124-.583 2.333-.895 1.208-.313 2.479-.313 1.25 0 2.458.313 1.209.312 2.334.895.541.292.875.813.333.521.333 1.125V17Zm1.5-1.5h9q0-.208-.125-.354t-.292-.25q-.937-.5-1.979-.771T10 13.854q-1.062 0-2.104.261-1.042.26-1.979.76-.188.104-.302.26-.115.157-.115.365Z"></path></g>
       <g id="bar-chart"><path fill-rule="evenodd" clip-rule="evenodd" d="M4 16V8h3v8Zm4.5 0V4h3v12Zm4.5 0v-6h3v6Z"></path></g>
@@ -38,6 +39,7 @@
       <g id="security"><path fill-rule="evenodd" clip-rule="evenodd" d="M3.183 4.7L10 1.667 16.816 4.7v4.542c0 4.208-2.908 8.133-6.816 9.091-3.909-.958-6.817-4.883-6.817-9.091V4.7zM15.3 9.992H10V3.325L4.7 5.683V10l5.3-.008v6.775c2.816-.875 4.9-3.65 5.3-6.775z"></path></g>
       <g id="shoppingcart"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.1585 10.8333H12.8502C13.4502 10.8333 14.0002 10.5083 14.3002 9.99167L17.0335 5.20001C17.2502 4.81667 17.2502 4.33334 17.0335 3.95001C16.8168 3.56667 16.3918 3.33334 15.9502 3.33334H4.61683L3.87516 1.66667H0.833496V3.33334H2.79183L5.74183 9.98334L4.85016 11.7583C4.59183 12.275 4.61683 12.8833 4.92516 13.3833C5.2335 13.8833 5.7585 14.175 6.34183 14.175H15.8335V12.5083H6.35016L7.1835 10.8417H12.1585V10.8333ZM7.50016 16.6667C7.50016 17.5871 6.75397 18.3333 5.8335 18.3333C4.91302 18.3333 4.16683 17.5871 4.16683 16.6667C4.16683 15.7462 4.91302 15 5.8335 15C6.75397 15 7.50016 15.7462 7.50016 16.6667ZM15.8335 16.6667C15.8335 17.5871 15.0873 18.3333 14.1668 18.3333C13.2464 18.3333 12.5002 17.5871 12.5002 16.6667C12.5002 15.7462 13.2464 15 14.1668 15C15.0873 15 15.8335 15.7462 15.8335 16.6667ZM12.8502 9.16667L15.2335 5.00001H5.3585L7.2085 9.16667H12.8502Z"></path></g>
       <g id="spam"><path d="M15.0714 6.66667V3.5H16.5V7.38889H15.0714V6.66667ZM15.0714 9.83333H16.5V8.38889H15.0714V9.83333ZM9.71429 10.9444C11.6214 10.9444 15.4286 11.9122 15.4286 13.8333V16H4V13.8333C4 11.9122 7.80714 10.9444 9.71429 10.9444ZM9.71429 4.44444C10.472 4.44444 11.1988 4.74881 11.7346 5.29058C12.2704 5.83235 12.5714 6.56715 12.5714 7.33333C12.5714 8.09951 12.2704 8.83431 11.7346 9.37609C11.1988 9.91786 10.472 10.2222 9.71429 10.2222C8.95652 10.2222 8.2298 9.91786 7.69398 9.37609C7.15816 8.83431 6.85714 8.09951 6.85714 7.33333C6.85714 6.56715 7.15816 5.83235 7.69398 5.29058C8.2298 4.74881 8.95652 4.44444 9.71429 4.44444ZM9.71429 12.3167C7.59286 12.3167 5.35714 13.3711 5.35714 13.8333V14.6278H14.0714V13.8333C14.0714 13.3711 11.8357 12.3167 9.71429 12.3167ZM9.71429 5.81667C9.31646 5.81667 8.93493 5.97646 8.65363 6.26089C8.37232 6.54532 8.21429 6.93109 8.21429 7.33333C8.21429 7.73558 8.37232 8.12135 8.65363 8.40578C8.93493 8.69021 9.31646 8.85 9.71429 8.85C10.1121 8.85 10.4936 8.69021 10.7749 8.40578C11.0563 8.12135 11.2143 7.73558 11.2143 7.33333C11.2143 6.93109 11.0563 6.54532 10.7749 6.26089C10.4936 5.97646 10.1121 5.81667 9.71429 5.81667Z"></path></g>
+      <g id="timer"><path d="M7.5 3V1.5H12.5V3H7.5ZM9.25 12H10.75V7H9.25V12ZM10 18C9.02778 18 8.11806 17.8194 7.27083 17.4583C6.42361 17.0833 5.68056 16.5833 5.04167 15.9583C4.41667 15.3194 3.91667 14.5764 3.54167 13.7292C3.18056 12.8819 3 11.9722 3 11C3 10.0278 3.18056 9.11806 3.54167 8.27083C3.91667 7.42361 4.41667 6.6875 5.04167 6.0625C5.68056 5.42361 6.42361 4.92361 7.27083 4.5625C8.11806 4.1875 9.02778 4 10 4C10.8056 4 11.5764 4.13889 12.3125 4.41667C13.0625 4.68055 13.7569 5.05555 14.3958 5.54167L15.4792 4.47917L16.5208 5.52083L15.4583 6.60417C15.9444 7.22917 16.3194 7.91667 16.5833 8.66667C16.8611 9.41667 17 10.1944 17 11C17 11.9722 16.8125 12.8819 16.4375 13.7292C16.0764 14.5764 15.5764 15.3194 14.9375 15.9583C14.3125 16.5833 13.5764 17.0833 12.7292 17.4583C11.8819 17.8194 10.9722 18 10 18ZM10 16.5C11.5278 16.5 12.8264 15.9653 13.8958 14.8958C14.9653 13.8264 15.5 12.5278 15.5 11C15.5 9.47222 14.9653 8.17361 13.8958 7.10417C12.8264 6.03472 11.5278 5.5 10 5.5C8.47222 5.5 7.17361 6.03472 6.10417 7.10417C5.03472 8.17361 4.5 9.47222 4.5 11C4.5 12.5278 5.03472 13.8264 6.10417 14.8958C7.17361 15.9653 8.47222 16.5 10 16.5Z"></path></g>
       <g id="undo"><path d="M11.8335 15.8333H5.8335V14.5833H11.8543C12.8266 14.5833 13.6634 14.2604 14.3647 13.6146C15.0661 12.9687 15.4168 12.1666 15.4168 11.2083C15.4168 10.25 15.0661 9.4479 14.3647 8.80206C13.6634 8.15623 12.8266 7.83331 11.8543 7.83331H5.7085L8.0835 10.2083L7.2085 11.0833L3.3335 7.20831L7.2085 3.33331L8.0835 4.20831L5.7085 6.58331H11.8335C13.1529 6.58331 14.2884 7.02776 15.2397 7.91665C16.1911 8.80554 16.6668 9.90276 16.6668 11.2083C16.6668 12.5139 16.1911 13.6111 15.2397 14.5C14.2884 15.3889 13.1529 15.8333 11.8335 15.8333Z"></path></g>
       <g id="volume-down"><path fill-rule="evenodd" clip-rule="evenodd" d="M1 13H4.46667L8 16.5V3.5L4.46667 7H1V13ZM10 6.5V13.5C11.776 12.8652 12.5 11.0043 12.5 10C12.5 8.99565 11.776 7.14348 10 6.5Z"></path></g>
       <g id="volume-up"><path fill-rule="evenodd" clip-rule="evenodd" d="M1 13H4.46667L8 16.4V3.40002L4.46667 7.00002H1V13ZM10 6.40002V13.4C11.776 12.7652 12.5 10.9044 12.5 9.90002C12.5 8.89568 11.776 7.0435 10 6.40002ZM10 4.16171C12.4771 4.89717 14.5 7.18908 14.5 9.90002C14.5 12.611 12.4771 14.9029 10 15.6383V17.4C13.4371 16.6218 16 13.5602 16 9.90002C16 6.23982 13.4371 3.17825 10 2.40002V4.16171Z"></path></g>
diff --git a/chrome/browser/resources/settings/privacy_page/anti_abuse_page.html b/chrome/browser/resources/settings/privacy_page/anti_abuse_page.html
index a1a8613..758eece 100644
--- a/chrome/browser/resources/settings/privacy_page/anti_abuse_page.html
+++ b/chrome/browser/resources/settings/privacy_page/anti_abuse_page.html
@@ -42,19 +42,24 @@
   <div class="info-section">
     <h2 class="info-header">$i18n{antiAbuseWhenOnHeader}</h2>
     <div class="info-text-container">
-      <iron-icon icon="settings20:dashboard" aria-hidden="true"></iron-icon>
+      <iron-icon icon="settings20:archive" aria-hidden="true"></iron-icon>
       <div>$i18n{antiAbuseWhenOnSectionOne}</div>
     </div>
     <div class="info-text-container">
-      <iron-icon icon="settings20:background-replace" aria-hidden="true">
+      <iron-icon icon="settings20:dashboard" aria-hidden="true">
       </iron-icon>
       <div>$i18n{antiAbuseWhenOnSectionTwo}</div>
     </div>
+    <div class="info-text-container">
+      <iron-icon icon="settings20:timer" aria-hidden="true">
+      </iron-icon>
+      <div>$i18n{antiAbuseWhenOnSectionThree}</div>
+    </div>
   </div>
   <div class="info-section">
     <h2 class="info-header">$i18n{antiAbuseThingsToConsiderHeader}</h2>
     <div class="info-text-container">
-      <iron-icon icon="settings20:check-circle-outline" aria-hidden="true">
+      <iron-icon icon="settings20:background-replace" aria-hidden="true">
       </iron-icon>
       <div>$i18n{antiAbuseThingsToConsiderSectionOne}</div>
     </div>
diff --git a/chrome/browser/resources/settings/settings.ts b/chrome/browser/resources/settings/settings.ts
index a2a4a02a..0021bc8 100644
--- a/chrome/browser/resources/settings/settings.ts
+++ b/chrome/browser/resources/settings/settings.ts
@@ -6,6 +6,7 @@
 
 export {ExtensionControlledIndicatorElement} from '/shared/settings/controls/extension_controlled_indicator.js';
 export {DEFAULT_CHECKED_VALUE, DEFAULT_UNCHECKED_VALUE} from '/shared/settings/controls/settings_boolean_control_mixin.js';
+export {SettingsDropdownMenuElement} from '/shared/settings/controls/settings_dropdown_menu.js';
 export {ExtensionControlBrowserProxy, ExtensionControlBrowserProxyImpl} from '/shared/settings/extension_control_browser_proxy.js';
 export {LifetimeBrowserProxy, LifetimeBrowserProxyImpl} from '/shared/settings/lifetime_browser_proxy.js';
 export {ProfileInfo, ProfileInfoBrowserProxy, ProfileInfoBrowserProxyImpl} from '/shared/settings/people_page/profile_info_browser_proxy.js';
@@ -43,7 +44,6 @@
 export {BaseMixin} from './base_mixin.js';
 export {SettingsBasicPageElement} from './basic_page/basic_page.js';
 export {ControlledRadioButtonElement} from './controls/controlled_radio_button.js';
-export {SettingsDropdownMenuElement} from './controls/settings_dropdown_menu.js';
 export {SettingsIdleLoadElement} from './controls/settings_idle_load.js';
 export {SettingsToggleButtonElement} from './controls/settings_toggle_button.js';
 // <if expr="not is_chromeos">
diff --git a/chrome/browser/resources/settings_shared/BUILD.gn b/chrome/browser/resources/settings_shared/BUILD.gn
index 3d6582a..51eff5a 100644
--- a/chrome/browser/resources/settings_shared/BUILD.gn
+++ b/chrome/browser/resources/settings_shared/BUILD.gn
@@ -10,7 +10,10 @@
   grd_prefix = "settings_shared"
   grd_resource_path_prefix = "shared/settings"
 
-  web_component_files = [ "controls/extension_controlled_indicator.ts" ]
+  web_component_files = [
+    "controls/extension_controlled_indicator.ts",
+    "controls/settings_dropdown_menu.ts",
+  ]
 
   non_web_component_files = [
     "extension_control_browser_proxy.ts",
diff --git a/chrome/browser/resources/settings/controls/settings_dropdown_menu.html b/chrome/browser/resources/settings_shared/controls/settings_dropdown_menu.html
similarity index 100%
rename from chrome/browser/resources/settings/controls/settings_dropdown_menu.html
rename to chrome/browser/resources/settings_shared/controls/settings_dropdown_menu.html
diff --git a/chrome/browser/resources/settings/controls/settings_dropdown_menu.ts b/chrome/browser/resources/settings_shared/controls/settings_dropdown_menu.ts
similarity index 96%
rename from chrome/browser/resources/settings/controls/settings_dropdown_menu.ts
rename to chrome/browser/resources/settings_shared/controls/settings_dropdown_menu.ts
index 24d06d0f..c6883dc 100644
--- a/chrome/browser/resources/settings/controls/settings_dropdown_menu.ts
+++ b/chrome/browser/resources/settings_shared/controls/settings_dropdown_menu.ts
@@ -21,10 +21,10 @@
 
 import {assert} from '//resources/js/assert_ts.js';
 import {microTask, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {CrPolicyPrefMixin} from '/shared/settings/controls/cr_policy_pref_mixin.js';
-import {PrefControlMixin} from '/shared/settings/controls/pref_control_mixin.js';
 import {prefToString, stringToPrefValue} from 'chrome://resources/cr_components/settings_prefs/pref_util.js';
 
+import {CrPolicyPrefMixin} from './cr_policy_pref_mixin.js';
+import {PrefControlMixin} from './pref_control_mixin.js';
 import {getTemplate} from './settings_dropdown_menu.html.js';
 
 /**
diff --git a/chrome/browser/safe_browsing/tailored_security/notification_handler_desktop.cc b/chrome/browser/safe_browsing/tailored_security/notification_handler_desktop.cc
index 4bb2014..054c3576 100644
--- a/chrome/browser/safe_browsing/tailored_security/notification_handler_desktop.cc
+++ b/chrome/browser/safe_browsing/tailored_security/notification_handler_desktop.cc
@@ -17,8 +17,10 @@
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
+#include "chrome/grit/google_chrome_strings.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/core/browser/tailored_security_service/tailored_security_outcome.h"
+#include "components/safe_browsing/core/common/features.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/vector_icons/vector_icons.h"
@@ -114,8 +116,13 @@
       kTailoredSecurityUnconsentedPromotionNotificationId;
   const std::u16string& title = l10n_util::GetStringUTF16(
       IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_NOTIFICATION_TITLE);
-  const std::u16string& description = l10n_util::GetStringUTF16(
-      IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_NOTIFICATION_DESCRIPTION);
+  const std::u16string& description =
+      (base::FeatureList::IsEnabled(
+          safe_browsing::kTailoredSecurityUpdatedMessages))
+          ? l10n_util::GetStringUTF16(
+                IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_NOTIFICATION_DESCRIPTION_UPDATED)
+          : l10n_util::GetStringUTF16(
+                IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_NOTIFICATION_DESCRIPTION);
   const std::u16string& primary_button = l10n_util::GetStringUTF16(
       IDS_TAILORED_SECURITY_UNCONSENTED_PROMOTION_NOTIFICATION_ACCEPT);
   const std::u16string& secondary_button =
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java
index 1fbae55..7c00f099 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java
@@ -83,7 +83,8 @@
         mDisplayDensity = activity.getResources().getDisplayMetrics().density;
     }
 
-    private void displayInitialScreenshot() {
+    @VisibleForTesting
+    void displayInitialScreenshot() {
         mEntryManager.addBitmapGeneratorObserver(new EntryManager.BitmapGeneratorObserver() {
             @Override
             public void onStatusChange(int status) {
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediatorTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediatorTest.java
index 035321c..4790127 100644
--- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediatorTest.java
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediatorTest.java
@@ -4,9 +4,14 @@
 
 package org.chromium.chrome.browser.share.long_screenshots;
 
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.app.Activity;
 import android.graphics.Bitmap;
+import android.graphics.Point;
 import android.os.Looper;
+import android.util.Size;
 import android.view.View;
 
 import androidx.test.filters.MediumTest;
@@ -16,6 +21,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -23,6 +30,10 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.share.long_screenshots.bitmap_generation.EntryManager;
+import org.chromium.chrome.browser.share.long_screenshots.bitmap_generation.EntryManager.BitmapGeneratorObserver;
+import org.chromium.chrome.browser.share.long_screenshots.bitmap_generation.LongScreenshotsEntry;
+import org.chromium.chrome.browser.share.long_screenshots.bitmap_generation.LongScreenshotsEntry.EntryListener;
+import org.chromium.chrome.browser.share.long_screenshots.bitmap_generation.LongScreenshotsEntry.EntryStatus;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.ui.test.util.BlankUiTestActivity;
 
@@ -30,6 +41,8 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class LongScreenshotsMediatorTest {
+    /** Some nominal representative screen dimension */
+    private static final int NOMINAL_SCREEN_DIMENTION = 1000;
     private Activity mActivity;
     private Bitmap mBitmap;
     private LongScreenshotsMediator mMediator;
@@ -44,6 +57,15 @@
     @Mock
     private EntryManager mManager;
 
+    @Mock
+    private LongScreenshotsEntry mLongScreenshotsEntry;
+
+    @Captor
+    private ArgumentCaptor<BitmapGeneratorObserver> mBitmapGeneratorObserverCaptor;
+
+    @Captor
+    private ArgumentCaptor<LongScreenshotsEntry.EntryListener> mEntryListenerCaptor;
+
     @Before
     public void setUp() {
         Looper.prepare();
@@ -78,4 +100,42 @@
         mMediator.areaSelectionClose(mView);
         Assert.assertFalse(mMediator.getDialog().isShowing());
     }
+
+    @Test
+    @MediumTest
+    public void testOnStatusChange() {
+        mMediator.displayInitialScreenshot();
+        verify(mManager).addBitmapGeneratorObserver(mBitmapGeneratorObserverCaptor.capture());
+        BitmapGeneratorObserver generatorObserver = mBitmapGeneratorObserverCaptor.getValue();
+        // Now we can call the onStatusChange that's within displayInitialScreenShot.
+        generatorObserver.onStatusChange(EntryStatus.CAPTURE_IN_PROGRESS);
+        generatorObserver.onStatusChange(EntryStatus.BITMAP_GENERATION_IN_PROGRESS);
+    }
+
+    @Test
+    @MediumTest
+    public void testOnCompositorReady() {
+        Bitmap someBitmap = Bitmap.createBitmap(
+                NOMINAL_SCREEN_DIMENTION, NOMINAL_SCREEN_DIMENTION, Bitmap.Config.ARGB_8888);
+        mMediator.displayInitialScreenshot();
+        verify(mManager).addBitmapGeneratorObserver(mBitmapGeneratorObserverCaptor.capture());
+        BitmapGeneratorObserver generatorObserver = mBitmapGeneratorObserverCaptor.getValue();
+
+        // Now we can call the onCompositorReady and capture it's EntryListener.
+        when(mManager.generateFullpageEntry()).thenReturn(mLongScreenshotsEntry);
+        when(mLongScreenshotsEntry.getBitmap()).thenReturn(someBitmap);
+        generatorObserver.onCompositorReady(
+                new Size(NOMINAL_SCREEN_DIMENTION, NOMINAL_SCREEN_DIMENTION), new Point(0, 0));
+        verify(mLongScreenshotsEntry).setListener(mEntryListenerCaptor.capture());
+        EntryListener entryListener = mEntryListenerCaptor.getValue();
+
+        // Now we can call the onResult method of the EntryListener.
+        // In-progress should be ignored.
+        entryListener.onResult(EntryStatus.BITMAP_GENERATION_IN_PROGRESS);
+        // Should already be captured, so this should put up a Toast with the error.
+        entryListener.onResult(EntryStatus.CAPTURE_IN_PROGRESS);
+        // This should trigger showAreaSelectionDialog to show the generated bitmap!
+        entryListener.onResult(EntryStatus.BITMAP_GENERATED);
+        Assert.assertTrue(mMediator.getDialog().isShowing());
+    }
 }
diff --git a/chrome/browser/sharing/sharing_service_unittest.cc b/chrome/browser/sharing/sharing_service_unittest.cc
index 80d689d..07143cc 100644
--- a/chrome/browser/sharing/sharing_service_unittest.cc
+++ b/chrome/browser/sharing/sharing_service_unittest.cc
@@ -210,6 +210,11 @@
   syncer::TestSyncService test_sync_service_;
   sync_preferences::TestingPrefServiceSyncable prefs_;
 
+ private:
+  // `sharing_service_` must outlive the raw_ptrs below.
+  std::unique_ptr<SharingService> sharing_service_;
+
+ protected:
   testing::NiceMock<MockInstanceIDDriver> mock_instance_id_driver_;
   raw_ptr<testing::NiceMock<MockSharingHandlerRegistry>> handler_registry_;
   raw_ptr<testing::NiceMock<MockSharingFCMHandler>> fcm_handler_;
@@ -222,7 +227,6 @@
   bool device_candidates_initialized_ = false;
 
  private:
-  std::unique_ptr<SharingService> sharing_service_;
   absl::optional<SharingSendMessageResult> send_message_result_;
   std::unique_ptr<chrome_browser_sharing::ResponseMessage>
       send_message_response_;
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service.h b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service.h
index 2d610d2..a0cbbe2 100644
--- a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service.h
+++ b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service.h
@@ -7,8 +7,9 @@
 
 #include "base/functional/callback_forward.h"
 #include "base/memory/weak_ptr.h"
-#include "chrome/common/renderer_configuration.mojom-forward.h"
+#include "chrome/common/renderer_configuration.mojom.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 
 // BoundSessionCookieRefreshService is responsible for maintaining cookies
 // associated with bound sessions. This class does the following:
@@ -16,7 +17,9 @@
 // - Provides bound session params to renderers
 // - Monitors cookie changes and update renderers
 // - Preemptively refreshes bound session cookies
-class BoundSessionCookieRefreshService : public KeyedService {
+class BoundSessionCookieRefreshService
+    : public KeyedService,
+      public chrome::mojom::BoundSessionRequestThrottledListener {
  public:
   using RendererBoundSessionParamsUpdaterDelegate = base::RepeatingClosure;
 
@@ -36,14 +39,6 @@
   virtual chrome::mojom::BoundSessionParamsPtr GetBoundSessionParams()
       const = 0;
 
-  // Called when a network request requires a fresh SIDTS cookie. This function
-  // is intended to be called by network requests throttlers.
-  // The callback will be called once the cookie is fresh or the session is
-  // terminated. Note: The callback might be called synchronously if the
-  // previous conditions apply.
-  virtual void OnRequestBlockedOnCookie(
-      base::OnceClosure resume_blocked_request) = 0;
-
   virtual base::WeakPtr<BoundSessionCookieRefreshService> GetWeakPtr() = 0;
 
  private:
@@ -53,6 +48,12 @@
   // renderers calls this setter to subscribe for bound session params updates.
   virtual void SetRendererBoundSessionParamsUpdaterDelegate(
       RendererBoundSessionParamsUpdaterDelegate renderer_updater) = 0;
+
+  // Adds a Receiver to `BoundSessionCookieRefreshService` to receive
+  // notification when a request is throttled and requires a fresh cookie.
+  virtual void AddBoundSessionRequestThrottledListenerReceiver(
+      mojo::PendingReceiver<chrome::mojom::BoundSessionRequestThrottledListener>
+          receiver) {}
 };
 
 #endif  // CHROME_BROWSER_SIGNIN_BOUND_SESSION_CREDENTIALS_BOUND_SESSION_COOKIE_REFRESH_SERVICE_H_
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.cc b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.cc
index 9c1ddafd7..8670886 100644
--- a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.cc
+++ b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.cc
@@ -205,8 +205,15 @@
   renderer_updater_ = renderer_updater;
 }
 
+void BoundSessionCookieRefreshServiceImpl::
+    AddBoundSessionRequestThrottledListenerReceiver(
+        mojo::PendingReceiver<
+            chrome::mojom::BoundSessionRequestThrottledListener> receiver) {
+  renderer_request_throttled_listener_.Add(this, std::move(receiver));
+}
+
 void BoundSessionCookieRefreshServiceImpl::OnRequestBlockedOnCookie(
-    base::OnceClosure resume_blocked_request) {
+    OnRequestBlockedOnCookieCallback resume_blocked_request) {
   if (!IsBoundSession()) {
     // Session has been terminated.
     std::move(resume_blocked_request).Run();
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.h b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.h
index 5e54f75c..5712e1d 100644
--- a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.h
+++ b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/signin/bound_session_credentials/bound_session_cookie_controller.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 
 class SigninClient;
 
@@ -31,8 +32,13 @@
   void Initialize() override;
   bool IsBoundSession() const override;
   chrome::mojom::BoundSessionParamsPtr GetBoundSessionParams() const override;
+  void AddBoundSessionRequestThrottledListenerReceiver(
+      mojo::PendingReceiver<chrome::mojom::BoundSessionRequestThrottledListener>
+          receiver) override;
+
+  // chrome::mojom::BoundSessionRequestThrottledListener:
   void OnRequestBlockedOnCookie(
-      base::OnceClosure resume_blocked_request) override;
+      OnRequestBlockedOnCookieCallback resume_blocked_request) override;
 
   base::WeakPtr<BoundSessionCookieRefreshService> GetWeakPtr() override;
 
@@ -77,6 +83,10 @@
 
   std::unique_ptr<BoundSessionStateTracker> bound_session_tracker_;
   std::unique_ptr<BoundSessionCookieController> cookie_controller_;
+
+  mojo::ReceiverSet<chrome::mojom::BoundSessionRequestThrottledListener>
+      renderer_request_throttled_listener_;
+
   base::WeakPtrFactory<BoundSessionCookieRefreshService> weak_ptr_factory_{
       this};
 };
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl_unittest.cc b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl_unittest.cc
index 1c539ff..ced5c44 100644
--- a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl_unittest.cc
+++ b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl_unittest.cc
@@ -46,8 +46,7 @@
 
   void OnRequestBlockedOnCookie(
       base::OnceClosure resume_blocked_request) override {
-    EXPECT_FALSE(resume_blocked_request_);
-    resume_blocked_request_ = std::move(resume_blocked_request);
+    resume_blocked_requests_.push_back(std::move(resume_blocked_request));
   }
 
   void set_on_destroy_callback(base::OnceCallback<void()> on_destroy_callback) {
@@ -60,14 +59,18 @@
     delegate_->OnCookieExpirationDateChanged();
   }
 
-  void SimualteRefreshBoundSessionCompleted() {
-    EXPECT_TRUE(resume_blocked_request_);
-    std::move(resume_blocked_request_).Run();
+  void SimulateRefreshBoundSessionCompleted() {
+    EXPECT_FALSE(resume_blocked_requests_.empty());
+    std::vector<base::OnceClosure> callbacks;
+    std::swap(resume_blocked_requests_, callbacks);
+    for (auto& callback : callbacks) {
+      std::move(callback).Run();
+    }
   }
 
  private:
   base::OnceCallback<void()> on_destroy_callback_;
-  base::OnceClosure resume_blocked_request_;
+  std::vector<base::OnceClosure> resume_blocked_requests_;
 };
 
 }  // namespace
@@ -99,7 +102,7 @@
 
   void OnCookieControllerDestroy() { cookie_controller_ = nullptr; }
 
-  BoundSessionCookieRefreshServiceImpl* CreateCookieRefreshServiceImpl() {
+  BoundSessionCookieRefreshServiceImpl* GetCookieRefreshServiceImpl() {
     if (!cookie_refresh_service_) {
       cookie_refresh_service_ =
           std::make_unique<BoundSessionCookieRefreshServiceImpl>(
@@ -148,6 +151,8 @@
 
   void TerminateBoundSession() { identity_test_env_.ClearPrimaryAccount(); }
 
+  void RunUntilIdle() { task_environment_.RunUntilIdle(); }
+
  private:
   base::test::TaskEnvironment task_environment_;
   sync_preferences::TestingPrefServiceSyncable prefs_;
@@ -159,8 +164,7 @@
 
 TEST_F(BoundSessionCookieRefreshServiceImplTest, VerifyControllerParams) {
   SetupPreConditionForBoundSession();
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_TRUE(service->IsBoundSession());
   FakeBoundSessionCookieController* controller = cookie_controller();
   EXPECT_TRUE(controller);
@@ -171,8 +175,7 @@
 
 TEST_F(BoundSessionCookieRefreshServiceImplTest,
        VerifyBoundSessionParamsUnboundSession) {
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_FALSE(service->IsBoundSession());
   EXPECT_TRUE(service->GetBoundSessionParams().is_null());
 }
@@ -180,8 +183,7 @@
 TEST_F(BoundSessionCookieRefreshServiceImplTest,
        VerifyBoundSessionParamsBoundSession) {
   SetupPreConditionForBoundSession();
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_TRUE(service->IsBoundSession());
 
   chrome::mojom::BoundSessionParamsPtr bound_session_params =
@@ -193,22 +195,20 @@
 TEST_F(BoundSessionCookieRefreshServiceImplTest,
        RefreshBoundSessionCookieBoundSession) {
   SetupPreConditionForBoundSession();
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_TRUE(service->IsBoundSession());
   base::test::TestFuture<void> future;
   service->OnRequestBlockedOnCookie(future.GetCallback());
   EXPECT_TRUE(cookie_controller());
 
   EXPECT_FALSE(future.IsReady());
-  cookie_controller()->SimualteRefreshBoundSessionCompleted();
+  cookie_controller()->SimulateRefreshBoundSessionCompleted();
   EXPECT_TRUE(future.IsReady());
 }
 
 TEST_F(BoundSessionCookieRefreshServiceImplTest,
        RefreshBoundSessionCookieUnboundSession) {
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_FALSE(service->IsBoundSession());
 
   // Unbound session, the callback should be called immediately.
@@ -219,8 +219,7 @@
 
 TEST_F(BoundSessionCookieRefreshServiceImplTest,
        UpdateAllRenderersOnBoundSessionStarted) {
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_FALSE(service->IsBoundSession());
   base::MockRepeatingCallback<void()> renderer_updater;
   EXPECT_CALL(renderer_updater, Run()).Times(0);
@@ -239,8 +238,7 @@
   base::MockRepeatingCallback<void()> renderer_updater;
   EXPECT_CALL(renderer_updater, Run()).Times(0);
   SetupPreConditionForBoundSession();
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_TRUE(service->IsBoundSession());
   SetRendererUpdater(renderer_updater.Get());
   testing::Mock::VerifyAndClearExpectations(&renderer_updater);
@@ -255,8 +253,7 @@
   base::MockRepeatingCallback<void()> renderer_updater;
   EXPECT_CALL(renderer_updater, Run()).Times(0);
   SetupPreConditionForBoundSession();
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_TRUE(service->IsBoundSession());
   SetRendererUpdater(renderer_updater.Get());
   testing::Mock::VerifyAndClearExpectations(&renderer_updater);
@@ -267,10 +264,35 @@
 }
 
 TEST_F(BoundSessionCookieRefreshServiceImplTest,
+       AddBoundSessionRequestThrottledListenerReceivers) {
+  SetupPreConditionForBoundSession();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
+  EXPECT_TRUE(service->IsBoundSession());
+  mojo::Remote<chrome::mojom::BoundSessionRequestThrottledListener> listener_1;
+  mojo::Remote<chrome::mojom::BoundSessionRequestThrottledListener> listener_2;
+  service->AddBoundSessionRequestThrottledListenerReceiver(
+      listener_1.BindNewPipeAndPassReceiver());
+  service->AddBoundSessionRequestThrottledListenerReceiver(
+      listener_2.BindNewPipeAndPassReceiver());
+
+  base::test::TestFuture<void> future_1;
+  base::test::TestFuture<void> future_2;
+  listener_1->OnRequestBlockedOnCookie(future_1.GetCallback());
+  listener_2->OnRequestBlockedOnCookie(future_2.GetCallback());
+  RunUntilIdle();
+
+  EXPECT_FALSE(future_1.IsReady());
+  EXPECT_FALSE(future_2.IsReady());
+
+  cookie_controller()->SimulateRefreshBoundSessionCompleted();
+  EXPECT_TRUE(future_1.Wait());
+  EXPECT_TRUE(future_2.Wait());
+}
+
+TEST_F(BoundSessionCookieRefreshServiceImplTest,
        IsBoundSessionNoPrimaryAccount) {
   EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_FALSE(service->IsBoundSession());
 }
 
@@ -278,8 +300,7 @@
        IsBoundSessionSigninPrimaryAccount) {
   SetupPreConditionForBoundSession();
   EXPECT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_TRUE(service->IsBoundSession());
   identity_test_env()->WaitForRefreshTokensLoaded();
   EXPECT_TRUE(service->IsBoundSession());
@@ -291,8 +312,7 @@
   SetupPreConditionForBoundSession();
   EXPECT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
   identity_test_env()->ResetToAccountsNotYetLoadedFromDiskState();
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_TRUE(service->IsBoundSession());
   EXPECT_TRUE(cookie_controller());
 }
@@ -301,8 +321,7 @@
        IsBoundSessionRefreshTokenInPersistentErrorState) {
   SetupPreConditionForBoundSession();
   EXPECT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_TRUE(service->IsBoundSession());
   EXPECT_TRUE(cookie_controller());
 
@@ -316,7 +335,7 @@
 
   identity_test_env()->ResetToAccountsNotYetLoadedFromDiskState();
   ResetCookieRefreshService();
-  service = CreateCookieRefreshServiceImpl();
+  service = GetCookieRefreshServiceImpl();
   EXPECT_TRUE(service->IsBoundSession());
   EXPECT_TRUE(cookie_controller());
 
@@ -328,8 +347,7 @@
 
 TEST_F(BoundSessionCookieRefreshServiceImplTest,
        IsBoundSessionOnPrimaryAccountChanged) {
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   identity_test_env()->WaitForRefreshTokensLoaded();
   EXPECT_FALSE(service->IsBoundSession());
   EXPECT_FALSE(cookie_controller());
@@ -353,8 +371,7 @@
        IsBoundSessionEmptyGaiaAccounts) {
   SetupPreConditionForBoundSession();
   EXPECT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
-  BoundSessionCookieRefreshServiceImpl* service =
-      CreateCookieRefreshServiceImpl();
+  BoundSessionCookieRefreshServiceImpl* service = GetCookieRefreshServiceImpl();
   EXPECT_TRUE(service->IsBoundSession());
   EXPECT_TRUE(cookie_controller());
 
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_request_throttled_listener_browser_impl_unittest.cc b/chrome/browser/signin/bound_session_credentials/bound_session_request_throttled_listener_browser_impl_unittest.cc
index 30d3970..e318584f 100644
--- a/chrome/browser/signin/bound_session_credentials/bound_session_request_throttled_listener_browser_impl_unittest.cc
+++ b/chrome/browser/signin/bound_session_credentials/bound_session_request_throttled_listener_browser_impl_unittest.cc
@@ -32,7 +32,7 @@
       RendererBoundSessionParamsUpdaterDelegate renderer_updater) override {}
 
   void OnRequestBlockedOnCookie(
-      base::OnceClosure resume_blocked_request) override {
+      OnRequestBlockedOnCookieCallback resume_blocked_request) override {
     resume_blocked_request_ = std::move(resume_blocked_request);
   }
 
diff --git a/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl.cc b/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl.cc
index 8061a079..6499856 100644
--- a/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl.cc
+++ b/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl.cc
@@ -37,8 +37,11 @@
 
 SupervisedUserWebContentHandlerImpl::SupervisedUserWebContentHandlerImpl(
     content::WebContents* web_contents,
-    int frame_id)
-    : ChromeSupervisedUserWebContentHandlerBase(web_contents, frame_id) {}
+    int frame_id,
+    int64_t interstitial_navigation_id)
+    : ChromeSupervisedUserWebContentHandlerBase(web_contents,
+                                                frame_id,
+                                                interstitial_navigation_id) {}
 
 SupervisedUserWebContentHandlerImpl::~SupervisedUserWebContentHandlerImpl() =
     default;
@@ -54,7 +57,7 @@
               ->GetProfileKey());
 
   WebsiteParentApproval::RequestLocalApproval(
-      web_contents_.get(), supervised_user::NormalizeUrl(url),
+      web_contents_, supervised_user::NormalizeUrl(url),
       base::BindOnce(
           &SupervisedUserWebContentHandlerImpl::OnLocalApprovalRequestCompleted,
           weak_ptr_factory_.GetWeakPtr(), std::ref(*settings_service), url,
@@ -68,7 +71,7 @@
                                                        std::u16string reason) {
   std::string message = l10n_util::GetStringFUTF8(
       IDS_BLOCK_INTERSTITIAL_DEFAULT_FEEDBACK_TEXT, reason);
-  ReportChildAccountFeedback(web_contents_.get(), message, url);
+  ReportChildAccountFeedback(web_contents_, message, url);
 }
 
 void SupervisedUserWebContentHandlerImpl::OnLocalApprovalRequestCompleted(
diff --git a/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl.h b/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl.h
index b87ef059..ff06d3f 100644
--- a/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl.h
+++ b/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl.h
@@ -18,7 +18,8 @@
     : public ChromeSupervisedUserWebContentHandlerBase {
  public:
   SupervisedUserWebContentHandlerImpl(content::WebContents* web_contents,
-                                      int frame_id);
+                                      int frame_id,
+                                      int64_t interstitial_navigation_id);
 
   SupervisedUserWebContentHandlerImpl(
       const SupervisedUserWebContentHandlerImpl&) = delete;
diff --git a/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl_unittest.cc b/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl_unittest.cc
index 7b545c6..4c72ba7a 100644
--- a/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl_unittest.cc
+++ b/chrome/browser/supervised_user/android/supervised_user_web_content_handler_impl_unittest.cc
@@ -71,7 +71,9 @@
       content::WebContents::Create(
           content::WebContents::CreateParams(GetProfilePtr()));
   SupervisedUserWebContentHandlerImpl web_content_handler =
-      SupervisedUserWebContentHandlerImpl(web_contents.get(), /*frame_id=*/0);
+      SupervisedUserWebContentHandlerImpl(web_contents.get(),
+                                          /*frame_id=*/0,
+                                          /*interstitial_navigation_id=*/0);
 
   web_content_handler.OnLocalApprovalRequestCompleted(
       supervisedUserSettingsServiceMock, url, start_time,
@@ -101,11 +103,14 @@
 
   base::TimeDelta elapsed_time = base::Minutes(5);
   task_environment().FastForwardBy(elapsed_time);
+
   std::unique_ptr<content::WebContents> web_contents =
       content::WebContents::Create(
           content::WebContents::CreateParams(GetProfilePtr()));
   SupervisedUserWebContentHandlerImpl web_content_handler =
-      SupervisedUserWebContentHandlerImpl(web_contents.get(), /*frame_id=*/0);
+      SupervisedUserWebContentHandlerImpl(web_contents.get(),
+                                          /*frame_id=*/0,
+                                          /*interstitial_navigation_id=*/0);
 
   // Receive a request canceled by the parent.
   // Check that no duration metric is recorded for incomplete requests.
@@ -133,11 +138,14 @@
 
   base::TimeDelta elapsed_time = base::Minutes(5);
   task_environment().FastForwardBy(elapsed_time);
+
   std::unique_ptr<content::WebContents> web_contents =
       content::WebContents::Create(
           content::WebContents::CreateParams(GetProfilePtr()));
   SupervisedUserWebContentHandlerImpl web_content_handler =
-      SupervisedUserWebContentHandlerImpl(web_contents.get(), /*frame_id=*/0);
+      SupervisedUserWebContentHandlerImpl(web_contents.get(),
+                                          /*frame_id=*/0,
+                                          /*interstitial_navigation_id=*/0);
 
   // Receive a request accepted by the parent with a total duration of 5
   // minutes. Check that duration metric is recorded.
diff --git a/chrome/browser/supervised_user/chrome_supervised_user_web_content_handler_base.cc b/chrome/browser/supervised_user/chrome_supervised_user_web_content_handler_base.cc
index 5ed63c2..3fe7922 100644
--- a/chrome/browser/supervised_user/chrome_supervised_user_web_content_handler_base.cc
+++ b/chrome/browser/supervised_user/chrome_supervised_user_web_content_handler_base.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/supervised_user/chrome_supervised_user_web_content_handler_base.h"
 
+#include "chrome/browser/supervised_user/supervised_user_interstitial_tab_closer.h"
 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h"
 #include "components/infobars/content/content_infobar_manager.h"
 #include "components/infobars/core/infobar.h"
@@ -14,8 +15,11 @@
 ChromeSupervisedUserWebContentHandlerBase::
     ChromeSupervisedUserWebContentHandlerBase(
         content::WebContents* web_contents,
-        int frame_id)
-    : web_contents_(web_contents), frame_id_(frame_id) {
+        int frame_id,
+        int64_t interstitial_navigation_id)
+    : web_contents_(web_contents),
+      frame_id_(frame_id),
+      interstitial_navigation_id_(interstitial_navigation_id) {
   CHECK(web_contents_);
 }
 
@@ -58,3 +62,43 @@
     }
   }
 }
+
+int64_t ChromeSupervisedUserWebContentHandlerBase::GetInterstitialNavigationId()
+    const {
+  return interstitial_navigation_id_;
+}
+
+void ChromeSupervisedUserWebContentHandlerBase::GoBack() {
+  // GoBack only for main frame.
+  CHECK(IsMainFrame());
+  if (!AttemptMoveAwayFromCurrentFrameURL()) {
+    TabCloser::CheckIfInBrowserThenCloseTab(web_contents_);
+  }
+  OnInterstitialDone();
+}
+
+bool ChromeSupervisedUserWebContentHandlerBase::
+    AttemptMoveAwayFromCurrentFrameURL() {
+  // No need to do anything if the WebContents is in the process of being
+  // destroyed anyway.
+  if (web_contents_->IsBeingDestroyed()) {
+    return true;
+  }
+  // If the interstitial was shown over an existing page, navigate back from
+  // that page. If that is not possible, attempt to close the entire tab.
+  if (web_contents_->GetController().CanGoBack()) {
+    web_contents_->GetController().GoBack();
+    return true;
+  }
+  return false;
+}
+
+void ChromeSupervisedUserWebContentHandlerBase::OnInterstitialDone() {
+  auto* navigation_observer =
+      SupervisedUserNavigationObserver::FromWebContents(web_contents_);
+  // After this, the WebContents may be destroyed. Make sure we don't try to use
+  // it again. `OnInterstitialDone` will destruct the web content handler,
+  // and consequently the web_contents_ pointer.
+  web_contents_ = nullptr;
+  navigation_observer->OnInterstitialDone(frame_id_);
+}
diff --git a/chrome/browser/supervised_user/chrome_supervised_user_web_content_handler_base.h b/chrome/browser/supervised_user/chrome_supervised_user_web_content_handler_base.h
index d658241..fcc33df 100644
--- a/chrome/browser/supervised_user/chrome_supervised_user_web_content_handler_base.h
+++ b/chrome/browser/supervised_user/chrome_supervised_user_web_content_handler_base.h
@@ -27,15 +27,26 @@
   // supervised_user::WebContentHandler implementation:
   bool IsMainFrame() const override;
   void CleanUpInfoBarOnMainFrame() override;
+  int64_t GetInterstitialNavigationId() const override;
+  void GoBack() override;
 
  protected:
   ChromeSupervisedUserWebContentHandlerBase(content::WebContents* web_contents,
-                                            int frame_id);
+                                            int frame_id,
+                                            int64_t interstitial_navigation_id);
   raw_ptr<content::WebContents> web_contents_;
 
  private:
+  // Tries to navigate to the previous page (if one exists) and returns
+  // if it was successful.
+  bool AttemptMoveAwayFromCurrentFrameURL();
+  // Notifies the consumers of the intestitial.
+  void OnInterstitialDone();
+
   // The uniquely identifying global id for the frame.
   const int frame_id_;
+  // The Navigation id of the navigation that last triggered the interstitial.
+  int64_t interstitial_navigation_id_;
 };
 
 #endif  // CHROME_BROWSER_SUPERVISED_USER_CHROME_SUPERVISED_USER_WEB_CONTENT_HANDLER_BASE_H_
diff --git a/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl.cc b/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl.cc
index 71711f06..cf46098 100644
--- a/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl.cc
+++ b/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl.cc
@@ -70,13 +70,17 @@
     content::WebContents* web_contents,
     const GURL& url,
     favicon::LargeIconService& large_icon_service,
-    int frame_id)
-    : ChromeSupervisedUserWebContentHandlerBase(web_contents, frame_id),
+    int frame_id,
+    int64_t interstitial_navigation_id)
+    : ChromeSupervisedUserWebContentHandlerBase(web_contents,
+                                                frame_id,
+                                                interstitial_navigation_id),
       favicon_handler_(std::make_unique<SupervisedUserFaviconRequestHandler>(
           url.GetWithEmptyPath(),
           &large_icon_service)),
       profile_(
           *Profile::FromBrowserContext(web_contents->GetBrowserContext())) {
+  CHECK(web_contents_);
   if (supervised_user::IsLocalWebApprovalsEnabled()) {
     // Prefetch the favicon which will be rendered as part of the web approvals
     // ParentAccessDialog. Pass in DoNothing() for the favicon fetched callback
@@ -121,7 +125,6 @@
                                                        std::u16string reason) {
   std::string message = l10n_util::GetStringFUTF8(
       IDS_BLOCK_INTERSTITIAL_DEFAULT_FEEDBACK_TEXT, reason);
-
   chrome::ShowFeedbackPage(
       url, &profile_.get(), chrome::kFeedbackSourceSupervisedUserInterstitial,
       message, std::string() /* description_placeholder_text */,
diff --git a/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl.h b/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl.h
index d8bcb7b2..14f599d 100644
--- a/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl.h
+++ b/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl.h
@@ -30,7 +30,8 @@
       content::WebContents* web_contents,
       const GURL& url,
       favicon::LargeIconService& large_icon_service,
-      int frame_id);
+      int frame_id,
+      int64_t interstitial_navigation_id);
 
   SupervisedUserWebContentHandlerImpl(
       const SupervisedUserWebContentHandlerImpl&) = delete;
diff --git a/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl_unittest.cc b/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl_unittest.cc
index 52e7e1d3..e23134c 100644
--- a/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl_unittest.cc
+++ b/chrome/browser/supervised_user/chromeos/supervised_user_web_content_handler_impl_unittest.cc
@@ -87,7 +87,8 @@
       content::WebContents::Create(
           content::WebContents::CreateParams(GetProfilePtr()));
   SupervisedUserWebContentHandlerImpl web_content_handler(
-      web_contents.get(), url, large_icon_service(), /*frame_id=*/0);
+      web_contents.get(), url, large_icon_service(),
+      /*frame_id=*/0, /*interstitial_navigation_id=*/0);
 
   web_content_handler.OnLocalApprovalRequestCompleted(
       supervisedUserSettingsServiceMock, url, start_time, std::move(result));
@@ -129,7 +130,8 @@
       content::WebContents::Create(
           content::WebContents::CreateParams(GetProfilePtr()));
   SupervisedUserWebContentHandlerImpl web_content_handler(
-      web_contents.get(), url, large_icon_service(), /*frame_id=*/0);
+      web_contents.get(), url, large_icon_service(),
+      /*frame_id=*/0, /*interstitial_navigation_id=*/0);
 
   web_content_handler.OnLocalApprovalRequestCompleted(
       supervisedUserSettingsServiceMock, url, start_time, std::move(result));
@@ -171,7 +173,8 @@
       content::WebContents::Create(
           content::WebContents::CreateParams(GetProfilePtr()));
   SupervisedUserWebContentHandlerImpl web_content_handler(
-      web_contents.get(), url, large_icon_service(), /*frame_id=*/0);
+      web_contents.get(), url, large_icon_service(),
+      /*frame_id=*/0, /*interstitial_navigation_id=*/0);
 
   web_content_handler.OnLocalApprovalRequestCompleted(
       supervisedUserSettingsServiceMock, url, start_time, std::move(result));
@@ -211,7 +214,8 @@
       content::WebContents::Create(
           content::WebContents::CreateParams(GetProfilePtr()));
   SupervisedUserWebContentHandlerImpl web_content_handler(
-      web_contents.get(), url, large_icon_service(), /*frame_id=*/0);
+      web_contents.get(), url, large_icon_service(),
+      /*frame_id=*/0, /*interstitial_navigation_id=*/0);
 
   web_content_handler.OnLocalApprovalRequestCompleted(
       supervisedUserSettingsServiceMock, url, start_time, std::move(result));
diff --git a/chrome/browser/supervised_user/linux_mac_windows/supervised_user_web_content_handler_impl.cc b/chrome/browser/supervised_user/linux_mac_windows/supervised_user_web_content_handler_impl.cc
index 9d0d6a09..b85612a 100644
--- a/chrome/browser/supervised_user/linux_mac_windows/supervised_user_web_content_handler_impl.cc
+++ b/chrome/browser/supervised_user/linux_mac_windows/supervised_user_web_content_handler_impl.cc
@@ -9,8 +9,11 @@
 
 SupervisedUserWebContentHandlerImpl::SupervisedUserWebContentHandlerImpl(
     content::WebContents* web_contents,
-    int frame_id)
-    : ChromeSupervisedUserWebContentHandlerBase(web_contents, frame_id) {}
+    int frame_id,
+    int64_t interstitial_navigation_id)
+    : ChromeSupervisedUserWebContentHandlerBase(web_contents,
+                                                frame_id,
+                                                interstitial_navigation_id) {}
 
 SupervisedUserWebContentHandlerImpl::~SupervisedUserWebContentHandlerImpl() =
     default;
diff --git a/chrome/browser/supervised_user/linux_mac_windows/supervised_user_web_content_handler_impl.h b/chrome/browser/supervised_user/linux_mac_windows/supervised_user_web_content_handler_impl.h
index 966efefa..26cf42d 100644
--- a/chrome/browser/supervised_user/linux_mac_windows/supervised_user_web_content_handler_impl.h
+++ b/chrome/browser/supervised_user/linux_mac_windows/supervised_user_web_content_handler_impl.h
@@ -20,7 +20,8 @@
     : public ChromeSupervisedUserWebContentHandlerBase {
  public:
   SupervisedUserWebContentHandlerImpl(content::WebContents* web_contents,
-                                      int frame_id);
+                                      int frame_id,
+                                      int64_t interstitial_navigation_id);
   SupervisedUserWebContentHandlerImpl(
       const SupervisedUserWebContentHandlerImpl&) = delete;
   SupervisedUserWebContentHandlerImpl& operator=(
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial.cc b/chrome/browser/supervised_user/supervised_user_interstitial.cc
index d311ad0..484bec2 100644
--- a/chrome/browser/supervised_user/supervised_user_interstitial.cc
+++ b/chrome/browser/supervised_user/supervised_user_interstitial.cc
@@ -17,89 +17,22 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/supervised_user/supervised_user_navigation_observer.h"
 #include "chrome/browser/supervised_user/supervised_user_service.h"
 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
 #include "components/prefs/pref_service.h"
 #include "components/supervised_user/core/browser/web_content_handler.h"
 #include "components/supervised_user/core/common/features.h"
 #include "components/supervised_user/core/common/pref_names.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_user_data.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 
-#if !BUILDFLAG(IS_ANDROID)
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/chrome_pages.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#endif
-
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 #endif
 
-using content::WebContents;
-
 namespace {
 
-class TabCloser : public content::WebContentsUserData<TabCloser> {
- public:
-  TabCloser(const TabCloser&) = delete;
-  TabCloser& operator=(const TabCloser&) = delete;
-
-  ~TabCloser() override {}
-
-  static void MaybeClose(WebContents* web_contents) {
-    DCHECK(web_contents);
-
-    // Close the tab only if there is a browser for it (which is not the case
-    // for example in a <webview>).
-#if !BUILDFLAG(IS_ANDROID)
-    if (!chrome::FindBrowserWithWebContents(web_contents))
-      return;
-#endif
-    TabCloser::CreateForWebContents(web_contents);
-  }
-
- private:
-  friend class content::WebContentsUserData<TabCloser>;
-
-  explicit TabCloser(WebContents* web_contents)
-      : content::WebContentsUserData<TabCloser>(*web_contents) {
-    content::GetUIThreadTaskRunner({})->PostTask(
-        FROM_HERE, base::BindOnce(&TabCloser::CloseTabImpl,
-                                  weak_ptr_factory_.GetWeakPtr()));
-  }
-
-  void CloseTabImpl() {
-    // On Android, FindBrowserWithWebContents and TabStripModel don't exist.
-#if !BUILDFLAG(IS_ANDROID)
-    Browser* browser = chrome::FindBrowserWithWebContents(&GetWebContents());
-    DCHECK(browser);
-    TabStripModel* tab_strip = browser->tab_strip_model();
-    DCHECK_NE(TabStripModel::kNoTab,
-              tab_strip->GetIndexOfWebContents(&GetWebContents()));
-    if (tab_strip->count() <= 1) {
-      // Don't close the last tab in the window.
-      GetWebContents().RemoveUserData(UserDataKey());
-      return;
-    }
-#endif
-    GetWebContents().Close();
-  }
-
-  base::WeakPtrFactory<TabCloser> weak_ptr_factory_{this};
-
-  WEB_CONTENTS_USER_DATA_KEY_DECL();
-};
-
-WEB_CONTENTS_USER_DATA_KEY_IMPL(TabCloser);
-
 // TODO(b/250924204): Implement shared logic to get the user's given name.
 std::u16string GetActiveUserFirstName() {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -113,40 +46,28 @@
 
 // static
 std::unique_ptr<SupervisedUserInterstitial> SupervisedUserInterstitial::Create(
-    WebContents* web_contents,
     std::unique_ptr<supervised_user::WebContentHandler> web_content_handler,
     SupervisedUserService& supervised_user_service,
     const GURL& url,
-    supervised_user::FilteringBehaviorReason reason,
-    int frame_id,
-    int64_t interstitial_navigation_id) {
-  std::unique_ptr<SupervisedUserInterstitial> interstitial =
-      base::WrapUnique(new SupervisedUserInterstitial(
-          web_contents, std::move(web_content_handler), supervised_user_service,
-          url, reason, frame_id, interstitial_navigation_id));
+    supervised_user::FilteringBehaviorReason reason) {
+  std::unique_ptr<SupervisedUserInterstitial> interstitial = base::WrapUnique(
+      new SupervisedUserInterstitial(std::move(web_content_handler),
+                                     supervised_user_service, url, reason));
 
   interstitial->web_content_handler()->CleanUpInfoBarOnMainFrame();
-
   // Caller is responsible for deleting the interstitial.
   return interstitial;
 }
 
 SupervisedUserInterstitial::SupervisedUserInterstitial(
-    WebContents* web_contents,
     std::unique_ptr<supervised_user::WebContentHandler> web_content_handler,
     SupervisedUserService& supervised_user_service,
     const GURL& url,
-    supervised_user::FilteringBehaviorReason reason,
-    int frame_id,
-    int64_t interstitial_navigation_id)
+    supervised_user::FilteringBehaviorReason reason)
     : supervised_user_service_(supervised_user_service),
       web_content_handler_(std::move(web_content_handler)),
-      web_contents_(web_contents),
       url_(url),
-      reason_(reason),
-      frame_id_(frame_id),
-      interstitial_navigation_id_(interstitial_navigation_id) {}
-
+      reason_(reason) {}
 SupervisedUserInterstitial::~SupervisedUserInterstitial() {}
 
 // static
@@ -180,14 +101,9 @@
 }
 
 void SupervisedUserInterstitial::GoBack() {
-  // GoBack only for main frame.
-  DCHECK_EQ(web_contents()->GetPrimaryMainFrame()->GetFrameTreeNodeId(),
-            frame_id());
-
+  web_content_handler_->GoBack();
   UMA_HISTOGRAM_ENUMERATION(kInterstitialCommandHistogramName, Commands::BACK,
                             Commands::HISTOGRAM_BOUNDING_VALUE);
-  AttemptMoveAwayFromCurrentFrameURL();
-  OnInterstitialDone();
 }
 
 void SupervisedUserInterstitial::RequestUrlAccessRemote(
@@ -222,32 +138,6 @@
   return;
 }
 
-void SupervisedUserInterstitial::AttemptMoveAwayFromCurrentFrameURL() {
-  // No need to do anything if the WebContents is in the process of being
-  // destroyed anyway.
-  if (web_contents_->IsBeingDestroyed())
-    return;
-
-  // If the interstitial was shown over an existing page, navigate back from
-  // that page. If that is not possible, attempt to close the entire tab.
-  if (web_contents_->GetController().CanGoBack()) {
-    web_contents_->GetController().GoBack();
-    return;
-  }
-
-  TabCloser::MaybeClose(web_contents_);
-}
-
-void SupervisedUserInterstitial::OnInterstitialDone() {
-  auto* navigation_observer =
-      SupervisedUserNavigationObserver::FromWebContents(web_contents_);
-
-  // After this, the WebContents may be destroyed. Make sure we don't try to use
-  // it again.
-  web_contents_ = nullptr;
-  navigation_observer->OnInterstitialDone(frame_id_);
-}
-
 void SupervisedUserInterstitial::OutputRequestPermissionSourceMetric() {
   RequestPermissionSource source;
   if (web_content_handler_->IsMainFrame()) {
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial.h b/chrome/browser/supervised_user/supervised_user_interstitial.h
index da56bd8..e45329b2 100644
--- a/chrome/browser/supervised_user/supervised_user_interstitial.h
+++ b/chrome/browser/supervised_user/supervised_user_interstitial.h
@@ -10,15 +10,9 @@
 
 #include "base/allocator/partition_allocator/pointers/raw_ref.h"
 #include "base/functional/callback_forward.h"
-#include "base/memory/raw_ptr.h"
-#include "build/chromeos_buildflags.h"
 #include "components/supervised_user/core/browser/supervised_user_error_page.h"
 #include "url/gurl.h"
 
-namespace content {
-class WebContents;
-}  // namespace content
-
 namespace supervised_user {
 class WebContentHandler;
 }
@@ -76,13 +70,10 @@
   ~SupervisedUserInterstitial();
 
   static std::unique_ptr<SupervisedUserInterstitial> Create(
-      content::WebContents* web_contents,
       std::unique_ptr<supervised_user::WebContentHandler> web_content_handler,
       SupervisedUserService& supervised_user_service,
       const GURL& url,
-      supervised_user::FilteringBehaviorReason reason,
-      int frame_id,
-      int64_t interstitial_navigation_id);
+      supervised_user::FilteringBehaviorReason reason);
 
   static std::string GetHTMLContents(
       SupervisedUserService* supervised_user_service,
@@ -97,11 +88,6 @@
   void ShowFeedback();
 
   // Getter methods.
-  content::WebContents* web_contents() { return web_contents_; }
-  int frame_id() const { return frame_id_; }
-  int64_t interstitial_navigation_id() const {
-    return interstitial_navigation_id_;
-  }
   const GURL& url() const { return url_; }
   supervised_user::WebContentHandler* web_content_handler() {
     return web_content_handler_.get();
@@ -109,37 +95,19 @@
 
  private:
   SupervisedUserInterstitial(
-      content::WebContents* web_contents,
       std::unique_ptr<supervised_user::WebContentHandler> web_content_handler,
       SupervisedUserService& supervised_user_service,
       const GURL& url,
-      supervised_user::FilteringBehaviorReason reason,
-      int frame_id,
-      int64_t interstitial_navigation_id);
-
-  // Tries to go back.
-  void AttemptMoveAwayFromCurrentFrameURL();
-
-  void OnInterstitialDone();
-
+      supervised_user::FilteringBehaviorReason reason);
   void OutputRequestPermissionSourceMetric();
 
   const raw_ref<SupervisedUserService> supervised_user_service_;
 
   std::unique_ptr<supervised_user::WebContentHandler> web_content_handler_;
 
-  // Owns SupervisedUserNavigationObserver which owns us.
-  raw_ptr<content::WebContents> web_contents_;
-
   // The last committed url for this frame.
   GURL url_;
   supervised_user::FilteringBehaviorReason reason_;
-
-  // The uniquely identifying global id for the frame.
-  int frame_id_;
-
-  // The Navigation ID of the navigation that last triggered the interstitial.
-  int64_t interstitial_navigation_id_;
 };
 
 #endif  // CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_INTERSTITIAL_H_
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial_tab_closer.cc b/chrome/browser/supervised_user/supervised_user_interstitial_tab_closer.cc
new file mode 100644
index 0000000..d466753
--- /dev/null
+++ b/chrome/browser/supervised_user/supervised_user_interstitial_tab_closer.cc
@@ -0,0 +1,58 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/supervised_user/supervised_user_interstitial_tab_closer.h"
+
+#include "build/build_config.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+
+#if !BUILDFLAG(IS_ANDROID)
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#endif
+
+TabCloser::~TabCloser() = default;
+
+// static
+void TabCloser::CheckIfInBrowserThenCloseTab(
+    content::WebContents* web_contents) {
+  DCHECK(web_contents);
+  // Close the tab only if there is a browser for it (which is not the case
+  // for example in a <webview>).
+#if !BUILDFLAG(IS_ANDROID)
+  if (!chrome::FindBrowserWithWebContents(web_contents)) {
+    return;
+  }
+#endif
+  TabCloser::CreateForWebContents(web_contents);
+}
+
+TabCloser::TabCloser(content::WebContents* web_contents)
+    : content::WebContentsUserData<TabCloser>(*web_contents) {
+  content::GetUIThreadTaskRunner({})->PostTask(
+      FROM_HERE,
+      base::BindOnce(&TabCloser::CloseTabImpl, weak_ptr_factory_.GetWeakPtr()));
+}
+
+void TabCloser::CloseTabImpl() {
+  // On Android, FindBrowserWithWebContents and TabStripModel don't exist.
+#if !BUILDFLAG(IS_ANDROID)
+  Browser* browser = chrome::FindBrowserWithWebContents(&GetWebContents());
+  DCHECK(browser);
+  TabStripModel* tab_strip = browser->tab_strip_model();
+  DCHECK_NE(TabStripModel::kNoTab,
+            tab_strip->GetIndexOfWebContents(&GetWebContents()));
+  if (tab_strip->count() <= 1) {
+    // Don't close the last tab in the window.
+    GetWebContents().RemoveUserData(UserDataKey());
+    return;
+  }
+#endif
+  GetWebContents().Close();
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(TabCloser);
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial_tab_closer.h b/chrome/browser/supervised_user/supervised_user_interstitial_tab_closer.h
new file mode 100644
index 0000000..f86937e
--- /dev/null
+++ b/chrome/browser/supervised_user/supervised_user_interstitial_tab_closer.h
@@ -0,0 +1,39 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_INTERSTITIAL_TAB_CLOSER_H_
+#define CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_INTERSTITIAL_TAB_CLOSER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+// Helper class for closing an open tab when we go back from a Supervised User
+// Intersitial.
+class TabCloser : public content::WebContentsUserData<TabCloser> {
+ public:
+  TabCloser(const TabCloser&) = delete;
+  TabCloser& operator=(const TabCloser&) = delete;
+  ~TabCloser() override;
+
+  // Closes the tab linked to the present web contents. On non-Android
+  // platforms, the tab closes only if it is displayed on a browser.
+  static void CheckIfInBrowserThenCloseTab(content::WebContents* web_contents);
+
+ private:
+  friend class content::WebContentsUserData<TabCloser>;
+
+  explicit TabCloser(content::WebContents* web_contents);
+
+  void CloseTabImpl();
+
+  base::WeakPtrFactory<TabCloser> weak_ptr_factory_{this};
+
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+};
+
+#endif  // CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_INTERSTITIAL_TAB_CLOSER_H_
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_observer.cc b/chrome/browser/supervised_user/supervised_user_navigation_observer.cc
index 8b42b4c..2111810 100644
--- a/chrome/browser/supervised_user/supervised_user_navigation_observer.cc
+++ b/chrome/browser/supervised_user/supervised_user_navigation_observer.cc
@@ -51,17 +51,19 @@
     content::WebContents* web_contents,
     GURL url,
     Profile* profile,
-    int frame_id) {
+    int frame_id,
+    int navigation_id) {
 #if BUILDFLAG(IS_CHROMEOS)
   return std::make_unique<SupervisedUserWebContentHandlerImpl>(
       web_contents, url,
-      *LargeIconServiceFactory::GetForBrowserContext(profile), frame_id);
+      *LargeIconServiceFactory::GetForBrowserContext(profile), frame_id,
+      navigation_id);
 #elif BUILDFLAG(IS_ANDROID)
-  return std::make_unique<SupervisedUserWebContentHandlerImpl>(web_contents,
-                                                               frame_id);
+  return std::make_unique<SupervisedUserWebContentHandlerImpl>(
+      web_contents, frame_id, navigation_id);
 #elif BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
-  return std::make_unique<SupervisedUserWebContentHandlerImpl>(web_contents,
-                                                               frame_id);
+  return std::make_unique<SupervisedUserWebContentHandlerImpl>(
+      web_contents, frame_id, navigation_id);
 #endif
 }
 
@@ -144,7 +146,8 @@
   // interstitial in the frame, then interstitial is done.
   if (base::Contains(supervised_user_interstitials_, frame_id) &&
       navigation_id != supervised_user_interstitials_[frame_id]
-                           ->interstitial_navigation_id()) {
+                           ->web_content_handler()
+                           ->GetInterstitialNavigationId()) {
     OnInterstitialDone(frame_id);
   }
 
@@ -313,13 +316,13 @@
     const OnInterstitialResultCallback& callback) {
   Profile* profile =
       Profile::FromBrowserContext(web_contents()->GetBrowserContext());
-  auto web_content_handler =
-      CreateWebContentHandler(web_contents(), url, profile, frame_id);
+  auto web_content_handler = CreateWebContentHandler(
+      web_contents(), url, profile, frame_id, navigation_id);
   CHECK(web_content_handler);
   std::unique_ptr<SupervisedUserInterstitial> interstitial =
-      SupervisedUserInterstitial::Create(
-          web_contents(), std::move(web_content_handler),
-          *supervised_user_service_, url, reason, frame_id, navigation_id);
+      SupervisedUserInterstitial::Create(std::move(web_content_handler),
+                                         *supervised_user_service_, url,
+                                         reason);
   supervised_user_interstitials_[frame_id] = std::move(interstitial);
 
   bool already_requested = base::Contains(requested_hosts_, url.host());
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillBridge.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillBridge.java
index 828ca068e..bc06f81 100644
--- a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillBridge.java
+++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillBridge.java
@@ -68,9 +68,9 @@
     }
 
     @CalledByNative
-    private static void insertWebAuthnCredential(
-            WebAuthnCredential[] credentials, int index, String username, String id) {
-        credentials[index] = new WebAuthnCredential(username, id);
+    private static void insertWebAuthnCredential(WebAuthnCredential[] credentials, int index,
+            String rpId, byte[] credentialId, byte[] userId, String username) {
+        credentials[index] = new WebAuthnCredential(rpId, credentialId, userId, username);
     }
 
     @CalledByNative
diff --git a/chrome/browser/touch_to_fill/android/java/src/org/chromium/chrome/browser/touch_to_fill/data/WebAuthnCredential.java b/chrome/browser/touch_to_fill/android/java/src/org/chromium/chrome/browser/touch_to_fill/data/WebAuthnCredential.java
index e0aca7a..0ac3cf3 100644
--- a/chrome/browser/touch_to_fill/android/java/src/org/chromium/chrome/browser/touch_to_fill/data/WebAuthnCredential.java
+++ b/chrome/browser/touch_to_fill/android/java/src/org/chromium/chrome/browser/touch_to_fill/data/WebAuthnCredential.java
@@ -11,25 +11,41 @@
  * Touch To Fill sheet.
  */
 public class WebAuthnCredential {
+    private final String mRpId;
+    private final byte[] mCredentialId;
+    private final byte[] mUserId;
     private final String mUsername;
-    private final String mId;
 
     /**
+     * @param rpId Relying party identifier
+     * @param credentialId Unique identifier for the credential
+     * @param userId User handle
      * @param username Username shown to the user.
-     * @param id Unique identifier for the credential.
      */
-    public WebAuthnCredential(String username, String id) {
+    public WebAuthnCredential(String rpId, byte[] credentialId, byte[] userId, String username) {
+        mRpId = rpId;
+        mCredentialId = credentialId;
+        mUserId = userId;
         mUsername = username;
-        mId = id;
+    }
+
+    @CalledByNative
+    public String getRpId() {
+        return mRpId;
+    }
+
+    @CalledByNative
+    public byte[] getCredentialId() {
+        return mCredentialId;
+    }
+
+    @CalledByNative
+    public byte[] getUserId() {
+        return mUserId;
     }
 
     @CalledByNative
     public String getUsername() {
         return mUsername;
     }
-
-    @CalledByNative
-    public String getId() {
-        return mId;
-    }
 }
diff --git a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillIntegrationTest.java b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillIntegrationTest.java
index e66b123..2f95d7f 100644
--- a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillIntegrationTest.java
+++ b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillIntegrationTest.java
@@ -90,7 +90,8 @@
         // TODO(https://crbug.com/783819): Migrate Credential to GURL.
         sAna = new Credential("Ana", "S3cr3t", "Ana", sExampleUrl.getSpec(), false, false, 0);
         sBob = new Credential("Bob", "*****", "Bob", MOBILE_URL, true, false, 0);
-        sCam = new WebAuthnCredential("cam@example.net", "12345");
+        sCam = new WebAuthnCredential(
+                "example.net", new byte[] {1}, new byte[] {2}, "cam@example.net");
 
         mActivityTestRule.startMainActivityOnBlankPage();
         runOnUiThreadBlocking(() -> {
diff --git a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java
index 0c7529c..4aeed49 100644
--- a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java
+++ b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java
@@ -87,7 +87,8 @@
             new Credential("", "***", "No Username", "m.example.xyz", true, false, 0);
     private static final Credential BOB =
             new Credential("Bob", "***", "Bob", "mobile.example.xyz", true, false, 0);
-    private static final WebAuthnCredential CAM = new WebAuthnCredential("Cam", "12345");
+    private static final WebAuthnCredential CAM =
+            new WebAuthnCredential("example.net", new byte[] {1}, new byte[] {2}, "Cam");
     private static final Credential NIK =
             new Credential("Nik", "***", "Nik", "group.xyz", false, true, 0);
     private final AtomicBoolean mManageButtonClicked = new AtomicBoolean(false);
diff --git a/chrome/browser/touch_to_fill/android/junit/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillControllerTest.java b/chrome/browser/touch_to_fill/android/junit/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillControllerTest.java
index bea2394..68e40af 100644
--- a/chrome/browser/touch_to_fill/android/junit/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillControllerTest.java
+++ b/chrome/browser/touch_to_fill/android/junit/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillControllerTest.java
@@ -96,7 +96,7 @@
     private static final Credential CARL =
             new Credential("Carl", "G3h3!m", "Carl", TEST_URL.getSpec(), false, false, 0);
     private static final WebAuthnCredential DINO =
-            new WebAuthnCredential("dino@example.com", "12345");
+            new WebAuthnCredential("dinos.com", new byte[] {1}, new byte[] {2}, "dino@example.com");
     private static final @Px int DESIRED_FAVICON_SIZE = 64;
 
     @Rule
diff --git a/chrome/browser/touch_to_fill/android/touch_to_fill_view_impl.cc b/chrome/browser/touch_to_fill/android/touch_to_fill_view_impl.cc
index d849b47..c458c4e 100644
--- a/chrome/browser/touch_to_fill/android/touch_to_fill_view_impl.cc
+++ b/chrome/browser/touch_to_fill/android/touch_to_fill_view_impl.cc
@@ -5,8 +5,10 @@
 #include "chrome/browser/touch_to_fill/android/touch_to_fill_view_impl.h"
 
 #include <memory>
+#include <vector>
 
 #include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
@@ -17,10 +19,10 @@
 #include "chrome/browser/ui/passwords/ui_utils.h"
 #include "components/password_manager/core/browser/origin_credential_store.h"
 #include "components/password_manager/core/browser/passkey_credential.h"
+#include "components/password_manager/core/browser/password_ui_utils.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/android/view_android.h"
 #include "ui/android/window_android.h"
-#include "ui/base/l10n/l10n_util.h"
 #include "url/android/gurl_android.h"
 #include "url/gurl.h"
 #include "url/origin.h"
@@ -56,13 +58,21 @@
 PasskeyCredential ConvertJavaWebAuthnCredential(
     JNIEnv* env,
     const JavaParamRef<jobject>& credential) {
+  std::vector<uint8_t> credential_id;
+  base::android::JavaByteArrayToByteVector(
+      env, Java_WebAuthnCredential_getCredentialId(env, credential),
+      &credential_id);
+
+  std::vector<uint8_t> user_id;
+  base::android::JavaByteArrayToByteVector(
+      env, Java_WebAuthnCredential_getUserId(env, credential), &user_id);
+
   return PasskeyCredential(
-      PasskeyCredential::Username(ConvertJavaStringToUTF8(
-          env, Java_WebAuthnCredential_getUsername(env, credential))),
-      PasskeyCredential::DeviceName(
-          l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_USE_SCREEN_LOCK)),
-      PasskeyCredential::BackendId(ConvertJavaStringToUTF8(
-          env, Java_WebAuthnCredential_getId(env, credential))));
+      PasskeyCredential::Source::kAndroidPhone,
+      ConvertJavaStringToUTF8(Java_WebAuthnCredential_getRpId(env, credential)),
+      std::move(credential_id), std::move(user_id),
+      ConvertJavaStringToUTF8(
+          Java_WebAuthnCredential_getUsername(env, credential)));
 }
 
 }  // namespace
@@ -117,9 +127,11 @@
   for (size_t i = 0; i < passkey_credentials.size(); ++i) {
     const PasskeyCredential& credential = passkey_credentials[i];
     Java_TouchToFillBridge_insertWebAuthnCredential(
-        env, passkey_array, i,
-        ConvertUTF16ToJavaString(env, credential.username()),
-        ConvertUTF8ToJavaString(env, credential.id()));
+        env, passkey_array, i, ConvertUTF8ToJavaString(env, credential.rp_id()),
+        base::android::ToJavaByteArray(env, credential.credential_id()),
+        base::android::ToJavaByteArray(env, credential.user_id()),
+        ConvertUTF16ToJavaString(
+            env, password_manager::ToUsernameString(credential.username())));
   }
 
   Java_TouchToFillBridge_showCredentials(
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.cc b/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.cc
index ff63d49..f65d270 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.cc
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate.h"
 
+#include "base/base64.h"
 #include "base/check.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_functions.h"
@@ -143,7 +144,7 @@
     return;
 
   password_client_->GetWebAuthnCredentialsDelegateForDriver(driver_.get())
-      ->SelectPasskey(credential.id());
+      ->SelectPasskey(base::Base64Encode(credential.credential_id()));
 
   CleanUpDriverAndReportOutcome(TouchToFillOutcome::kPasskeyCredentialSelected,
                                 /*show_virtual_keyboard=*/false);
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate_unittest.cc b/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate_unittest.cc
index 671e552..ab304eb 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate_unittest.cc
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller_autofill_delegate_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <tuple>
 
+#include "base/base64.h"
 #include "base/memory/raw_ptr.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
@@ -686,9 +687,9 @@
   MockTouchToFillView* weak_view = mock_view.get();
   touch_to_fill_controller().set_view(std::move(mock_view));
 
-  PasskeyCredential credential(PasskeyCredential::Username("alice@example.com"),
-                               PasskeyCredential::DeviceName(u"Pixel 7"),
-                               PasskeyCredential::BackendId("12345"));
+  PasskeyCredential credential(PasskeyCredential::Source::kAndroidPhone,
+                               "example.com", {1, 2, 3, 4}, {5, 6, 7, 8},
+                               "alice@example.com");
   std::vector<PasskeyCredential> credentials({credential});
 
   EXPECT_CALL(*weak_view,
@@ -702,7 +703,8 @@
       MakeTouchToFillControllerDelegate(
           autofill::mojom::SubmissionReadinessState::kNoInformation));
 
-  EXPECT_CALL(*webauthn_credentials_delegate(), SelectPasskey(credential.id()));
+  EXPECT_CALL(*webauthn_credentials_delegate(),
+              SelectPasskey(base::Base64Encode(credential.credential_id())));
   EXPECT_CALL(driver(), TouchToFillClosed(ShowVirtualKeyboard(false)));
   touch_to_fill_controller().OnPasskeyCredentialSelected(credentials[0]);
   histogram_tester().ExpectUniqueSample(
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.cc b/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.cc
index 65df4cb..48722f3 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.cc
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate.cc
@@ -38,8 +38,7 @@
 void TouchToFillControllerWebAuthnDelegate::OnPasskeyCredentialSelected(
     const password_manager::PasskeyCredential& credential,
     base::OnceClosure action_complete) {
-  request_delegate_->OnWebAuthnAccountSelected(
-      *base::Base64Decode(credential.id()));
+  request_delegate_->OnWebAuthnAccountSelected(credential.credential_id());
   std::move(action_complete).Run();
 }
 
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate_unittest.cc b/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate_unittest.cc
index e183e37c..f19d1bf6b 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate_unittest.cc
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller_webauthn_delegate_unittest.cc
@@ -31,32 +31,20 @@
 using ::testing::ElementsAreArray;
 using ::testing::Eq;
 
+constexpr char kRpId[] = "example.com";
 constexpr char kExampleCom[] = "https://example.com/";
-constexpr uint8_t kUserId1[] = {'1', '2', '3', '4'};
-constexpr uint8_t kUserId2[] = {'5', '6', '7', '8'};
+const std::vector<uint8_t> kCredentialId1 = {'a', 'b', 'c', 'd'};
+const std::vector<uint8_t> kCredentialId2 = {'e', 'f', 'g', 'h'};
+const std::vector<uint8_t> kUserId1 = {'1', '2', '3', '4'};
 constexpr char kUserName1[] = "John.Doe@example.com";
-constexpr char kUserName2[] = "Jane.Doe@example.com";
 
-std::vector<uint8_t> UserId1AsVector() {
-  return std::vector<uint8_t>(std::begin(kUserId1), std::end(kUserId1));
-}
-std::vector<uint8_t> UserId2AsVector() {
-  return std::vector<uint8_t>(std::begin(kUserId2), std::end(kUserId2));
-}
-std::string UserId1AsString() {
-  return base::Base64Encode(kUserId1);
-}
-std::string UserId2AsString() {
-  return base::Base64Encode(kUserId2);
-}
-std::string UserName1() {
-  return std::string(kUserName1);
-}
-std::string UserName2() {
-  return std::string(kUserName2);
-}
-std::u16string DeviceName() {
-  return u"Use your lock screen";
+PasskeyCredential CreatePasskey(
+    std::vector<uint8_t> credential_id = kCredentialId1,
+    std::vector<uint8_t> user_id = kUserId1,
+    std::string username = kUserName1) {
+  return PasskeyCredential(PasskeyCredential::Source::kAndroidPhone, kRpId,
+                           std::move(credential_id), std::move(user_id),
+                           std::move(username));
 }
 
 class MockWebAuthnRequestDelegateAndroid
@@ -145,10 +133,7 @@
 };
 
 TEST_F(TouchToFillControllerWebAuthnTest, ShowAndSelectCredential) {
-  PasskeyCredential credential((PasskeyCredential::Username(UserName1())),
-                               PasskeyCredential::DeviceName(DeviceName()),
-                               PasskeyCredential::BackendId(UserId1AsString()));
-  std::vector<PasskeyCredential> credentials({credential});
+  std::vector<PasskeyCredential> credentials{CreatePasskey()};
 
   EXPECT_CALL(view(),
               Show(Eq(GURL(kExampleCom)), IsOriginSecure(true),
@@ -159,21 +144,13 @@
   touch_to_fill_controller().Show({}, credentials,
                                   MakeTouchToFillControllerDelegate());
 
-  EXPECT_CALL(request_delegate(), OnWebAuthnAccountSelected(UserId1AsVector()));
+  EXPECT_CALL(request_delegate(), OnWebAuthnAccountSelected(kCredentialId1));
   touch_to_fill_controller().OnPasskeyCredentialSelected(credentials[0]);
 }
 
 TEST_F(TouchToFillControllerWebAuthnTest, ShowAndSelectWithMultipleCredential) {
-  PasskeyCredential credential1(
-      (PasskeyCredential::Username(UserName1())),
-      PasskeyCredential::DeviceName(DeviceName()),
-      PasskeyCredential::BackendId(UserId1AsString()));
-
-  PasskeyCredential credential2(
-      (PasskeyCredential::Username(UserName2())),
-      PasskeyCredential::DeviceName(DeviceName()),
-      PasskeyCredential::BackendId(UserId2AsString()));
-  std::vector<PasskeyCredential> credentials({credential1, credential2});
+  std::vector<PasskeyCredential> credentials(
+      {CreatePasskey(kCredentialId1), CreatePasskey(kCredentialId2)});
 
   EXPECT_CALL(view(),
               Show(Eq(GURL(kExampleCom)), IsOriginSecure(true),
@@ -184,15 +161,12 @@
   touch_to_fill_controller().Show({}, credentials,
                                   MakeTouchToFillControllerDelegate());
 
-  EXPECT_CALL(request_delegate(), OnWebAuthnAccountSelected(UserId2AsVector()));
+  EXPECT_CALL(request_delegate(), OnWebAuthnAccountSelected(kCredentialId2));
   touch_to_fill_controller().OnPasskeyCredentialSelected(credentials[1]);
 }
 
 TEST_F(TouchToFillControllerWebAuthnTest, ShowAndCancel) {
-  PasskeyCredential credential((PasskeyCredential::Username(UserName1())),
-                               PasskeyCredential::DeviceName(DeviceName()),
-                               PasskeyCredential::BackendId(UserId1AsString()));
-  std::vector<PasskeyCredential> credentials({credential});
+  std::vector<PasskeyCredential> credentials({CreatePasskey()});
 
   EXPECT_CALL(view(),
               Show(Eq(GURL(kExampleCom)), IsOriginSecure(true),
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
index d0c9b0a..b597699 100644
--- a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
+++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
@@ -11,7 +11,6 @@
 
 #include "base/functional/bind.h"
 #include "base/strings/stringprintf.h"
-#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/time/time.h"
@@ -53,10 +52,6 @@
 class InfoBarAndroid;
 }
 
-constexpr char kTabUnderVisibleTime[] = "Tab.TabUnder.VisibleTime";
-constexpr char kTabUnderVisibleTimeBefore[] = "Tab.TabUnder.VisibleTimeBefore";
-constexpr char kPopupToTabUnder[] = "Tab.TabUnder.PopupToTabUnderTime";
-
 class PopupOpenerTabHelperTest : public ChromeRenderViewHostTestHarness {
  public:
   PopupOpenerTabHelperTest() : ChromeRenderViewHostTestHarness() {}
@@ -135,8 +130,6 @@
 
   base::SimpleTestTickClock* raw_clock() { return &raw_clock_; }
 
-  base::HistogramTester* histogram_tester() { return &histogram_tester_; }
-
 #if BUILDFLAG(IS_ANDROID)
   messages::MessageWrapper* message_wrapper() {
     return framebust_blocked_message_delegate_->message_for_testing();
@@ -151,7 +144,6 @@
   }
 
  private:
-  base::HistogramTester histogram_tester_;
   base::SimpleTestTickClock raw_clock_;
   std::vector<std::unique_ptr<content::WebContents>> popups_;
 #if BUILDFLAG(IS_ANDROID)
@@ -161,211 +153,6 @@
 #endif
 };
 
-TEST_F(PopupOpenerTabHelperTest, LogVisibleTime) {
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-  raw_clock()->Advance(base::Minutes(1));
-
-  web_contents()->WasHidden();
-
-  NavigateAndCommitWithoutGesture(GURL("https://example.test/"));
-
-  raw_clock()->Advance(base::Minutes(1));
-  web_contents()->WasShown();
-  raw_clock()->Advance(base::Seconds(1));
-
-  DeleteContents();
-
-  histogram_tester()->ExpectUniqueSample(
-      "Tab.VisibleTime", base::Seconds(60 + 1).InMilliseconds(), 1);
-}
-
-TEST_F(PopupOpenerTabHelperTest, SimpleTabUnder_LogsMetrics) {
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-
-  // Spend 1s on the page before doing anything.
-  raw_clock()->Advance(base::Seconds(1));
-
-  // Popup and then navigate 50ms after.
-  SimulatePopup();
-  raw_clock()->Advance(base::Milliseconds(50));
-  NavigateAndCommitWithoutGesture(GURL("https://example.test/"));
-
-  // Spent 100 ms on the opener before closing it.
-  raw_clock()->Advance(base::Minutes(1));
-  web_contents()->WasShown();
-  raw_clock()->Advance(base::Milliseconds(100));
-  DeleteContents();
-
-  histogram_tester()->ExpectUniqueSample(kTabUnderVisibleTimeBefore, 1050, 1);
-  histogram_tester()->ExpectUniqueSample(kTabUnderVisibleTime, 100, 1);
-  histogram_tester()->ExpectUniqueSample(kPopupToTabUnder, 50, 1);
-}
-
-TEST_F(PopupOpenerTabHelperTest, TabUnderAfterRedirect_LogsMetrics) {
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-
-  // Popup and then navigate 50ms after.
-  SimulatePopup();
-  raw_clock()->Advance(base::Milliseconds(50));
-
-  std::unique_ptr<content::NavigationSimulator> simulator =
-      content::NavigationSimulator::CreateRendererInitiated(
-          GURL("https://first.test"), main_rfh());
-  simulator->SetHasUserGesture(false);
-  simulator->Start();
-
-  // Foreground the tab before the navigation redirects cross process. Note that
-  // currently, this time does not get accounted for in the visibility metrics,
-  // though we may want to include it in the future.
-  web_contents()->WasShown();
-  raw_clock()->Advance(base::Milliseconds(10));
-
-  simulator->Redirect(GURL("https://example.test/"));
-  raw_clock()->Advance(base::Milliseconds(15));
-
-  simulator->Commit();
-
-  // Spent 100 additional ms on the opener before closing it.
-  raw_clock()->Advance(base::Milliseconds(100));
-  DeleteContents();
-
-  histogram_tester()->ExpectUniqueSample(kTabUnderVisibleTime, 115, 1);
-  histogram_tester()->ExpectUniqueSample(kPopupToTabUnder, 60, 1);
-}
-
-TEST_F(PopupOpenerTabHelperTest, FirstNavigation_NoLogging) {
-  SimulatePopup();
-  web_contents()->WasHidden();
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-  raw_clock()->Advance(base::Minutes(1));
-  DeleteContents();
-  histogram_tester()->ExpectTotalCount(kTabUnderVisibleTime, 0);
-}
-
-TEST_F(PopupOpenerTabHelperTest, VisibleNavigation_NoLogging) {
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-  SimulatePopup();
-  web_contents()->WasShown();
-  NavigateAndCommitWithoutGesture(GURL("https://example.test/"));
-  raw_clock()->Advance(base::Minutes(1));
-  DeleteContents();
-  histogram_tester()->ExpectTotalCount(kTabUnderVisibleTime, 0);
-}
-
-// This is counter intuitive, but we want to log metrics in the dry-run state if
-// we would have blocked the navigation. So, even though the user ends up
-// aborting the navigation, it still counts as a tab-under for metrics purposes,
-// because we would have intervened.
-TEST_F(PopupOpenerTabHelperTest, AbortedNavigationAfterStart_LogsMetrics) {
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-  SimulatePopup();
-
-  std::unique_ptr<content::NavigationSimulator> simulator =
-      content::NavigationSimulator::CreateRendererInitiated(
-          GURL("https://example.test/"), main_rfh());
-  simulator->SetHasUserGesture(false);
-  simulator->Fail(net::ERR_ABORTED);
-
-  raw_clock()->Advance(base::Minutes(1));
-  DeleteContents();
-  histogram_tester()->ExpectTotalCount(kTabUnderVisibleTime, 1);
-}
-
-// See comment in the AbortedNavigation case above.
-TEST_F(PopupOpenerTabHelperTest, FailedNavigation_NoLogging) {
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-  SimulatePopup();
-
-  std::unique_ptr<content::NavigationSimulator> simulator =
-      content::NavigationSimulator::CreateRendererInitiated(
-          GURL("https://example.test/"), main_rfh());
-  simulator->SetHasUserGesture(false);
-  simulator->Fail(net::ERR_CONNECTION_RESET);
-
-  raw_clock()->Advance(base::Minutes(1));
-  DeleteContents();
-  histogram_tester()->ExpectTotalCount(kTabUnderVisibleTime, 1);
-}
-
-// Aborts the navigation before the cross-origin redirect.
-TEST_F(PopupOpenerTabHelperTest, AbortedNavigationBeforeRedirect_LogsMetrics) {
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-  SimulatePopup();
-
-  std::unique_ptr<content::NavigationSimulator> simulator =
-      content::NavigationSimulator::CreateRendererInitiated(
-          GURL("https://first.test/path"), main_rfh());
-  simulator->SetHasUserGesture(false);
-  simulator->Start();
-  simulator->Fail(net::ERR_ABORTED);
-
-  raw_clock()->Advance(base::Minutes(1));
-  DeleteContents();
-  histogram_tester()->ExpectTotalCount(kTabUnderVisibleTime, 0);
-}
-
-TEST_F(PopupOpenerTabHelperTest, SameOriginNavigation_NoLogging) {
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-  SimulatePopup();
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/path"));
-
-  raw_clock()->Advance(base::Minutes(1));
-  DeleteContents();
-  histogram_tester()->ExpectTotalCount(kTabUnderVisibleTime, 0);
-}
-
-TEST_F(PopupOpenerTabHelperTest, HasUserGesture_NoLogging) {
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-
-  SimulatePopup();
-  std::unique_ptr<content::NavigationSimulator> simulator =
-      content::NavigationSimulator::CreateRendererInitiated(
-          GURL("https://example.test/"), main_rfh());
-  simulator->SetHasUserGesture(true);
-  simulator->Commit();
-
-  raw_clock()->Advance(base::Minutes(1));
-  DeleteContents();
-  histogram_tester()->ExpectTotalCount(kTabUnderVisibleTime, 0);
-}
-
-TEST_F(PopupOpenerTabHelperTest, OpenPopupNoRedirect_NoLogging) {
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-  SimulatePopup();
-  DeleteContents();
-  histogram_tester()->ExpectTotalCount(kTabUnderVisibleTime, 0);
-  histogram_tester()->ExpectTotalCount(kPopupToTabUnder, 0);
-}
-
-// Same as simple tab-under case, but this one starts the navigation before
-// issuing the popup. Currently, this case is not supported.
-TEST_F(PopupOpenerTabHelperTest, SimulateTabUnderNavBeforePopup_LogsMetrics) {
-  NavigateAndCommitWithoutGesture(GURL("https://first.test/"));
-
-  // Start navigating, then popup, then commit.
-  raw_clock()->Advance(base::Milliseconds(50));
-  std::unique_ptr<content::NavigationSimulator> simulator =
-      content::NavigationSimulator::CreateRendererInitiated(
-          GURL("https://example.test/"), main_rfh());
-  simulator->SetHasUserGesture(false);
-  simulator->Start();
-  SimulatePopup();
-  simulator->Commit();
-
-  // Spent 100 ms on the opener before closing it.
-  raw_clock()->Advance(base::Minutes(1));
-  web_contents()->WasShown();
-  raw_clock()->Advance(base::Milliseconds(100));
-  DeleteContents();
-
-  // No histograms are logged because:
-  // 1. The navigation starts in the foreground.
-  // 2. The popup is issued before the navigation, and the popup metrics only
-  //    log for navigations after the popup.
-  histogram_tester()->ExpectTotalCount(kTabUnderVisibleTime, 0);
-  histogram_tester()->ExpectTotalCount(kPopupToTabUnder, 0);
-}
-
 // Navigate to a site without pop-ups, verify the user popup settings are not
 // logged to ukm.
 TEST_F(PopupOpenerTabHelperTest,
diff --git a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc
index 64d5813..4c0205c 100644
--- a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc
+++ b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc
@@ -150,10 +150,6 @@
 
   seen_tab_under_ = true;
   content::WebContents* contents = navigation_handle()->GetWebContents();
-  auto* popup_opener =
-      blocked_content::PopupOpenerTabHelper::FromWebContents(contents);
-  DCHECK(popup_opener);
-  popup_opener->OnDidTabUnder();
 
   LogTabUnderAttempt(navigation_handle());
 
diff --git a/chrome/browser/ui/commerce/price_tracking/shopping_list_ui_tab_helper_unittest.cc b/chrome/browser/ui/commerce/price_tracking/shopping_list_ui_tab_helper_unittest.cc
index a0542609..a83f6fb 100644
--- a/chrome/browser/ui/commerce/price_tracking/shopping_list_ui_tab_helper_unittest.cc
+++ b/chrome/browser/ui/commerce/price_tracking/shopping_list_ui_tab_helper_unittest.cc
@@ -78,6 +78,7 @@
 
   void TearDown() override {
     // Make sure the tab helper id destroyed before any of its dependencies are.
+    tab_helper_ = nullptr;
     web_contents_->RemoveUserData(ShoppingListUiTabHelper::UserDataKey());
   }
 
@@ -138,12 +139,16 @@
   std::unique_ptr<MockShoppingService> shopping_service_;
   std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_;
   std::unique_ptr<image_fetcher::MockImageFetcher> image_fetcher_;
-  base::raw_ptr<content::WebContents> web_contents_;
 
  private:
   content::BrowserTaskEnvironment task_environment_;
   TestingProfile profile_;
+
+  // Must outlive `web_contents_`.
   content::TestWebContentsFactory test_web_contents_factory_;
+
+ protected:
+  base::raw_ptr<content::WebContents> web_contents_;
 };
 
 TEST_F(ShoppingListUiTabHelperTest, TestSubscriptionEventsUpdateState) {
diff --git a/chrome/browser/ui/views/frame/test_with_browser_view.cc b/chrome/browser/ui/views/frame/test_with_browser_view.cc
index 458191b..eca283f 100644
--- a/chrome/browser/ui/views/frame/test_with_browser_view.cc
+++ b/chrome/browser/ui/views/frame/test_with_browser_view.cc
@@ -86,8 +86,7 @@
   browser_view_->browser()->tab_strip_model()->CloseAllTabs();
   // Ensure the Browser is reset before BrowserWithTestWindowTest cleans up
   // the Profile.
-  browser_view_->GetWidget()->CloseNow();
-  browser_view_ = nullptr;
+  browser_view_.ExtractAsDangling()->GetWidget()->CloseNow();
   content::RunAllTasksUntilIdle();
   BrowserWithTestWindowTest::TearDown();
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
index c127502..9a2e086 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
+++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
@@ -132,12 +132,14 @@
 
   if (!content_setting_image_model_->is_visible()) {
     SetVisible(false);
+    GetViewAccessibility().OverrideIsIgnored(true);
     critical_promo_bubble_.reset();
     return;
   }
   DCHECK(web_contents);
   UpdateImage();
   SetVisible(true);
+  GetViewAccessibility().OverrideIsIgnored(false);
 
   if (content_setting_image_model_->ShouldNotifyAccessibility(web_contents)) {
     auto name = l10n_util::GetStringUTF16(
diff --git a/chrome/browser/ui/views/safe_browsing/tailored_security_unconsented_modal.cc b/chrome/browser/ui/views/safe_browsing/tailored_security_unconsented_modal.cc
index 4e1c356..1a033317 100644
--- a/chrome/browser/ui/views/safe_browsing/tailored_security_unconsented_modal.cc
+++ b/chrome/browser/ui/views/safe_browsing/tailored_security_unconsented_modal.cc
@@ -9,10 +9,12 @@
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "components/safe_browsing/core/browser/tailored_security_service/tailored_security_outcome.h"
+#include "components/safe_browsing/core/common/features.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "content/public/browser/web_contents.h"
@@ -25,6 +27,8 @@
 #include "ui/gfx/image/image_skia_operations.h"
 #include "ui/views/bubble/bubble_frame_view.h"
 #include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/layout_provider.h"
 
 namespace safe_browsing {
@@ -95,6 +99,17 @@
   SetModalType(ui::MODAL_TYPE_CHILD);
 
   SetTitle(IDS_TAILORED_SECURITY_UNCONSENTED_MODAL_TITLE);
+  if (base::FeatureList::IsEnabled(
+          safe_browsing::kTailoredSecurityUpdatedMessages)) {
+    // TODO(crbug.com/1439615) Update the modal width to match the mocks.
+    AddChildView(std::make_unique<views::Label>(l10n_util::GetStringUTF16(
+        IDS_TAILORED_SECURITY_UNCONSENTED_MODAL_BODY)));
+    SetLayoutManager(std::make_unique<views::BoxLayout>(
+        views::BoxLayout::Orientation::kVertical,
+        ChromeLayoutProvider::Get()->GetInsetsMetric(views::INSETS_DIALOG),
+        ChromeLayoutProvider::Get()->GetDistanceMetric(
+            views::DISTANCE_RELATED_LABEL_HORIZONTAL)));
+  }
   SetButtonLabel(ui::DIALOG_BUTTON_OK,
                  l10n_util::GetStringUTF16(
                      IDS_TAILORED_SECURITY_UNCONSENTED_ACCEPT_BUTTON));
diff --git a/chrome/browser/ui/views/toolbar/app_menu.cc b/chrome/browser/ui/views/toolbar/app_menu.cc
index a6d7a30..671ab01 100644
--- a/chrome/browser/ui/views/toolbar/app_menu.cc
+++ b/chrome/browser/ui/views/toolbar/app_menu.cc
@@ -257,8 +257,7 @@
     SetFocusBehavior(FocusBehavior::ALWAYS);
     SetHorizontalAlignment(gfx::ALIGN_CENTER);
 
-    SetBackground(std::make_unique<InMenuButtonBackground>(
-        InMenuButtonBackground::ButtonType::kNoBorder));
+    SetBackground(std::make_unique<InMenuButtonBackground>(type));
     SetBorder(views::CreateEmptyBorder(
         gfx::Insets::TLBR(0, kHorizontalPadding, 0, kHorizontalPadding)));
     label()->SetFontList(MenuConfig::instance().font_list);
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
index 0a3b185..6148c1f 100644
--- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
+++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
@@ -33,7 +33,7 @@
   // different screen densities, make the ideal size be the size which works
   // with a high density display (if the OS supports high density displays).
   float max_supported_scale = ui::GetScaleForResourceScaleFactor(
-      ui::GetSupportedResourceScaleFactors().back());
+      ui::GetMaxSupportedResourceScaleFactor());
   return round(GetBrandIconMinimumSize() * max_supported_scale);
 }
 
diff --git a/chrome/browser/ui/webui/ash/add_supervision/add_supervision_ui.cc b/chrome/browser/ui/webui/ash/add_supervision/add_supervision_ui.cc
index 43f6526d..14e41eb8 100644
--- a/chrome/browser/ui/webui/ash/add_supervision/add_supervision_ui.cc
+++ b/chrome/browser/ui/webui/ash/add_supervision/add_supervision_ui.cc
@@ -21,6 +21,8 @@
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/generated_resources.h"
+#include "chrome/grit/supervision_resources.h"
+#include "chrome/grit/supervision_resources_map.h"
 #include "components/google/core/common/google_util.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -204,16 +206,19 @@
   source->AddResourcePath("add_supervision_api_server.js",
                           IDR_ADD_SUPERVISION_API_SERVER_JS);
   source->AddResourcePath("add_supervision_ui.js", IDR_ADD_SUPERVISION_UI_JS);
-  source->AddResourcePath("images/network_unavailable.svg",
-                          IDR_ADD_SUPERVISION_NETWORK_UNAVAILABLE_SVG);
+  source->AddResourcePath("add_supervision_app.js", IDR_ADD_SUPERVISION_APP_JS);
+  source->AddResourcePaths(
+      base::make_span(kSupervisionResources, kSupervisionResourcesSize));
 
   source->AddLocalizedString("pageTitle", IDS_ADD_SUPERVISION_PAGE_TITLE);
-  source->AddLocalizedString("networkDownHeading",
-                             IDS_ADD_SUPERVISION_NETWORK_DOWN_HEADING);
-  source->AddLocalizedString("networkDownDescription",
-                             IDS_ADD_SUPERVISION_NETWORK_DOWN_DESCRIPTION);
-  source->AddLocalizedString("networkDownButtonLabel",
-                             IDS_ADD_SUPERVISION_NETWORK_DOWN_BUTTON_LABEL);
+  source->AddLocalizedString("supervisedUserErrorDescription",
+                             IDS_SUPERVISED_USER_ERROR_DESCRIPTION);
+  source->AddLocalizedString("supervisedUserErrorTitle",
+                             IDS_SUPERVISED_USER_ERROR_TITLE);
+  source->AddLocalizedString("supervisedUserOfflineDescription",
+                             IDS_SUPERVISED_USER_OFFLINE_DESCRIPTION);
+  source->AddLocalizedString("supervisedUserOfflineTitle",
+                             IDS_SUPERVISED_USER_OFFLINE_TITLE);
 
   // Full paths (relative to src) are important for Mojom generated files.
   source->AddResourcePath(
diff --git a/chrome/browser/ui/webui/ash/add_supervision/add_supervision_ui_browsertest.cc b/chrome/browser/ui/webui/ash/add_supervision/add_supervision_ui_browsertest.cc
index f67f819..a9d999a 100644
--- a/chrome/browser/ui/webui/ash/add_supervision/add_supervision_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/ash/add_supervision/add_supervision_ui_browsertest.cc
@@ -19,15 +19,28 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/network_connection_change_simulator.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace ash {
 
 namespace {
+// Element references for use in test scripts.
+const char kGetAddSupervisionAppElementJS[] =
+    "document.querySelector('add-supervision-app')";
 
 const char kGetAddSupervisionUIElementJS[] =
-    "document.querySelector('add-supervision-ui')";
-}
+    "document.querySelector('add-supervision-app')"
+    ".shadowRoot.querySelector('add-supervision-ui')";
+
+const char kGetSupervisedUserOfflineElementJS[] =
+    "document.querySelector('add-supervision-app')"
+    ".shadowRoot.querySelector('supervised-user-offline')";
+
+const char kGetSupervisedUserErrorElementJS[] =
+    "document.querySelector('add-supervision-app')"
+    ".shadowRoot.querySelector('supervised-user-error')";
+}  // namespace
 
 // Base class for AddSupervision tests.
 class AddSupervisionBrowserTest : public InProcessBrowserTest {
@@ -41,6 +54,7 @@
   ~AddSupervisionBrowserTest() override = default;
 
   void SetUpOnMainThread() override {
+    embedded_test_server()->StartAcceptingConnections();
     // TODO(danan):  See if this is possible to do this instead using
     // FakeGaia.IssueOAuthToken().
     identity_test_env_ = std::make_unique<signin::IdentityTestEnvironment>();
@@ -58,6 +72,14 @@
             AddSupervisionMetricsRecorder::EnrollmentState::kInitiated);
   }
 
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    embedded_test_server()->ServeFilesFromSourceDirectory("chrome/test/data");
+    ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+    command_line->AppendSwitchASCII(
+        "add-supervision-url",
+        embedded_test_server()->GetURL("/supervised_user/simple.html").spec());
+  }
+
   AddSupervisionUI* GetAddSupervisionUI() {
     return static_cast<AddSupervisionUI*>(
         contents()->GetWebUI()->GetController());
@@ -73,14 +95,15 @@
     return GURL(chrome::kChromeUIAddSupervisionURL);
   }
 
-  bool IsElementVisible(const std::string& element_selector) {
+  bool IsScreenActive(const std::string& element_selector) {
     bool found;
-    bool hidden;
-    std::string script = std::string("domAutomationController.send(") +
-                         element_selector + ".hidden);";
-    LOG(ERROR) << "Script: " << script;
-    found = content::ExecuteScriptAndExtractBool(contents(), script, &hidden);
-    return found && !hidden;
+    bool active;
+    std::string is_active = std::string("domAutomationController.send(") +
+                            element_selector +
+                            ".classList.contains('active'));";
+    found =
+        content::ExecuteScriptAndExtractBool(contents(), is_active, &active);
+    return found && active;
   }
 
  private:
@@ -131,33 +154,28 @@
       ui_test_utils::NavigateToURL(browser(), add_supervision_webui_url()));
   EXPECT_TRUE(content::WaitForLoadStop(contents()));
 
-  // Webview div should be initially visible.
-  ASSERT_TRUE(IsElementVisible(std::string(kGetAddSupervisionUIElementJS) +
-                               std::string(".webviewDiv")));
+  // The online screen should be initially active.
+  EXPECT_TRUE(IsScreenActive(std::string(kGetAddSupervisionUIElementJS)));
+
+  EXPECT_FALSE(IsScreenActive(std::string(kGetSupervisedUserOfflineElementJS)));
 
   // Simulate going offline.
-  ASSERT_TRUE(content::ExecuteScript(
+  EXPECT_TRUE(content::ExecuteScript(
       contents(), "window.dispatchEvent(new CustomEvent('offline'));"));
 
-  // Ensure the offline content view is shown.
-  ASSERT_TRUE(IsElementVisible(std::string(kGetAddSupervisionUIElementJS) +
-                               std::string(".offlineContentDiv")));
+  // Ensure only the offline screen is active.
+  EXPECT_TRUE(IsScreenActive(std::string(kGetSupervisedUserOfflineElementJS)));
 
-  // Ensure the online webview content content is hidden.
-  ASSERT_FALSE(IsElementVisible(std::string(kGetAddSupervisionUIElementJS) +
-                                std::string(".webviewDiv")));
+  EXPECT_FALSE(IsScreenActive(std::string(kGetAddSupervisionUIElementJS)));
 
   // Simulate going online.
-  ASSERT_TRUE(content::ExecuteScript(
+  EXPECT_TRUE(content::ExecuteScript(
       contents(), "window.dispatchEvent(new CustomEvent('online'));"));
 
-  // Offline div should be hidden.
-  ASSERT_FALSE(IsElementVisible(std::string(kGetAddSupervisionUIElementJS) +
-                                std::string(".offlineContentDiv")));
+  // Ensure only the online screen is active.
+  EXPECT_TRUE(IsScreenActive(std::string(kGetAddSupervisionUIElementJS)));
 
-  // Webview div should be shown.
-  ASSERT_TRUE(IsElementVisible(std::string(kGetAddSupervisionUIElementJS) +
-                               std::string(".webviewDiv")));
+  EXPECT_FALSE(IsScreenActive(std::string(kGetSupervisedUserOfflineElementJS)));
 }
 
 IN_PROC_BROWSER_TEST_F(AddSupervisionBrowserTest, ShowConfirmSignoutDialog) {
@@ -221,4 +239,34 @@
             1);
 }
 
+IN_PROC_BROWSER_TEST_F(AddSupervisionBrowserTest, ShowErrorScreen) {
+  // Open the Add Supervision URL.
+  ASSERT_TRUE(
+      ui_test_utils::NavigateToURL(browser(), add_supervision_webui_url()));
+  EXPECT_TRUE(content::WaitForLoadStop(contents()));
+
+  // The online screen should be initially active.
+  EXPECT_TRUE(IsScreenActive(std::string(kGetAddSupervisionUIElementJS)));
+
+  // Simulate an error event.
+  EXPECT_TRUE(content::ExecuteScript(
+      contents(), std::string(kGetAddSupervisionAppElementJS) +
+                      std::string(".dispatchEvent(new CustomEvent('show-error',"
+                                  "{bubbles: true, composed: true}));")));
+
+  // Ensure that the error screen is active.
+  EXPECT_TRUE(IsScreenActive(std::string(kGetSupervisedUserErrorElementJS)));
+
+  EXPECT_FALSE(IsScreenActive(std::string(kGetAddSupervisionUIElementJS)));
+
+  // Simulate an offline event.
+  EXPECT_TRUE(content::ExecuteScript(
+      contents(), "window.dispatchEvent(new CustomEvent('offline'));"));
+
+  // Ensure that the error screen remains active.
+  EXPECT_TRUE(IsScreenActive(std::string(kGetSupervisedUserErrorElementJS)));
+
+  EXPECT_FALSE(IsScreenActive(std::string(kGetSupervisedUserOfflineElementJS)));
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ui/webui/password_manager/promo_card.cc b/chrome/browser/ui/webui/password_manager/promo_card.cc
index 82df89a..9d8c8b35 100644
--- a/chrome/browser/ui/webui/password_manager/promo_card.cc
+++ b/chrome/browser/ui/webui/password_manager/promo_card.cc
@@ -7,6 +7,7 @@
 #include "base/functional/bind.h"
 #include "base/json/values_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/notreached.h"
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -26,6 +27,20 @@
 
 namespace {
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class PromoCardType {
+  // Password Checkup promo bubble.
+  kCheckup = 0,
+  // Password on the web promo bubble.
+  kWebPasswordManager = 1,
+  // Add shortcut promo bubble.
+  kAddShortcut = 2,
+  // Access passwords on iOS/Android promo bubble.
+  kAccessOnAnyDevice = 3,
+  kMaxValue = kAccessOnAnyDevice,
+};
+
 constexpr base::TimeDelta kPasswordCheckupPromoPeriod = base::Days(7);
 constexpr int kPromoDisplayLimit = 3;
 
@@ -54,6 +69,19 @@
   return promo_card_pref_entry;
 }
 
+PromoCardType ConvertIdToType(const std::string& promo_id) {
+  if (promo_id == kCheckupPromoId) {
+    return PromoCardType::kCheckup;
+  } else if (promo_id == kWebPasswordManagerPromoId) {
+    return PromoCardType::kWebPasswordManager;
+  } else if (promo_id == kShortcutPromoId) {
+    return PromoCardType::kAddShortcut;
+  } else if (promo_id == kAccessOnAnyDevicePromoId) {
+    return PromoCardType::kAccessOnAnyDevice;
+  }
+  NOTREACHED_NORETURN();
+}
+
 }  // namespace
 
 // static
@@ -108,9 +136,11 @@
   for (auto& promo_card_pref : update.Get()) {
     if (*promo_card_pref.GetDict().FindString(kIdKey) == GetPromoID()) {
       promo_card_pref.GetDict().Set(kWasDismissedKey, true);
-      return;
+      break;
     }
   }
+  base::UmaHistogramEnumeration("PasswordManager.PromoCard.Dismissed",
+                                ConvertIdToType(GetPromoID()));
 }
 
 void PromoCardInterface::OnPromoCardShown() {
@@ -124,9 +154,11 @@
                                     number_of_times_shown_);
       promo_card_pref.GetDict().Set(kLastTimeShownKey,
                                     base::TimeToValue(last_time_shown_));
-      return;
+      break;
     }
   }
+  base::UmaHistogramEnumeration("PasswordManager.PromoCard.Shown",
+                                ConvertIdToType(GetPromoID()));
 }
 
 PasswordCheckupPromo::PasswordCheckupPromo(
diff --git a/chrome/browser/ui/webui/password_manager/promo_card_unittest.cc b/chrome/browser/ui/webui/password_manager/promo_card_unittest.cc
index 775db91..5fbdface 100644
--- a/chrome/browser/ui/webui/password_manager/promo_card_unittest.cc
+++ b/chrome/browser/ui/webui/password_manager/promo_card_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/json/values_util.h"
 #include "base/test/bind.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
@@ -65,7 +66,7 @@
   explicit FakePromoCard(PrefService* prefs)
       : PromoCardInterface(GetPromoID(), prefs) {}
 
-  static constexpr char kId[] = "fake_promo_card";
+  static constexpr char kId[] = "password_checkup_promo";
 
   // PromoCardInterface implementation.
   std::string GetPromoID() const override { return kId; }
@@ -289,6 +290,8 @@
 }
 
 TEST_F(PromoCardCheckupTest, PromoShownIn7DaysAfterDismiss) {
+  base::HistogramTester histogram_tester;
+
   SavePassword();
 
   ASSERT_THAT(pref_service()->GetList(prefs::kPasswordManagerPromoCardsList),
@@ -304,6 +307,10 @@
   // Check that in 7 days it's shown again even after dismissing.
   task_environment()->AdvanceClock(base::Days(7) + base::Seconds(1));
   EXPECT_TRUE(promo->ShouldShowPromo());
+
+  histogram_tester.ExpectUniqueSample("PasswordManager.PromoCard.Shown", 0, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.PromoCard.Dismissed", 0,
+                                      1);
 }
 
 class PromoCardInWebTest : public PromoCardBaseTest {
@@ -376,6 +383,8 @@
 }
 
 TEST_F(PromoCardInWebTest, PromoNotShownAfterDismiss) {
+  base::HistogramTester histogram_tester;
+
   sync_service()->SetLocalSyncEnabled(false);
   ASSERT_TRUE(sync_service()->IsSyncFeatureEnabled());
 
@@ -387,6 +396,8 @@
 
   promo->OnPromoCardDismissed();
   EXPECT_FALSE(promo->ShouldShowPromo());
+  histogram_tester.ExpectUniqueSample("PasswordManager.PromoCard.Dismissed", 1,
+                                      1);
 }
 
 class PromoCardShortcutTest : public WebAppTest {
@@ -435,6 +446,7 @@
 }
 
 TEST_F(PromoCardShortcutTest, PromoNotShownAfterDismiss) {
+  base::HistogramTester histogram_tester;
   ASSERT_THAT(pref_service()->GetList(prefs::kPasswordManagerPromoCardsList),
               IsEmpty());
   std::unique_ptr<PromoCardInterface> promo =
@@ -443,6 +455,8 @@
 
   promo->OnPromoCardDismissed();
   EXPECT_FALSE(promo->ShouldShowPromo());
+  histogram_tester.ExpectUniqueSample("PasswordManager.PromoCard.Dismissed", 2,
+                                      1);
 }
 
 using PromoCardAccessAnyDeviceTest = PromoCardBaseTest;
@@ -463,6 +477,7 @@
 }
 
 TEST_F(PromoCardAccessAnyDeviceTest, PromoNotShownAfterDismiss) {
+  base::HistogramTester histogram_tester;
   ASSERT_THAT(pref_service()->GetList(prefs::kPasswordManagerPromoCardsList),
               IsEmpty());
   std::unique_ptr<PromoCardInterface> promo =
@@ -471,6 +486,8 @@
 
   promo->OnPromoCardDismissed();
   EXPECT_FALSE(promo->ShouldShowPromo());
+  histogram_tester.ExpectUniqueSample("PasswordManager.PromoCard.Dismissed", 3,
+                                      1);
 }
 
 }  // namespace password_manager
diff --git a/chrome/browser/ui/webui/password_manager/promo_cards_handler_unittest.cc b/chrome/browser/ui/webui/password_manager/promo_cards_handler_unittest.cc
index 9f5b6ba..40afa341 100644
--- a/chrome/browser/ui/webui/password_manager/promo_cards_handler_unittest.cc
+++ b/chrome/browser/ui/webui/password_manager/promo_cards_handler_unittest.cc
@@ -58,9 +58,11 @@
     prefs_.registry()->RegisterListPref(prefs::kPasswordManagerPromoCardsList);
 
     std::vector<std::unique_ptr<password_manager::PromoCardInterface>> cards;
-    cards.emplace_back(std::make_unique<MockPromoCard>("mock1", &prefs_));
+    cards.emplace_back(
+        std::make_unique<MockPromoCard>("password_checkup_promo", &prefs_));
     card1_ = static_cast<MockPromoCard*>(cards.back().get());
-    cards.emplace_back(std::make_unique<MockPromoCard>("mock2", &prefs_));
+    cards.emplace_back(
+        std::make_unique<MockPromoCard>("password_shortcut_promo", &prefs_));
     card2_ = static_cast<MockPromoCard*>(cards.back().get());
 
     auto handler =
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 946e7f2..336a7ce 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -3374,6 +3374,8 @@
     {"antiAbuseWhenOnHeader", IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_HEADER},
     {"antiAbuseWhenOnSectionOne", IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_ONE},
     {"antiAbuseWhenOnSectionTwo", IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_TWO},
+    {"antiAbuseWhenOnSectionThree",
+     IDS_SETTINGS_ANTI_ABUSE_WHEN_ON_SECTION_THREE},
     {"antiAbuseThingsToConsiderHeader",
      IDS_SETTINGS_ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER},
     {"antiAbuseThingsToConsiderSectionOne",
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_impl.cc b/chrome/browser/web_applications/externally_managed_app_manager_impl.cc
index 8fd65da..e6e9921 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager_impl.cc
+++ b/chrome/browser/web_applications/externally_managed_app_manager_impl.cc
@@ -245,8 +245,11 @@
 
       // TODO(crbug.com/1300321): Investigate re-install of the app for all
       // WebAppManagement sources.
-      if (ConvertExternalInstallSourceToSource(
-              install_options.install_source) == WebAppManagement::kPolicy) {
+      if ((ConvertExternalInstallSourceToSource(
+               install_options.install_source) == WebAppManagement::kPolicy) &&
+          (!lock.registrar()
+                .GetAppById(app_id.value())
+                ->IsPolicyInstalledApp())) {
         StartInstallationTask(std::move(front));
         return;
       } else {
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_impl_browsertest.cc b/chrome/browser/web_applications/externally_managed_app_manager_impl_browsertest.cc
index a08d53e..785a3c0e 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager_impl_browsertest.cc
+++ b/chrome/browser/web_applications/externally_managed_app_manager_impl_browsertest.cc
@@ -426,6 +426,35 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_F(ExternallyManagedAppManagerImplBrowserTest,
+                       PolicyAppOverridesUserInstalledApp) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  absl::optional<AppId> app_id;
+  {
+    // Install user app
+    auto install_info = std::make_unique<WebAppInstallInfo>();
+    GURL url(
+        embedded_test_server()->GetURL("/banners/"
+                                       "manifest_test_page.html"));
+    install_info->start_url = url;
+    install_info->title = u"Test user app";
+    app_id = test::InstallWebApp(profile(), std::move(install_info));
+    ASSERT_TRUE(app_id.has_value());
+    ASSERT_TRUE(registrar().WasInstalledByUser(app_id.value()));
+    ASSERT_FALSE(registrar().HasExternalApp(app_id.value()));
+    ASSERT_EQ("Test user app", registrar().GetAppShortName(app_id.value()));
+  }
+  {
+    // Install policy app
+    GURL url(
+        embedded_test_server()->GetURL("/banners/manifest_test_page.html"));
+    absl::optional<AppId> policy_app_id = ForceInstallWebApp(profile(), url);
+    ASSERT_EQ(policy_app_id, app_id);
+    ASSERT_EQ("Manifest test app",
+              registrar().GetAppShortName(policy_app_id.value()));
+  }
+}
+
 // Test that adding a manifest that points to a chrome:// URL does not actually
 // install a web app that points to a chrome:// URL.
 IN_PROC_BROWSER_TEST_P(ExternallyManagedBrowserTestWithPrefMigrationRead,
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc b/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc
index c78b090..371d3f7 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc
+++ b/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc
@@ -872,27 +872,23 @@
             foo_run_loop.Quit();
           }));
 
-  base::RunLoop().RunUntilIdle();
-  externally_managed_app_manager_impl().SetNextInstallationTaskResult(
-      kFooWebAppUrl, webapps::InstallResultCode::kSuccessNewInstall);
+  foo_run_loop.Run();
 
   externally_managed_app_manager_impl().Install(
       GetInstallOptionsWithWebAppInfo(kFooWebAppUrl),
       base::BindLambdaForTesting(
           [&](const GURL& url,
               ExternallyManagedAppManager::InstallResult result) {
-            EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
+            EXPECT_EQ(webapps::InstallResultCode::kSuccessAlreadyInstalled,
                       result.code);
             EXPECT_EQ(kFooWebAppUrl, url);
 
-            EXPECT_EQ(2u, install_run_count());
+            EXPECT_EQ(1u, install_run_count());
             EXPECT_EQ(GetInstallOptionsWithWebAppInfo(kFooWebAppUrl),
                       last_install_options());
 
             bar_run_loop.Quit();
           }));
-  foo_run_loop.Run();
-  base::RunLoop().RunUntilIdle();
   bar_run_loop.Run();
 }
 
@@ -1011,15 +1007,13 @@
   }
 
   {
-    externally_managed_app_manager_impl().SetNextInstallationTaskResult(
-        kFooWebAppUrl, webapps::InstallResultCode::kSuccessNewInstall);
     auto [url, code] = InstallAndWait(&externally_managed_app_manager_impl(),
                                       GetInstallOptions(kFooWebAppUrl));
 
-    EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
+    EXPECT_EQ(webapps::InstallResultCode::kSuccessAlreadyInstalled, code);
     EXPECT_EQ(kFooWebAppUrl, url);
 
-    EXPECT_EQ(2u, install_run_count());
+    EXPECT_EQ(1u, install_run_count());
   }
 }
 
@@ -1038,13 +1032,12 @@
       base::BindLambdaForTesting(
           [&](const GURL& url,
               ExternallyManagedAppManager::InstallResult result) {
-            EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
+            EXPECT_EQ(webapps::InstallResultCode::kSuccessAlreadyInstalled,
                       result.code);
             EXPECT_EQ(kFooWebAppUrl, url);
 
-            // Both installation tasks run if the install was triggered
-            // by policy.
-            EXPECT_EQ(2u, install_run_count());
+            // Only the first installation task runs
+            EXPECT_EQ(1u, install_run_count());
             EXPECT_TRUE(first_callback_ran);
             run_loop.Quit();
           }));
@@ -1060,12 +1053,10 @@
             EXPECT_EQ(1u, install_run_count());
             EXPECT_EQ(GetInstallOptions(kFooWebAppUrl), last_install_options());
             first_callback_ran = true;
-            externally_managed_app_manager_impl().SetNextInstallationTaskResult(
-                kFooWebAppUrl, webapps::InstallResultCode::kSuccessNewInstall);
           }));
   run_loop.Run();
 
-  EXPECT_EQ(2u, install_run_count());
+  EXPECT_EQ(1u, install_run_count());
   EXPECT_EQ(GetInstallOptions(kFooWebAppUrl), last_install_options());
 }
 
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc b/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc
index 23bdbb6e..93470e4 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc
+++ b/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc
@@ -647,6 +647,57 @@
                                              /*additional_policy_ids=*/{}))));
 }
 
+TEST_F(ExternallyAppManagerTest, PolicyAppOverridesUserInstalledApp) {
+  const GURL kStartUrl = GURL("https://www.example.com/index.html");
+  const GURL kInstallUrl =
+      GURL("https://www.example.com/nested/install_url.html");
+  const GURL kManifestUrl = GURL("https://www.example.com/manifest.json");
+
+  AppId app_id = PopulateBasicInstallPageWithManifest(kInstallUrl, kManifestUrl,
+                                                      kStartUrl);
+
+  {
+    // Install user app
+    auto& install_page_state =
+        web_contents_manager().GetOrCreatePageState(kInstallUrl);
+    install_page_state.opt_manifest->short_name = u"Test user app";
+
+    auto install_info = std::make_unique<WebAppInstallInfo>();
+    install_info->start_url = kStartUrl;
+    install_info->title = u"Test user app";
+    absl::optional<AppId> user_app_id =
+        test::InstallWebApp(profile(), std::move(install_info));
+
+    ASSERT_TRUE(user_app_id.has_value());
+    ASSERT_EQ(user_app_id.value(), app_id);
+    ASSERT_TRUE(app_registrar().WasInstalledByUser(app_id));
+    ASSERT_FALSE(app_registrar().HasExternalApp(app_id));
+    ASSERT_EQ("Test user app", app_registrar().GetAppShortName(app_id));
+  }
+  {
+    // Install policy app
+    auto& install_page_state =
+        web_contents_manager().GetOrCreatePageState(kInstallUrl);
+    install_page_state.opt_manifest->short_name = u"Test policy app";
+
+    SynchronizeFuture result;
+    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+        CreateExternalInstallOptionsFromTemplate(
+            {kInstallUrl}, ExternalInstallSource::kExternalPolicy),
+        ExternalInstallSource::kExternalPolicy, result.GetCallback());
+    ASSERT_TRUE(result.Wait());
+    std::map<GURL, ExternallyManagedAppManager::InstallResult> install_results =
+        result.Get<InstallResults>();
+    EXPECT_THAT(
+        install_results,
+        ElementsAre(std::make_pair(
+            kInstallUrl,
+            ExternallyManagedAppManager::InstallResult(
+                webapps::InstallResultCode::kSuccessNewInstall, app_id))));
+    ASSERT_EQ("Test policy app", app_registrar().GetAppShortName(app_id));
+  }
+}
+
 TEST_F(ExternallyAppManagerTest, NoNetworkWithPlaceholder) {
   const GURL kInstallUrl = GURL("https://www.example.com/install_url.html");
   ExternalInstallOptions template_options(
diff --git a/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc b/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc
index 583e6b5..d20ff7b74 100644
--- a/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc
+++ b/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc
@@ -59,16 +59,15 @@
   webauthn_account_selection_callback_ = std::move(callback);
 
   std::vector<PasskeyCredential> display_credentials;
-  base::ranges::transform(
-      credentials, std::back_inserter(display_credentials),
-      [](const auto& credential) {
-        return PasskeyCredential(
-            PasskeyCredential::Username(credential.user.name),
-            PasskeyCredential::DeviceName(l10n_util::GetStringUTF16(
-                IDS_PASSWORD_MANAGER_USE_SCREEN_LOCK)),
-            PasskeyCredential::BackendId(
-                base::Base64Encode(credential.cred_id)));
-      });
+  base::ranges::transform(credentials, std::back_inserter(display_credentials),
+                          [](const auto& credential) {
+                            return PasskeyCredential(
+                                PasskeyCredential::Source::kAndroidPhone,
+                                credential.rp_id, credential.cred_id,
+                                credential.user.id,
+                                credential.user.name.value_or(""),
+                                credential.user.display_name.value_or(""));
+                          });
 
   if (is_conditional_request) {
     conditional_request_in_progress_ = true;
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
index 26f887e2..8725215 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -129,24 +129,27 @@
   }
 }
 
-// Returns the resource identifier for the label describing the platform
-// authenticator, e.g. "Use TouchID".
-int GetPlatformAuthenticatorLabel() {
-#if BUILDFLAG(IS_WIN)
-  return IDS_PASSWORD_MANAGER_USE_WINDOWS_HELLO;
-#elif BUILDFLAG(IS_MAC)
-  return IDS_PASSWORD_MANAGER_USE_TOUCH_ID;
-#else
-  return IDS_PASSWORD_MANAGER_USE_GENERIC_DEVICE;
-#endif
-}
-
 // Whether to show Step::kCreatePasskey, which prompts the user before platform
 // authenticator dispatch during MakeCredential. This is currently only shown on
 // MacOS, because that is the only desktop platform authenticator without a
 // "native" WebAuthn UI.
 constexpr bool kShowCreatePlatformPasskeyStep = BUILDFLAG(IS_MAC);
 
+password_manager::PasskeyCredential::Source ToPasswordManagerSource(
+    device::AuthenticatorType type) {
+  switch (type) {
+    case device::AuthenticatorType::kWinNative:
+      return password_manager::PasskeyCredential::Source::kWindowsHello;
+    case device::AuthenticatorType::kTouchID:
+      return password_manager::PasskeyCredential::Source::kTouchId;
+    case device::AuthenticatorType::kPhone:
+      return password_manager::PasskeyCredential::Source::kAndroidPhone;
+    case device::AuthenticatorType::kChromeOS:
+    case device::AuthenticatorType::kOther:
+      return password_manager::PasskeyCredential::Source::kOther;
+  }
+}
+
 }  // namespace
 
 AuthenticatorRequestDialogModel::EphemeralState::EphemeralState() = default;
@@ -1063,12 +1066,10 @@
         ephemeral_state_.creds_, std::back_inserter(credentials),
         [](const auto& credential) {
           return password_manager::PasskeyCredential(
-              password_manager::PasskeyCredential::Username(
-                  credential.user.name),
-              password_manager::PasskeyCredential::DeviceName(
-                  l10n_util::GetStringUTF16(GetPlatformAuthenticatorLabel())),
-              password_manager::PasskeyCredential::BackendId(
-                  base::Base64Encode(credential.cred_id)));
+              ToPasswordManagerSource(credential.source), credential.rp_id,
+              credential.cred_id, credential.user.id,
+              credential.user.name.value_or(""),
+              credential.user.display_name.value_or(""));
         });
     ReportConditionalUiPasskeyCount(credentials.size());
     ChromeWebAuthnCredentialsDelegateFactory::GetFactory(web_contents)
diff --git a/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc b/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc
index b01ca34..3eda6d6 100644
--- a/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc
+++ b/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc
@@ -21,7 +21,6 @@
 #include "components/autofill/core/browser/ui/popup_types.h"
 #include "components/network_session_configurator/common/network_switches.h"
 #include "components/password_manager/core/browser/password_store_interface.h"
-#include "components/password_manager/core/browser/password_ui_utils.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/scoped_authenticator_environment_for_testing.h"
@@ -72,17 +71,6 @@
            e => window.domAutomationController.send('error ' + e));
 })())";
 
-std::u16string GetPlatformAuthenticatorLabel() {
-#if BUILDFLAG(IS_WIN)
-  int message = IDS_PASSWORD_MANAGER_USE_WINDOWS_HELLO;
-#elif BUILDFLAG(IS_MAC)
-  int message = IDS_PASSWORD_MANAGER_USE_TOUCH_ID;
-#else
-  int message = IDS_PASSWORD_MANAGER_USE_GENERIC_DEVICE;
-#endif
-  return l10n_util::GetStringUTF16(message);
-}
-
 // Autofill integration tests. This file contains end-to-end tests for
 // integration between WebAuthn and Autofill. These tests are sensitive to focus
 // changes, so they are interactive UI tests.
@@ -182,8 +170,7 @@
     ASSERT_LT(suggestion_index, suggestions.size())
         << "WebAuthn entry not found";
     EXPECT_EQ(webauthn_entry.main_text.value, u"flandre");
-    EXPECT_EQ(webauthn_entry.labels.at(0).at(0).value,
-              GetPlatformAuthenticatorLabel());
+    EXPECT_EQ(webauthn_entry.labels.at(0).at(0).value, GetDeviceString());
     EXPECT_EQ(webauthn_entry.icon, "globeIcon");
 
     // Click the credential.
@@ -229,8 +216,7 @@
     ASSERT_LT(suggestion_index, suggestions.size())
         << "WebAuthn entry not found";
     EXPECT_EQ(webauthn_entry.main_text.value, u"flandre");
-    EXPECT_EQ(webauthn_entry.labels.at(0).at(0).value,
-              GetPlatformAuthenticatorLabel());
+    EXPECT_EQ(webauthn_entry.labels.at(0).at(0).value, GetDeviceString());
     EXPECT_EQ(webauthn_entry.icon, "globeIcon");
 
     // Abort the request.
@@ -259,6 +245,8 @@
     }
   }
 
+  virtual std::u16string GetDeviceString() = 0;
+
   raw_ptr<device::test::VirtualFidoDeviceFactory> virtual_device_factory_;
   net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
 };
@@ -297,6 +285,10 @@
     WebAuthnAutofillIntegrationTest::PostRunTestOnMainThread();
   }
 
+  std::u16string GetDeviceString() override {
+    return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_USE_GENERIC_DEVICE);
+  }
+
  protected:
   std::unique_ptr<content::ScopedAuthenticatorEnvironmentForTesting>
       scoped_auth_env_;
@@ -359,6 +351,10 @@
     WebAuthnAutofillIntegrationTest::PostRunTestOnMainThread();
   }
 
+  std::u16string GetDeviceString() override {
+    return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_USE_WINDOWS_HELLO);
+  }
+
  protected:
   std::unique_ptr<device::FakeWinWebAuthnApi> fake_webauthn_api_;
   std::unique_ptr<content::ScopedAuthenticatorEnvironmentForTesting>
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt
index 1a8dbcc..cd5ec8a 100644
--- a/chrome/build/lacros64.pgo.txt
+++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@
-chrome-chromeos-amd64-generic-main-1682409317-349591e69269970b24a90788d1f02e0e8920b3a8.profdata
+chrome-chromeos-amd64-generic-main-1682423824-c49e1957e6a983352337fb21511dbd52837c1955.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 896d02b..bd9d0b7c 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1682416516-815a9c0b2658305f12c27e2ffa62b46dc133e750.profdata
+chrome-mac-arm-main-1682438343-e2f194690958320c64c4bf9d3a248fa32acdec6c.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 004604f..6be916a1 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1682402204-2673343f4cc7608647263ca8dfb06e378cee2989.profdata
+chrome-mac-main-1682423824-ff652f21df2526e2030829a03c660de23adac191.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 42cf06e..d7921103 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1682423824-8f2552128c5ffd3facff5161976d1215e2ea943e.profdata
+chrome-win32-main-1682434466-e9b58a690b0b5633ba34f25dc910122acc3a7ff0.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index ca4251cf..4ee225e 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1682423824-1108e7f48e3b2053001360ca132dfb1f252bdaf5.profdata
+chrome-win64-main-1682434466-6941e8364eb0ecf785782e3a91b6f6d524c58e55.profdata
diff --git a/chrome/common/extensions/api/web_authentication_proxy.idl b/chrome/common/extensions/api/web_authentication_proxy.idl
index 9a1a1dd..83fbdde4 100644
--- a/chrome/common/extensions/api/web_authentication_proxy.idl
+++ b/chrome/common/extensions/api/web_authentication_proxy.idl
@@ -2,41 +2,43 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// The webAuthenticationProxy API lets remote desktop software running on a
-// remote host intercept Web Authentication API (WebAuthn) requests in order to
-// handle them on a local client.
+// The <code>chrome.webAuthenticationProxy</code>. API lets remote desktop
+// software running on a remote host intercept Web Authentication API
+// (WebAuthn) requests in order to handle them on a local client.
 namespace webAuthenticationProxy {
   // An object representing a
-  // PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() call.
+  // <code>PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()</code>
+  // call.
   dictionary IsUvpaaRequest {
     // An opaque identifier for the request.
     long requestId;
   };
 
-  // An object representing a WebAuthn navigator.credentials.create() call.
+  // An object representing a WebAuthn
+  // <code>navigator.credentials.create()</code> call.
   dictionary CreateRequest {
     // An opaque identifier for the request.
     long requestId;
 
-    // An JSON serialized representation of the
-    // PublicKeyCredentialCreationOptions passed to
-    // navigator.credentials.create().
-    //
-    // TODO(crbug.com/1231802): Reference deserialization method or document
-    // format.
+    // The <code>PublicKeyCredentialCreationOptions</code> passed to
+    // <code>navigator.credentials.create()</code>, serialized as a JSON
+    // string. The serialization format is compatible with <a
+    // href="https://w3c.github.io/webauthn/#sctn-parseCreationOptionsFromJSON">
+    // <code>PublicKeyCredential.parseCreationOptionsFromJSON()</code></a>.
     DOMString requestDetailsJson;
   };
 
-  // An object representing a WebAuthn navigator.credentials.get() call.
+  // An object representing a WebAuthn <code>navigator.credentials.get()</code>
+  // call.
   dictionary GetRequest {
     // An opaque identifier for the request.
     long requestId;
 
-    // An JSON serialized representation of the
-    // PublicKeyCredentialRequestOptions passed to navigator.credentials.get().
-    //
-    // TODO(crbug.com/1231802): Reference deserialization method or document
-    // format.
+    // The <code>PublicKeyCredentialRequestOptions</code> passed to
+    // <code>navigator.credentials.get()</code>, serialized as a JSON string.
+    // The serialization format is compatible with <a
+    // href="https://w3c.github.io/webauthn/#sctn-parseRequestOptionsFromJSON">
+    // <code>PublicKeyCredential.parseRequestOptionsFromJSON()</code></a>.
     DOMString requestDetailsJson;
   };
 
@@ -47,9 +49,10 @@
     // A native application associated with this extension can cause this
     // event to be fired by writing to a file with a name equal to the
     // extension's ID in a directory named
-    // `WebAuthenticationProxyRemoteSessionStateChange` inside the [default
-    // user data
-    // directory](https://chromium.googlesource.com/chromium/src/+/main/docs/user_data_dir.md#default-location).
+    // <code>WebAuthenticationProxyRemoteSessionStateChange</code> inside the
+    // <a
+    // href="https://chromium.googlesource.com/chromium/src/+/main/docs/user_data_dir.md#default-location">default
+    // user data directory</a>
     //
     // The contents of the file should be empty. I.e., it is not necessary to
     // change the contents of the file in order to trigger this event.
@@ -57,33 +60,37 @@
     // The native host application may use this event mechanism to signal a
     // possible remote session state change (i.e. from detached to attached, or
     // vice versa) while the extension service worker is possibly suspended. In
-    // the handler for this event, the extension can call the `attach()` or
-    // `detach()` API methods accordingly.
+    // the handler for this event, the extension can call the
+    // <code>attach()</code> or <code>detach()</code> API methods accordingly.
     //
     // The event listener must be registered synchronously at load time.
     static void onRemoteSessionStateChange();
 
-    // Fires when a WebAuthn navigator.credentials.create() call occurs. The
-    // extension must supply a response by calling
-    // completeCreateRequest() with the given requestId.
+    // Fires when a WebAuthn <code>navigator.credentials.create()</code> call
+    // occurs. The extension must supply a response by calling
+    // <code>completeCreateRequest()</code> with the <code>requestId</code> from
+    // <code>requestInfo</code>.
     static void onCreateRequest(CreateRequest requestInfo);
 
     // Fires when a WebAuthn navigator.credentials.get() call occurs. The
     // extension must supply a response by calling
-    // completeGetRequest() with the given requestId.
+    // <code>completeGetRequest()</code> with the <code>requestId</code> from
+    // <code>requestInfo</code>
     static void onGetRequest(GetRequest requestInfo);
 
     // Fires when a
-    // PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() call
-    // occurs. The extension must supply a response by calling
-    // completeIsUvpaaRequest() with the given requestId.
+    // <code>PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()</code>
+    // call occurs. The extension must supply a response by calling
+    // <code>completeIsUvpaaRequest()</code> with the <code>requestId</code>
+    // from <code>requestInfo</code>
     static void onIsUvpaaRequest(IsUvpaaRequest requestInfo);
 
-    // Fires when a `onCreateRequest` or `onGetRequest` event is canceled
-    // (because the WebAuthn request was aborted by the caller, or because it
-    // timed out). When receiving this event, the extension should cancel
-    // processing of the corresponding request on the client side. Extensions
-    // cannot complete a request once it has been canceled.
+    // Fires when a <code>onCreateRequest</code> or <code>onGetRequest</code>
+    // event is canceled (because the WebAuthn request was aborted by the
+    // caller, or because it timed out). When receiving this event, the
+    // extension should cancel processing of the corresponding request on the
+    // client side. Extensions cannot complete a request once it has been
+    // canceled.
     static void onRequestCanceled(long requestId);
   };
 
@@ -96,34 +103,30 @@
   };
 
   dictionary CreateResponseDetails {
-    // The requestId of the `CreateRequest`.
+    // The <code>requestId</code> of the <code>CreateRequest</code>.
     long requestId;
 
-    // The `DOMException`, if any, yielded by the remote request.
+    // The <code>DOMException</code> yielded by the remote request, if any.
     DOMExceptionDetails? error;
 
-    // A JSON serialized representation of the `PublicKeyCredential`
-    // (https://w3c.github.io/webauthn/#publickeycredential), if any, yielded
-    // by the remote request.
-    //
-    // TODO(crbug.com/1231802): Reference serialization method or document
-    // format.
+    // The <code>PublicKeyCredential</code>, yielded by the remote request, if
+    // any, serialized as a JSON string by calling
+    // href="https://w3c.github.io/webauthn/#dom-publickeycredential-tojson">
+    // <code>PublicKeyCredential.toJSON()</code></a>.
     DOMString? responseJson;
   };
 
   dictionary GetResponseDetails {
-    // The requestId of the `CreateRequest`.
+    // The <code>requestId</code> of the <code>CreateRequest</code>.
     long requestId;
 
-    // The `DOMException`, if any, yielded by the remote request.
+    // The <code>DOMException</code> yielded by the remote request, if any.
     DOMExceptionDetails? error;
 
-    // A JSON serialized representation of the `PublicKeyCredential`
-    // (https://w3c.github.io/webauthn/#publickeycredential), if any, yielded
-    // by the remote request.
-    //
-    // TODO(crbug.com/1231802): Reference serialization method or document
-    // format.
+    // The <code>PublicKeyCredential</code>, yielded by the remote request, if
+    // any, serialized as a JSON string by calling
+    // href="https://w3c.github.io/webauthn/#dom-publickeycredential-tojson">
+    // <code>PublicKeyCredential.toJSON()</code></a>.
     DOMString? responseJson;
   };
 
@@ -133,26 +136,27 @@
   };
 
   interface Functions {
-    // Reports the result of a navigator.credentials.create() call. The
-    // extension must call this for every onCreateRequest event it has
-    // received, unless the request was canceled (in which case, an
-    // onRequestCanceled event is fired).
+    // Reports the result of a <code>navigator.credentials.create()</code>
+    // call. The extension must call this for every
+    // <code>onCreateRequest</code> event it has received, unless the request
+    // was canceled (in which case, an <code>onRequestCanceled</code> event is
+    // fired).
     [supportsPromises] static void completeCreateRequest(
         CreateResponseDetails details,
         VoidCallback callback);
 
-    // Reports the result of a navigator.credentials.get() call. The extension
-    // must call this for every onGetRequest event it has received, unless the
-    // request was canceled (in which case, an onRequestCanceled event is
-    // fired).
+    // Reports the result of a <code>navigator.credentials.get()</code> call.
+    // The extension must call this for every <code>onGetRequest</code> event
+    // it has received, unless the request was canceled (in which case, an
+    // <code>onRequestCanceled</code> event is fired).
     [supportsPromises] static void completeGetRequest(
         GetResponseDetails details,
         VoidCallback callback);
 
     // Reports the result of a
-    // PublicKeyCredential.isUserVerifyingPlatformAuthenticator() call. The
-    // extension must call this for every onIsUvpaaRequest event it has
-    // received.
+    // <code>PublicKeyCredential.isUserVerifyingPlatformAuthenticator()</code>
+    // call. The extension must call this for every
+    // <code>onIsUvpaaRequest</code> event it has received.
     [supportsPromises] static void completeIsUvpaaRequest(
         IsUvpaaResponseDetails details,
         VoidCallback callback);
@@ -167,14 +171,14 @@
     // This method fails with an error if a different extension is already
     // attached.
     //
-    // The attached extension must call `detach()` once the remote desktop
-    // session has ended in order to resume regular WebAuthn request
+    // The attached extension must call <code>detach()</code> once the remote
+    // desktop session has ended in order to resume regular WebAuthn request
     // processing. Extensions automatically become detached if they are
     // unloaded.
     //
-    // Refer to the `onRemoteSessionStateChange` event for signaling a change
-    // of remote session attachment from a native application to to the
-    // (possibly suspended) extension.
+    // Refer to the <code>onRemoteSessionStateChange</code> event for signaling
+    // a change of remote session attachment from a native application to to
+    // the (possibly suspended) extension.
     [supportsPromises] static void attach(ErrorCallback callback);
 
     // Removes this extension from being the active Web Authentication API
@@ -184,9 +188,9 @@
     // desktop session was terminated. Once this method returns, the extension
     // ceases to be the active Web Authentication API request proxy.
     //
-    // Refer to the `onRemoteSessionStateChange` event for signaling a change
-    // of remote session attachment from a native application to to the
-    // (possibly suspended) extension.
+    // Refer to the <code>onRemoteSessionStateChange</code> event for signaling
+    // a change of remote session attachment from a native application to to
+    // the (possibly suspended) extension.
     [supportsPromises] static void detach(ErrorCallback callback);
   };
 };
diff --git a/chrome/common/renderer_configuration.mojom b/chrome/common/renderer_configuration.mojom
index 6bd4a7c..950f9599d 100644
--- a/chrome/common/renderer_configuration.mojom
+++ b/chrome/common/renderer_configuration.mojom
@@ -31,6 +31,18 @@
   string allowed_domains_for_apps;
 };
 
+// Allows the renderer to notify the browser process that requests in renderer
+// are throttled and require a fresh short lived cookie.
+interface BoundSessionRequestThrottledListener {
+  // Called to notify the browser process when a network request requires a
+  // fresh cookie. This triggers a cookie refresh request and will
+  // run the callback to release the request upon success, failure or timeout.
+  // Note: The callback might be called synchronously in process if the
+  // previous conditions apply.
+  [EnableIf=enable_bound_session_credentials]
+  OnRequestBlockedOnCookie() => ();
+};
+
 interface ChromeOSListener {
   // Call when the merge session process (cookie reconstruction from
   // OAuth2 refresh token in ChromeOS login) is complete. All XHR's
@@ -46,11 +58,16 @@
   // the merge session is still running - otherwise not set.
   // |content_settings_manager| may be sent as an optimization to avoid
   // requesting it from the browser process, and may be null.
+  // |bound_session_request_throttled_listener| is passed only if the buildflag
+  // `enable_bound_session_credentials` is enabled. It can be null if bound
+  // sessions are not supported yet for the current profile type.
   SetInitialConfiguration(
       bool is_incognito_process,
       pending_receiver<ChromeOSListener>? chromeos_listener,
       pending_remote<content_settings.mojom.ContentSettingsManager>?
-          content_settings_manager);
+          content_settings_manager,
+      pending_remote<BoundSessionRequestThrottledListener>?
+          bound_session_request_throttled_listener);
 
   // Update renderer configuration with settings that can change.
   SetConfiguration(DynamicParams params);
diff --git a/chrome/credential_provider/extension/task_manager_unittests.cc b/chrome/credential_provider/extension/task_manager_unittests.cc
index f1d270a6..3eecbfe 100644
--- a/chrome/credential_provider/extension/task_manager_unittests.cc
+++ b/chrome/credential_provider/extension/task_manager_unittests.cc
@@ -8,11 +8,11 @@
 #include <windows.h>
 
 #include "base/functional/bind.h"
-#include "base/guid.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
+#include "base/uuid.h"
 #include "chrome/credential_provider/extension/extension_utils.h"
 #include "chrome/credential_provider/extension/task.h"
 #include "chrome/credential_provider/extension/task_manager.h"
@@ -184,7 +184,8 @@
 
   FakeTokenGenerator fake_token_generator;
   fake_token_generator.SetTokensForTesting(
-      {base::GenerateGUID(), base::GenerateGUID()});
+      {base::Uuid::GenerateRandomV4().AsLowercaseString(),
+       base::Uuid::GenerateRandomV4().AsLowercaseString()});
 
   ASSERT_EQ(S_OK, GenerateGCPWDmToken((BSTR)sid1));
 
@@ -284,7 +285,8 @@
 
   FakeTokenGenerator fake_token_generator;
   fake_token_generator.SetTokensForTesting(
-      {base::GenerateGUID(), base::GenerateGUID()});
+      {base::Uuid::GenerateRandomV4().AsLowercaseString(),
+       base::Uuid::GenerateRandomV4().AsLowercaseString()});
 
   ASSERT_EQ(S_OK, GenerateGCPWDmToken((BSTR)sid1));
 
diff --git a/chrome/credential_provider/gaiacp/associated_user_validator_unittests.cc b/chrome/credential_provider/gaiacp/associated_user_validator_unittests.cc
index cb4b6d7..c627755 100644
--- a/chrome/credential_provider/gaiacp/associated_user_validator_unittests.cc
+++ b/chrome/credential_provider/gaiacp/associated_user_validator_unittests.cc
@@ -5,13 +5,13 @@
 #include <memory>
 #include <string>
 
-#include "base/guid.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/test_reg_util_win.h"
 #include "base/time/time.h"
 #include "base/time/time_override.h"
+#include "base/uuid.h"
 #include "chrome/credential_provider/common/gcp_strings.h"
 #include "chrome/credential_provider/gaiacp/associated_user_validator.h"
 #include "chrome/credential_provider/gaiacp/gaia_credential_provider.h"
@@ -107,7 +107,7 @@
 
   // Ensure user has policies and valid GCPW token.
   fake_user_policies_manager_->SetUserPolicyStaleOrMissing(sid, false);
-  std::string dm_token = base::GenerateGUID();
+  std::string dm_token = base::Uuid::GenerateRandomV4().AsLowercaseString();
   fake_token_generator_->SetTokensForTesting({dm_token});
   EXPECT_EQ(S_OK, GenerateGCPWDmToken(sid));
 }
@@ -615,7 +615,7 @@
 
   if (cloud_policies_enabled) {
     fake_user_policies_manager.SetUserPolicies((BSTR)sid, user_policies);
-    std::string dm_token = base::GenerateGUID();
+    std::string dm_token = base::Uuid::GenerateRandomV4().AsLowercaseString();
     fake_token_generator.SetTokensForTesting({dm_token});
     ASSERT_EQ(S_OK, GenerateGCPWDmToken((BSTR)sid));
   }
@@ -751,7 +751,7 @@
   EXPECT_TRUE(policy->PrivateDataExists(store_key.c_str()));
 
   if (upload_device_details_state == 2) {
-    std::string dm_token = base::GenerateGUID();
+    std::string dm_token = base::Uuid::GenerateRandomV4().AsLowercaseString();
     fake_token_generator.SetTokensForTesting({dm_token});
     ASSERT_EQ(S_OK, GenerateGCPWDmToken((BSTR)sid));
   }
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
index 01399e26..848d79a1 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
@@ -13,7 +13,6 @@
 #include "base/base64.h"
 #include "base/base_paths_win.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/guid.h"
 #include "base/json/json_writer.h"
 #include "base/memory/raw_ptr.h"
 #include "base/ranges/algorithm.h"
@@ -26,6 +25,7 @@
 #include "base/test/scoped_path_override.h"
 #include "base/time/time.h"
 #include "base/time/time_override.h"
+#include "base/uuid.h"
 #include "chrome/browser/ui/startup/credential_provider_signin_dialog_win_test_data.h"
 #include "chrome/credential_provider/common/gcp_strings.h"
 #include "chrome/credential_provider/gaiacp/gaia_credential_base.h"
@@ -3389,7 +3389,7 @@
                       base::UTF8ToWide(kDefaultGaiaId), std::wstring(), domain,
                       &sid));
 
-  std::string dm_token = base::GenerateGUID();
+  std::string dm_token = base::Uuid::GenerateRandomV4().AsLowercaseString();
   FakeTokenGenerator fake_token_generator;
   fake_token_generator.SetTokensForTesting({dm_token});
 
diff --git a/chrome/renderer/chrome_render_thread_observer.cc b/chrome/renderer/chrome_render_thread_observer.cc
index c5d959c..a49c7ae 100644
--- a/chrome/renderer/chrome_render_thread_observer.cc
+++ b/chrome/renderer/chrome_render_thread_observer.cc
@@ -167,7 +167,9 @@
     mojo::PendingReceiver<chrome::mojom::ChromeOSListener>
         chromeos_listener_receiver,
     mojo::PendingRemote<content_settings::mojom::ContentSettingsManager>
-        content_settings_manager) {
+        content_settings_manager,
+    mojo::PendingRemote<chrome::mojom::BoundSessionRequestThrottledListener>
+        bound_session_request_throttled_listener) {
   if (content_settings_manager)
     content_settings_manager_.Bind(std::move(content_settings_manager));
   is_incognito_process_ = is_incognito_process;
diff --git a/chrome/renderer/chrome_render_thread_observer.h b/chrome/renderer/chrome_render_thread_observer.h
index 6419f916..800b0de 100644
--- a/chrome/renderer/chrome_render_thread_observer.h
+++ b/chrome/renderer/chrome_render_thread_observer.h
@@ -118,7 +118,9 @@
       mojo::PendingReceiver<chrome::mojom::ChromeOSListener>
           chromeos_listener_receiver,
       mojo::PendingRemote<content_settings::mojom::ContentSettingsManager>
-          content_settings_manager) override;
+          content_settings_manager,
+      mojo::PendingRemote<chrome::mojom::BoundSessionRequestThrottledListener>
+          bound_session_request_throttled_listener) override;
   void SetConfiguration(chrome::mojom::DynamicParamsPtr params) override;
   void OnRendererConfigurationAssociatedRequest(
       mojo::PendingAssociatedReceiver<chrome::mojom::RendererConfiguration>
diff --git a/chrome/renderer/extensions/api/notifications_native_handler.cc b/chrome/renderer/extensions/api/notifications_native_handler.cc
index ad311900..1ad27615 100644
--- a/chrome/renderer/extensions/api/notifications_native_handler.cc
+++ b/chrome/renderer/extensions/api/notifications_native_handler.cc
@@ -31,8 +31,8 @@
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   NotificationBitmapSizes bitmap_sizes = GetNotificationBitmapSizes();
 
-  float scale_factor = ui::GetScaleForResourceScaleFactor(
-      ui::GetSupportedResourceScaleFactors().back());
+  const float scale_factor = ui::GetScaleForResourceScaleFactor(
+      ui::GetMaxSupportedResourceScaleFactor());
 
   v8::Isolate* isolate = GetIsolate();
   v8::HandleScope handle_scope(isolate);
diff --git a/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc b/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc
index b132a49..97136a04 100644
--- a/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc
+++ b/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc
@@ -277,11 +277,9 @@
     return;
   }
 
-  // Possible QR version lengths, which we round up to with space-padding vs.
-  // null-padding.
-  // TODO(skare): ideally this shouldn't have any insight into supported
-  // versions.
-  constexpr size_t version_sizes[] = {84, 122, 180, 288};
+  // TODO(lukasza): Consider increasing `kLengthMax` - according to
+  // https://www.qrcode.com/en/about/version.html 177x177 QR code can encode up
+  // to 7089 digits.
   constexpr size_t kLengthMax = 288;
   if (request->data.length() > kLengthMax) {
     response->error_code = mojom::QRCodeGeneratorError::INPUT_TOO_LONG;
@@ -289,21 +287,6 @@
     return;
   }
 
-  uint8_t input[kLengthMax + 1] = {0};
-  base::strlcpy(reinterpret_cast<char*>(input), request->data.c_str(),
-                kLengthMax);
-  size_t data_size = 0;
-  for (const size_t& version_size : version_sizes) {
-    if (request->data.length() <= version_size) {
-      data_size = version_size;
-      break;
-    }
-  }
-
-  for (size_t i = request->data.length(); i < data_size; i++)
-    input[i] = 0x20;
-  input[data_size - 1] = 0;
-
   QRCodeGenerator qr;
   // The QR version (i.e. size) must be >= 5 because otherwise the dino painted
   // over the middle covers too much of the code to be decodable.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 3b811b5..b3d778de 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -5488,6 +5488,7 @@
     "../browser/browsing_data/counters/site_data_counting_helper_unittest.cc",
     "../browser/browsing_data/counters/site_settings_counter_unittest.cc",
     "../browser/browsing_data/site_data_size_collector_unittest.cc",
+    "../browser/chained_back_navigation_tracker_unittest.cc",
     "../browser/chooser_controller/title_util_unittest.cc",
     "../browser/chrome_browser_field_trials_unittest.cc",
     "../browser/chrome_content_browser_client_unittest.cc",
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index 8ffb5f9..f7c3338 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -632,11 +632,6 @@
           "$root_gen_dir/chromecast/internal/castui/app_strings_${locale}.pak",
         ]
         deps += [ "//chromecast/internal/castui:cast_ui_app_strings" ]
-
-        if (enable_chromecast_webui) {
-          sources += [ "$root_gen_dir/chromecast/internal/castui/ui_localized_${locale}.pak" ]
-          deps += [ "//chromecast/internal/castui:cast_ui_localized" ]
-        }
       }
     }
   }
@@ -657,7 +652,6 @@
     "DEFAULT_COMMAND_LINE_FLAGS=\"$_command_line_flags\"",
     "DISABLE_SECURE_FLAC_OPUS_DECODING=$disable_secure_flac_and_opus_decoding",
     "ENABLE_ASSISTANT=$enable_assistant",
-    "ENABLE_CHROMECAST_WEBUI=$enable_chromecast_webui",
     "ENABLE_EXTERNAL_MOJO_SERVICES=$enable_external_mojo_services",
     "ENABLE_PLAYREADY=$enable_playready",
     "ENABLE_VIDEO_CAPTURE_SERVICE=$enable_video_capture_service",
diff --git a/chromecast/OWNERS b/chromecast/OWNERS
index d7680b2..4be4c66 100644
--- a/chromecast/OWNERS
+++ b/chromecast/OWNERS
@@ -1,7 +1,6 @@
 set noparent
 halliwell@chromium.org
 seantopping@chromium.org
-servolk@chromium.org
 yucliu@chromium.org
 vigeni@google.com
 
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsScopes.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsScopes.java
index 5ed7a5aac..1fb646c 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsScopes.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsScopes.java
@@ -73,7 +73,12 @@
             contentViewRenderView.setSurfaceViewBackgroundColor(backgroundColor);
             FrameLayout.LayoutParams matchParent = new FrameLayout.LayoutParams(
                     FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
-            layout.addView(contentViewRenderView, matchParent);
+
+            // Use a slightly smaller layout as a mitigation for b/245596038 until the
+            // Android-level fix is available.
+            FrameLayout.LayoutParams talkbackFixLayout = new FrameLayout.LayoutParams(matchParent);
+            talkbackFixLayout.setMargins(0, 0, 1, 1);
+            layout.addView(contentViewRenderView, talkbackFixLayout);
 
             ContentView contentView = ContentView.createContentView(
                     context, null /* eventOffsetHandler */, webContents);
diff --git a/chromecast/chromecast.gni b/chromecast/chromecast.gni
index 48327b1..0dbf6c8 100644
--- a/chromecast/chromecast.gni
+++ b/chromecast/chromecast.gni
@@ -41,11 +41,6 @@
     display_web_contents_in_service = is_cast_audio_only
   }
 
-  # If true, Chromecast WebUI resources are included in a build.
-  # TODO(antz): default to false for audio-only builds, might need further
-  # clean up (b/27119303)
-  enable_chromecast_webui = !is_cast_audio_only && !is_android
-
   # Set true to enable assistant features.
   enable_assistant = false
 
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni
index dbf626e..c2d642b 100644
--- a/chromeos/tast_control.gni
+++ b/chromeos/tast_control.gni
@@ -323,6 +323,9 @@
   "inputs.VirtualKeyboardHandwriting.floating",
   "inputs.VirtualKeyboardTypingUserMode.incognito",
 
+  # b/279351324: Until crrev.com/c/4475024 upreved.
+  "a11y.LiveCaption.lacros",
+
   # READ COMMENT AT TOP BEFORE ADDING NEW TESTS HERE.
 ]
 
diff --git a/components/autofill/core/browser/form_structure_sectioning_util.cc b/components/autofill/core/browser/form_structure_sectioning_util.cc
index eff666d..c8a4d7d 100644
--- a/components/autofill/core/browser/form_structure_sectioning_util.cc
+++ b/components/autofill/core/browser/form_structure_sectioning_util.cc
@@ -105,7 +105,8 @@
   }
 }
 
-void ExpandSections(base::span<const std::unique_ptr<AutofillField>> fields) {
+void ExpandSections(base::span<const std::unique_ptr<AutofillField>> fields,
+                    bool overwrite_non_sectionable_fields) {
   auto HasSection = [](auto& field) {
     return IsSectionable(*field) && field->section;
   };
@@ -114,8 +115,9 @@
     auto end = base::ranges::find_if(it + 1, fields.end(), HasSection);
     if (end != fields.end() && (*it)->section == (*end)->section) {
       for (auto& field : base::make_span(it + 1, end)) {
-        if (IsSectionable(*field))
+        if (overwrite_non_sectionable_fields || IsSectionable(*field)) {
           field->section = (*it)->section;
+        }
       }
     }
     it = end;
@@ -203,8 +205,9 @@
   if (!features::kAutofillSectioningModeIgnoreAutocomplete.Get())
     AssignAutocompleteSections(fields);
   AssignCreditCardSections(fields, frame_token_ids);
-  if (features::kAutofillSectioningModeExpand.Get())
-    ExpandSections(fields);
+  if (features::kAutofillSectioningModeExpand.Get()) {
+    ExpandSections(fields, /*overwrite_non_sectionable_fields=*/false);
+  }
 
   auto begin = fields.begin();
   while (begin != fields.end()) {
@@ -214,6 +217,10 @@
     AssignFieldIdentifierSections({begin, end}, frame_token_ids);
     begin = end;
   }
+
+  if (features::kAutofillSectioningModeExpandOverUnfocusableFields.Get()) {
+    ExpandSections(fields, /*overwrite_non_sectionable_fields=*/true);
+  }
 }
 
 void LogSectioningMetrics(
diff --git a/components/autofill/core/browser/form_structure_sectioning_util.h b/components/autofill/core/browser/form_structure_sectioning_util.h
index 90df095..b1f452c7 100644
--- a/components/autofill/core/browser/form_structure_sectioning_util.h
+++ b/components/autofill/core/browser/form_structure_sectioning_util.h
@@ -113,6 +113,28 @@
 //   Country:   <input id=8>                               | field 5 based
 //   CC number: <input id=9>                               | field 5 based
 //   ------------------------------------------------------+-------------------
+//
+// d. `kAutofillSectioningModeExpandOverUnfocusableFields`: Without this
+//    parameter, unfocusable non-credit card fields are not sectioned. All such
+//    fields remain in the default section.
+//    When enabled, this parameter works like `kAutofillSectioningModeExpand`,
+//    except that it overwrites unfocsuable fields. In particular, it places
+//    non-focusable fields in the same section as the surrounding focusable
+//    fields.
+//    Contrary to `kAutofillSectioningModeExpand`, expanding the sections over
+//    unfocsuable fields happens after step 3, not after step 2.
+//    It doesn't make a difference on the "standard example" used above. In the
+//    following simpler example it assigns the "Country" field to the field 1
+//    based section.
+//
+//    Example:
+//   ------------------------------------------------------+-------------------
+//       HTML code                                         |      Section
+//   ------------------------------------------------------+-------------------
+//   Name:      <input id=1>                               | field 1 based
+//   Country:   <input id=2 style="display:none">          | field 1 based
+//   Street:    <input id=3>                               | field 1 based
+//   ------------------------------------------------------+-------------------
 void AssignSections(base::span<const std::unique_ptr<AutofillField>> fields);
 
 // Logs UMA and UKM metrics about the `fields`' sections.
diff --git a/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc b/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc
index 315f8dd..5237ece 100644
--- a/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc
+++ b/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc
@@ -306,5 +306,29 @@
               BucketsAre(Bucket(4, 2)));
 }
 
+TEST_F(FormStructureSectioningTest, ExpandOverUnfocusableFields) {
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kAutofillUseParameterizedSectioning,
+      {{features::kAutofillSectioningModeExpandOverUnfocusableFields.name,
+        "true"}});
+
+  std::vector<std::unique_ptr<AutofillField>> fields =
+      CreateFields({{.field_type = NAME_FULL},
+                    {.field_type = ADDRESS_HOME_COUNTRY, .is_focusable = false},
+                    {.field_type = ADDRESS_HOME_STREET_NAME}});
+  base::HistogramTester histogram_tester;
+  AssignSectionsAndLogMetrics(fields);
+
+  base::flat_map<LocalFrameToken, size_t> frame_token_ids;
+  const Section expected_section =
+      Section::FromFieldIdentifier(*fields[0], frame_token_ids);
+  EXPECT_EQ(GetSections(fields), std::vector<Section>(3, expected_section));
+  EXPECT_EQ(ComputeSectioningSignature(fields), StrToHash32Bit("000"));
+  histogram_tester.ExpectUniqueSample(kNumberOfSectionsHistogram, 1, 1);
+  EXPECT_THAT(histogram_tester.GetAllSamples(kFieldsPerSectionHistogram),
+              BucketsAre(Bucket(3, 1)));
+}
+
 }  // namespace
 }  // namespace autofill
diff --git a/components/autofill/core/browser/manual_testing_import.cc b/components/autofill/core/browser/manual_testing_import.cc
index 4d2f2065..8a88312 100644
--- a/components/autofill/core/browser/manual_testing_import.cc
+++ b/components/autofill/core/browser/manual_testing_import.cc
@@ -209,7 +209,7 @@
                                               const FieldTypeLookupTable&)>
         to_data_model) {
   if (!json_array) {
-    return {};
+    return std::vector<T>{};
   }
   const auto lookup_table = MakeFieldTypeLookupTable();
   std::vector<T> data_models;
@@ -225,7 +225,8 @@
     }
     data_models.push_back(std::move(*data_model));
   }
-  return data_models;
+  // Move due to implicit type conversion.
+  return std::move(data_models);
 }
 
 // Parses AutofillProfiles from the JSON `content` string.
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index 12e0787..2eebd38e 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -540,6 +540,10 @@
     &kAutofillUseParameterizedSectioning, "create_gaps", false};
 const base::FeatureParam<bool> kAutofillSectioningModeExpand{
     &kAutofillUseParameterizedSectioning, "expand_assigned_sections", false};
+const base::FeatureParam<bool>
+    kAutofillSectioningModeExpandOverUnfocusableFields{
+        &kAutofillUseParameterizedSectioning, "expand_over_unfocsuable_fields",
+        false};
 
 // Controls whether to use form renderer IDs to find the form which contains the
 // field that was last interacted with in
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index fbe3e08..d9e734e 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -191,6 +191,9 @@
 COMPONENT_EXPORT(AUTOFILL)
 extern const base::FeatureParam<bool> kAutofillSectioningModeExpand;
 COMPONENT_EXPORT(AUTOFILL)
+extern const base::FeatureParam<bool>
+    kAutofillSectioningModeExpandOverUnfocusableFields;
+COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillRefillByFormRendererId);
 COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableAblationStudy);
 COMPONENT_EXPORT(AUTOFILL)
diff --git a/components/blocked_content/popup_opener_tab_helper.cc b/components/blocked_content/popup_opener_tab_helper.cc
index 96d3e3d..0a8d202 100644
--- a/components/blocked_content/popup_opener_tab_helper.cc
+++ b/components/blocked_content/popup_opener_tab_helper.cc
@@ -8,7 +8,6 @@
 
 #include "base/check.h"
 #include "base/memory/ptr_util.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/time/tick_clock.h"
 #include "components/blocked_content/popup_tracker.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
@@ -22,38 +21,11 @@
 
 namespace blocked_content {
 
-PopupOpenerTabHelper::~PopupOpenerTabHelper() {
-  DCHECK(visibility_tracker_);
-  base::TimeDelta total_visible_time =
-      visibility_tracker_->GetForegroundDuration();
-  if (did_tab_under()) {
-    UMA_HISTOGRAM_LONG_TIMES(
-        "Tab.TabUnder.VisibleTime",
-        total_visible_time - visible_time_before_tab_under_.value());
-    UMA_HISTOGRAM_LONG_TIMES("Tab.TabUnder.VisibleTimeBefore",
-                             visible_time_before_tab_under_.value());
-  }
-  UMA_HISTOGRAM_LONG_TIMES("Tab.VisibleTime", total_visible_time);
-}
+PopupOpenerTabHelper::~PopupOpenerTabHelper() = default;
 
 void PopupOpenerTabHelper::OnOpenedPopup(PopupTracker* popup_tracker) {
   has_opened_popup_since_last_user_gesture_ = true;
   MaybeLogPagePopupContentSettings();
-
-  last_popup_open_time_ = tick_clock_->NowTicks();
-}
-
-void PopupOpenerTabHelper::OnDidTabUnder() {
-  // The tab already did a tab-under.
-  if (did_tab_under())
-    return;
-
-  // Tab-under requires a popup, so this better not be null.
-  DCHECK(!last_popup_open_time_.is_null());
-  UMA_HISTOGRAM_LONG_TIMES("Tab.TabUnder.PopupToTabUnderTime",
-                           tick_clock_->NowTicks() - last_popup_open_time_);
-
-  visible_time_before_tab_under_ = visibility_tracker_->GetForegroundDuration();
 }
 
 PopupOpenerTabHelper::PopupOpenerTabHelper(content::WebContents* web_contents,
diff --git a/components/blocked_content/popup_opener_tab_helper.h b/components/blocked_content/popup_opener_tab_helper.h
index ac69745..b64eedc 100644
--- a/components/blocked_content/popup_opener_tab_helper.h
+++ b/components/blocked_content/popup_opener_tab_helper.h
@@ -9,7 +9,6 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/time/tick_clock.h"
-#include "base/time/time.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
@@ -42,16 +41,11 @@
   ~PopupOpenerTabHelper() override;
 
   void OnOpenedPopup(PopupTracker* popup_tracker);
-  void OnDidTabUnder();
 
   bool has_opened_popup_since_last_user_gesture() const {
     return has_opened_popup_since_last_user_gesture_;
   }
 
-  bool did_tab_under() const {
-    return visible_time_before_tab_under_.has_value();
-  }
-
  private:
   friend class content::WebContentsUserData<PopupOpenerTabHelper>;
 
@@ -73,20 +67,12 @@
   // web contents at the time the function is called.
   void MaybeLogPagePopupContentSettings();
 
-  // Visible time for this tab until a tab-under is detected. At which point it
-  // gets the visible time from the |visibility_tracker_|. Will be unset until a
-  // tab-under is detected.
-  absl::optional<base::TimeDelta> visible_time_before_tab_under_;
-
   // The clock which is used by the visibility trackers.
   raw_ptr<const base::TickClock> tick_clock_;
 
   // Keeps track of the total foreground time for this tab.
   std::unique_ptr<ui::ScopedVisibilityTracker> visibility_tracker_;
 
-  // Measures the time this WebContents opened a popup.
-  base::TimeTicks last_popup_open_time_;
-
   bool has_opened_popup_since_last_user_gesture_ = false;
 
   // The last source id used for logging Popup_Page.
diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/browser_ui/site_settings/android/BUILD.gn
index 4fc26e8b..1809637 100644
--- a/components/browser_ui/site_settings/android/BUILD.gn
+++ b/components/browser_ui/site_settings/android/BUILD.gn
@@ -220,11 +220,12 @@
     "java/res/drawable-xxxhdpi/web_asset.png",
     "java/res/drawable/gm_database_24.xml",
     "java/res/drawable/ic_account_attention.xml",
+    "java/res/drawable/ic_archive.xml",
     "java/res/drawable/ic_background_replace.xml",
     "java/res/drawable/ic_block.xml",
-    "java/res/drawable/ic_check_circle_outline.xml",
     "java/res/drawable/ic_dashboard.xml",
     "java/res/drawable/ic_person_24dp.xml",
+    "java/res/drawable/ic_timer.xml",
     "java/res/drawable/settings_bluetooth.xml",
     "java/res/layout/add_site_dialog.xml",
     "java/res/layout/clear_data_dialog.xml",
diff --git a/components/browser_ui/site_settings/android/java/res/drawable/ic_archive.xml b/components/browser_ui/site_settings/android/java/res/drawable/ic_archive.xml
new file mode 100644
index 0000000..d5aa981
--- /dev/null
+++ b/components/browser_ui/site_settings/android/java/res/drawable/ic_archive.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2023 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="@macro/default_icon_color"
+      android:pathData="M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM6.24 5h11.52l.81.97H5.44l.8-.97zM5 19V8h14v11H5zm8.45-9h-2.9v3H8l4 4 4-4h-2.55z" />
+</vector>
\ No newline at end of file
diff --git a/components/browser_ui/site_settings/android/java/res/drawable/ic_check_circle_outline.xml b/components/browser_ui/site_settings/android/java/res/drawable/ic_check_circle_outline.xml
deleted file mode 100644
index 48018d018..0000000
--- a/components/browser_ui/site_settings/android/java/res/drawable/ic_check_circle_outline.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright 2023 The Chromium Authors
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-  <path
-      android:fillColor="@macro/default_icon_color"
-      android:pathData="M 10.726562 15.601562 L 16.675781 9.675781 L 15.398438 8.398438 L 10.726562 13.050781 L 8.601562 10.949219 L 7.324219 12.226562 Z M 12 21.601562 C 10.683594 21.601562 9.441406 21.351562 8.273438 20.851562 C 7.109375 20.351562 6.082031 19.667969 5.199219 18.800781 C 4.332031 17.917969 3.648438 16.890625 3.148438 15.726562 C 2.648438 14.558594 2.398438 13.316406 2.398438 12 C 2.398438 10.667969 2.648438 9.425781 3.148438 8.273438 C 3.648438 7.109375 4.332031 6.089844 5.199219 5.226562 C 6.082031 4.339844 7.109375 3.648438 8.273438 3.148438 C 9.441406 2.648438 10.683594 2.398438 12 2.398438 C 13.332031 2.398438 14.574219 2.648438 15.726562 3.148438 C 16.890625 3.648438 17.910156 4.339844 18.773438 5.226562 C 19.660156 6.089844 20.351562 7.109375 20.851562 8.273438 C 21.351562 9.425781 21.601562 10.667969 21.601562 12 C 21.601562 13.316406 21.351562 14.558594 20.851562 15.726562 C 20.351562 16.890625 19.660156 17.917969 18.773438 18.800781 C 17.910156 19.667969 16.890625 20.351562 15.726562 20.851562 C 14.574219 21.351562 13.332031 21.601562 12 21.601562 Z M 12 19.800781 C 14.167969 19.800781 16.007812 19.042969 17.523438 17.523438 C 19.042969 16.007812 19.800781 14.167969 19.800781 12 C 19.800781 9.832031 19.042969 7.992188 17.523438 6.476562 C 16.007812 4.957031 14.167969 4.199219 12 4.199219 C 9.832031 4.199219 7.992188 4.957031 6.476562 6.476562 C 4.957031 7.992188 4.199219 9.832031 4.199219 12 C 4.199219 14.167969 4.957031 16.007812 6.476562 17.523438 C 7.992188 19.042969 9.832031 19.800781 12 19.800781 Z M 12 19.800781" />
-</vector>
\ No newline at end of file
diff --git a/components/browser_ui/site_settings/android/java/res/drawable/ic_timer.xml b/components/browser_ui/site_settings/android/java/res/drawable/ic_timer.xml
new file mode 100644
index 0000000..ab617d9
--- /dev/null
+++ b/components/browser_ui/site_settings/android/java/res/drawable/ic_timer.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2023 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="@macro/default_icon_color"
+      android:pathData="M15,1H9v2h6V1z M11,14h2V8h-2V14z M19.03,7.39l1.42-1.42c-0.43-0.51-0.9-0.99-1.41-1.41l-1.42,1.42 C16.07,4.74,14.12,4,12,4c-4.97,0-9,4.03-9,9s4.02,9,9,9s9-4.03,9-9C21,10.88,20.26,8.93,19.03,7.39z M12,20c-3.87,0-7-3.13-7-7 s3.13-7,7-7s7,3.13,7,7S15.87,20,12,20z" />
+</vector>
\ No newline at end of file
diff --git a/components/browser_ui/site_settings/android/java/res/xml/website_preferences.xml b/components/browser_ui/site_settings/android/java/res/xml/website_preferences.xml
index 5cebf90..2da7a752 100644
--- a/components/browser_ui/site_settings/android/java/res/xml/website_preferences.xml
+++ b/components/browser_ui/site_settings/android/java/res/xml/website_preferences.xml
@@ -79,12 +79,17 @@
     <org.chromium.components.browser_ui.settings.TextMessagePreference
         android:key="anti_abuse_when_on_section_one"
         android:summary="@string/anti_abuse_when_on_section_one"
-        android:icon="@drawable/ic_dashboard"
+        android:icon="@drawable/ic_archive"
         app:allowDividerBelow="false" />
     <org.chromium.components.browser_ui.settings.TextMessagePreference
         android:key="anti_abuse_when_on_section_two"
         android:summary="@string/anti_abuse_when_on_section_two"
-        android:icon="@drawable/ic_background_replace"
+        android:icon="@drawable/ic_dashboard"
+        app:allowDividerBelow="false" />
+    <org.chromium.components.browser_ui.settings.TextMessagePreference
+        android:key="anti_abuse_when_on_section_three"
+        android:summary="@string/anti_abuse_when_on_section_three"
+        android:icon="@drawable/ic_timer"
         app:allowDividerBelow="false" />
     <PreferenceCategory
         android:key="anti_abuse_things_to_consider_header"
@@ -92,6 +97,6 @@
     <org.chromium.components.browser_ui.settings.TextMessagePreference
         android:key="anti_abuse_things_to_consider_section_one"
         android:summary="@string/anti_abuse_things_to_consider_section_one"
-        android:icon="@drawable/ic_check_circle_outline"
+        android:icon="@drawable/ic_background_replace"
         app:allowDividerBelow="false" />
 </PreferenceScreen>
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
index c1b94c7..c30564bd 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
@@ -208,6 +208,8 @@
     public static final String ANTI_ABUSE_WHEN_ON_HEADER = "anti_abuse_when_on_header";
     public static final String ANTI_ABUSE_WHEN_ON_SECTION_ONE = "anti_abuse_when_on_section_one";
     public static final String ANTI_ABUSE_WHEN_ON_SECTION_TWO = "anti_abuse_when_on_section_two";
+    public static final String ANTI_ABUSE_WHEN_ON_SECTION_THREE =
+            "anti_abuse_when_on_section_three";
     public static final String ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER =
             "anti_abuse_things_to_consider_header";
     public static final String ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE =
@@ -1166,6 +1168,8 @@
                     screen.findPreference(ANTI_ABUSE_WHEN_ON_SECTION_ONE);
             Preference antiAbuseWhenOnSectionTwo =
                     screen.findPreference(ANTI_ABUSE_WHEN_ON_SECTION_TWO);
+            Preference antiAbuseWhenOnSectionThree =
+                    screen.findPreference(ANTI_ABUSE_WHEN_ON_SECTION_THREE);
             Preference antiAbuseThingsToConsiderHeader =
                     screen.findPreference(ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER);
             Preference antiAbuseThingsToConsiderSectionOne =
@@ -1174,6 +1178,7 @@
             screen.removePreference(antiAbuseWhenOnHeader);
             screen.removePreference(antiAbuseWhenOnSectionOne);
             screen.removePreference(antiAbuseWhenOnSectionTwo);
+            screen.removePreference(antiAbuseWhenOnSectionThree);
             screen.removePreference(antiAbuseThingsToConsiderHeader);
             screen.removePreference(antiAbuseThingsToConsiderSectionOne);
         }
diff --git a/components/browser_ui/strings/android/site_settings.grdp b/components/browser_ui/strings/android/site_settings.grdp
index c4666f75..4a077ce 100644
--- a/components/browser_ui/strings/android/site_settings.grdp
+++ b/components/browser_ui/strings/android/site_settings.grdp
@@ -366,20 +366,24 @@
     When on
   </message>
 
-  <message name="IDS_ANTI_ABUSE_WHEN_ON_SECTION_ONE" desc="Summary text explaining that browsing is smoother when the 'anti-abuse' setting is enabled.">
-    Browsing is faster because a site is less likely to ask you to verify you're a real person
+  <message name="IDS_ANTI_ABUSE_WHEN_ON_SECTION_ONE" desc="Summary text explaining that Chrome saves a small amount of data when the anti-abuse features are enabled.">
+    A site you visit can save a small amount of info with Chrome, mainly to validate you're not a bot
   </message>
 
-  <message name="IDS_ANTI_ABUSE_WHEN_ON_SECTION_TWO" desc="Summary text explaining that the anti-abuse features do not reveal your browsing history.">
-    This setting works without identifying you or allowing sites to see your browsing history
+  <message name="IDS_ANTI_ABUSE_WHEN_ON_SECTION_TWO" desc="Summary text explaining how the anti-abuse features work.">
+    As you keep browsing, sites can check with Chrome and verify with a previous site you've visited that you're likely a real person
+  </message>
+
+  <message name="IDS_ANTI_ABUSE_WHEN_ON_SECTION_THREE" desc="Summary text explaining that browsing could be helped by the anti-abuse features.">
+    Browsing is faster because a site is less likely to ask you to verify you're a real person
   </message>
 
   <message name="IDS_ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER" desc="Header text for the section explaining additional things to consider when the 'anti-abuse' setting is enabled.">
     Things to consider
   </message>
 
-  <message name="IDS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE" desc="Summary text explaining that sites can save info with Chrome when the 'anti-abuse' setting is enabled.">
-    A site you visit can save info with Chrome that validates you're not a bot. As you keep browsing, sites can check with Chrome and verify with a previous site you've visited that you're likely a real person
+  <message name="IDS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE" desc="Summary text explaining that the anti-abuse features do not reveal a user's browsing history.">
+    This setting works without identifying you or allowing sites to see your browsing history, though sites can share a small amount of info as part of the verification
   </message>
 
   <!-- Augmented reality -->
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_DESCRIPTION.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_DESCRIPTION.png.sha1
index 082f8390..964f31b 100644
--- a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_DESCRIPTION.png.sha1
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_DESCRIPTION.png.sha1
@@ -1 +1 @@
-6b4d0cb9aafd724891dda0cdb572e3daf4834891
\ No newline at end of file
+1aab8a5fd54cb32d79d5dcbd2e65d87b7df941c2
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_PERMISSION_TITLE.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_PERMISSION_TITLE.png.sha1
index 082f8390..964f31b 100644
--- a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_PERMISSION_TITLE.png.sha1
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_PERMISSION_TITLE.png.sha1
@@ -1 +1 @@
-6b4d0cb9aafd724891dda0cdb572e3daf4834891
\ No newline at end of file
+1aab8a5fd54cb32d79d5dcbd2e65d87b7df941c2
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER.png.sha1
index 082f8390..964f31b 100644
--- a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER.png.sha1
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_THINGS_TO_CONSIDER_HEADER.png.sha1
@@ -1 +1 @@
-6b4d0cb9aafd724891dda0cdb572e3daf4834891
\ No newline at end of file
+1aab8a5fd54cb32d79d5dcbd2e65d87b7df941c2
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE.png.sha1
index 082f8390..964f31b 100644
--- a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE.png.sha1
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_THINGS_TO_CONSIDER_SECTION_ONE.png.sha1
@@ -1 +1 @@
-6b4d0cb9aafd724891dda0cdb572e3daf4834891
\ No newline at end of file
+1aab8a5fd54cb32d79d5dcbd2e65d87b7df941c2
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_HEADER.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_HEADER.png.sha1
index 082f8390..964f31b 100644
--- a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_HEADER.png.sha1
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_HEADER.png.sha1
@@ -1 +1 @@
-6b4d0cb9aafd724891dda0cdb572e3daf4834891
\ No newline at end of file
+1aab8a5fd54cb32d79d5dcbd2e65d87b7df941c2
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_SECTION_ONE.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_SECTION_ONE.png.sha1
index 082f8390..964f31b 100644
--- a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_SECTION_ONE.png.sha1
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_SECTION_ONE.png.sha1
@@ -1 +1 @@
-6b4d0cb9aafd724891dda0cdb572e3daf4834891
\ No newline at end of file
+1aab8a5fd54cb32d79d5dcbd2e65d87b7df941c2
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_SECTION_THREE.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_SECTION_THREE.png.sha1
new file mode 100644
index 0000000..964f31b
--- /dev/null
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_SECTION_THREE.png.sha1
@@ -0,0 +1 @@
+1aab8a5fd54cb32d79d5dcbd2e65d87b7df941c2
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_SECTION_TWO.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_SECTION_TWO.png.sha1
index 082f8390..964f31b 100644
--- a/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_SECTION_TWO.png.sha1
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_ANTI_ABUSE_WHEN_ON_SECTION_TWO.png.sha1
@@ -1 +1 @@
-6b4d0cb9aafd724891dda0cdb572e3daf4834891
\ No newline at end of file
+1aab8a5fd54cb32d79d5dcbd2e65d87b7df941c2
\ No newline at end of file
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index 79ba03d..adf1458 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "20.50",
-  "log_list_timestamp": "2023-04-24T12:54:54Z",
+  "version": "20.51",
+  "log_list_timestamp": "2023-04-25T12:56:12Z",
   "operators": [
     {
       "name": "Google",
diff --git a/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc b/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc
index f963125..8b8c8aa 100644
--- a/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc
+++ b/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc
@@ -219,7 +219,6 @@
         const GURL& url,
         base::Time expected_response_time,
         mojo_base::BigBuffer data,
-        const url::Origin& cache_storage_origin,
         const std::string& cache_storage_cache_name) override {}
 
    private:
diff --git a/components/media_router/browser/media_router_base.cc b/components/media_router/browser/media_router_base.cc
index 89d4a4e..e6c1cbd 100644
--- a/components/media_router/browser/media_router_base.cc
+++ b/components/media_router/browser/media_router_base.cc
@@ -38,7 +38,7 @@
 
 // static
 std::string MediaRouterBase::CreatePresentationId() {
-  return "mr_" + base::GenerateUuid();
+  return "mr_" + base::Uuid::GenerateRandomV4().AsLowercaseString();
 }
 
 void MediaRouterBase::NotifyPresentationConnectionStateChange(
diff --git a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
index 20ab5d3e..71193cc 100644
--- a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
+++ b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
@@ -224,9 +224,9 @@
           WebFeature::kWebCodecsAudioEncoder,
           WebFeature::kWebCodecsVideoFrameFromImage,
           WebFeature::kWebCodecsVideoFrameFromBuffer,
-          WebFeature::kPrivateNetworkAccessIgnoredPreflightError,
           WebFeature::kPrivateNetworkAccessIgnoredCrossOriginPreflightError,
           WebFeature::kPrivateNetworkAccessIgnoredCrossSitePreflightError,
+          WebFeature::kPrivateNetworkAccessPreflightWarning,
           WebFeature::kWebBluetoothGetAvailability,
           WebFeature::kCookieHasNotBeenRefreshedIn201To300Days,
           WebFeature::kCookieHasNotBeenRefreshedIn301To350Days,
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index f5dc8a6..c272170 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -635,7 +635,6 @@
     "login_database_unittest.cc",
     "old_google_credentials_cleaner_unittest.cc",
     "origin_credential_store_unittest.cc",
-    "passkey_credential_unittest.cc",
     "password_access_authenticator_unittest.cc",
     "password_account_storage_settings_watcher_unittest.cc",
     "password_autofill_manager_unittest.cc",
diff --git a/components/password_manager/core/browser/get_logins_with_affiliations_request_handler.cc b/components/password_manager/core/browser/get_logins_with_affiliations_request_handler.cc
index 1e5b790a..9fd6399 100644
--- a/components/password_manager/core/browser/get_logins_with_affiliations_request_handler.cc
+++ b/components/password_manager/core/browser/get_logins_with_affiliations_request_handler.cc
@@ -15,6 +15,7 @@
 #include "components/password_manager/core/browser/password_manager_util.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
 #include "components/password_manager/core/browser/psl_matching_helper.h"
+#include "components/password_manager/core/common/password_manager_features.h"
 
 namespace password_manager {
 
@@ -36,7 +37,8 @@
         PasswordStoreInterface* store)
     : requested_digest_(form), consumer_(std::move(consumer)), store_(store) {
   forms_received_ = base::BarrierClosure(
-      kCallsNumber,
+      kCallsNumber +
+          base::FeatureList::IsEnabled(features::kFillingAcrossGroupedSites),
       base::BindOnce(&GetLoginsWithAffiliationsRequestHandler::NotifyConsumer,
                      base::Unretained(this)));
 }
@@ -59,10 +61,17 @@
       this);
 }
 
-base::OnceCallback<void(LoginsResultOrError)>
-GetLoginsWithAffiliationsRequestHandler::AffiliatedLoginsClosure() {
+base::OnceCallback<
+    std::vector<PasswordFormDigest>(const std::vector<std::string>&)>
+GetLoginsWithAffiliationsRequestHandler::GroupClosure() {
   return base::BindOnce(
-      &GetLoginsWithAffiliationsRequestHandler::HandleAffiliatedLoginsReceived,
+      &GetLoginsWithAffiliationsRequestHandler::HandleGroupReceived, this);
+}
+
+base::OnceCallback<void(LoginsResultOrError)>
+GetLoginsWithAffiliationsRequestHandler::NonFormLoginsClosure() {
+  return base::BindOnce(
+      &GetLoginsWithAffiliationsRequestHandler::HandleNonFormLoginsReceived,
       this);
 }
 
@@ -109,7 +118,23 @@
   return forms;
 }
 
-void GetLoginsWithAffiliationsRequestHandler::HandleAffiliatedLoginsReceived(
+std::vector<PasswordFormDigest>
+GetLoginsWithAffiliationsRequestHandler::HandleGroupReceived(
+    const std::vector<std::string>& realms) {
+  CHECK(base::FeatureList::IsEnabled(features::kFillingAcrossGroupedSites));
+
+  std::vector<PasswordFormDigest> forms;
+  for (const auto& realm : realms) {
+    // The PSL forms are requested in the main request.
+    if (!IsPublicSuffixDomainMatch(realm, requested_digest_.signon_realm)) {
+      forms.emplace_back(PasswordForm::Scheme::kHtml, realm, GURL(realm));
+    }
+  }
+  group_ = base::flat_set<std::string>(realms.begin(), realms.end());
+  return forms;
+}
+
+void GetLoginsWithAffiliationsRequestHandler::HandleNonFormLoginsReceived(
     LoginsResultOrError logins_or_error) {
   if (absl::holds_alternative<PasswordStoreBackendError>(logins_or_error)) {
     backend_error_ = absl::get<PasswordStoreBackendError>(logins_or_error);
@@ -155,8 +180,14 @@
             !IsValidAndroidFacetURI(form->signon_realm)) {
           signon_realm = form->url.DeprecatedGetOriginAsURL().spec();
         }
-        if (base::Contains(affiliations_, signon_realm))
+        if (base::Contains(affiliations_, signon_realm)) {
           form->is_affiliation_based_match = true;
+        } else if (base::Contains(group_, signon_realm)) {
+          form->is_grouped_match = true;
+          // TODO(crbug.com/1432264): Delete after proper handling of affiliated
+          // groups filling is implemented.
+          form->is_affiliation_based_match = true;
+        }
         break;
       }
     }
diff --git a/components/password_manager/core/browser/get_logins_with_affiliations_request_handler.h b/components/password_manager/core/browser/get_logins_with_affiliations_request_handler.h
index b591360..da06a40 100644
--- a/components/password_manager/core/browser/get_logins_with_affiliations_request_handler.h
+++ b/components/password_manager/core/browser/get_logins_with_affiliations_request_handler.h
@@ -29,6 +29,8 @@
 // Helper object which is used to obtain PasswordForms for a particular login
 // and affiliated logins parallelly. 'consumer' is notified about result
 // afterwards.
+// TODO(crbug.com/1432264): Rewrite the class according to comments in
+// crrev.com/c/chromium/src/+/4439696/comment/be22b57e_15a4f8ce/
 class GetLoginsWithAffiliationsRequestHandler
     : public base::RefCounted<GetLoginsWithAffiliationsRequestHandler> {
  public:
@@ -51,8 +53,15 @@
       std::vector<PasswordFormDigest>(const std::vector<std::string>&)>
   AffiliationsClosure();
 
-  // Returns a OnceCallback that calls 'HandleAffiliatedLoginsReceived()'.
-  base::OnceCallback<void(LoginsResultOrError)> AffiliatedLoginsClosure();
+  // Returns a OnceCallback that calls 'HandleGroupReceived()'. The
+  // callback returns the forms to be additionally requested from the password
+  // store.
+  base::OnceCallback<
+      std::vector<PasswordFormDigest>(const std::vector<std::string>&)>
+  GroupClosure();
+
+  // Returns a OnceCallback that calls 'HandleNonLoginsReceived()'.
+  base::OnceCallback<void(LoginsResultOrError)> NonFormLoginsClosure();
 
  private:
   friend class base::RefCounted<GetLoginsWithAffiliationsRequestHandler>;
@@ -70,10 +79,14 @@
   std::vector<PasswordFormDigest> HandleAffiliationsReceived(
       const std::vector<std::string>& realms);
 
-  // Receives all the affiliated logins from the password store or an error,
+  // Similar to |HandleAffiliationsReceived|, but only for grouping.
+  std::vector<PasswordFormDigest> HandleGroupReceived(
+      const std::vector<std::string>& realms);
+
+  // Receives affiliated and group logins from the password store or an error,
   // in case one occurred, processes `logins_or_error` and calls
   // `forms_received_`.
-  void HandleAffiliatedLoginsReceived(LoginsResultOrError logins_or_error);
+  void HandleNonFormLoginsReceived(LoginsResultOrError logins_or_error);
 
   void NotifyConsumer();
 
@@ -82,11 +95,15 @@
   // All the affiliations for 'requested_digest_'.
   base::flat_set<std::string> affiliations_;
 
+  // The group realms for 'requested_digest_'.
+  base::flat_set<std::string> group_;
+
   base::WeakPtr<PasswordStoreConsumer> consumer_;
 
   raw_ptr<PasswordStoreInterface, DanglingUntriaged> store_;
 
-  // Closure which is released after being called 2 times.
+  // Closure which is released after being called 2 times (3 in case
+  // |kFillingAcrossGroupedSites| is enabled).
   base::RepeatingClosure forms_received_;
 
   // PasswordForms to be sent to consumer if the backend call made to retrieve
diff --git a/components/password_manager/core/browser/get_logins_with_affiliations_request_handler_unittest.cc b/components/password_manager/core/browser/get_logins_with_affiliations_request_handler_unittest.cc
index c7e1d3d..4ecb50e 100644
--- a/components/password_manager/core/browser/get_logins_with_affiliations_request_handler_unittest.cc
+++ b/components/password_manager/core/browser/get_logins_with_affiliations_request_handler_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/functional/callback.h"
 #include "base/strings/string_piece.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 
 #include "components/password_manager/core/browser/mock_password_store_consumer.h"
@@ -14,6 +15,7 @@
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
 #include "components/password_manager/core/browser/password_store_backend_error.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/common/password_manager_features.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -28,6 +30,8 @@
 constexpr const char kTestWebURL1[] = "https://one.example.com/path";
 constexpr const char kAffiliatedWebURL1[] = "https://noneexample.com/path";
 constexpr const char kAffiliatedRealm1[] = "https://noneexample.com/";
+constexpr const char kGroupWebURL1[] = "https://noneexample2.com/path";
+constexpr const char kGroupRealm1[] = "https://noneexample2.com/";
 
 const PasswordStoreBackendError kBackendError = PasswordStoreBackendError(
     PasswordStoreBackendErrorType::kUncategorized,
@@ -106,7 +110,7 @@
 
   std::vector<std::unique_ptr<PasswordForm>> affiliated_forms;
   affiliated_forms.push_back(std::make_unique<PasswordForm>(affiliated_form));
-  handler->AffiliatedLoginsClosure().Run(std::move(affiliated_forms));
+  handler->NonFormLoginsClosure().Run(std::move(affiliated_forms));
 }
 
 TEST_F(GetLoginsWithAffiliationsRequestHandlerTest,
@@ -122,7 +126,7 @@
       CreateForm(kAffiliatedWebURL1, u"username3", u"password");
   std::vector<std::unique_ptr<PasswordForm>> affiliated_forms;
   affiliated_forms.push_back(std::make_unique<PasswordForm>(*affiliated_form));
-  handler->AffiliatedLoginsClosure().Run(std::move(affiliated_forms));
+  handler->NonFormLoginsClosure().Run(std::move(affiliated_forms));
 
   std::vector<std::unique_ptr<PasswordForm>> expected_forms = MakeCopy(forms);
 
@@ -134,6 +138,81 @@
   handler->LoginsForFormClosure().Run(std::move(forms));
 }
 
+TEST_F(GetLoginsWithAffiliationsRequestHandlerTest,
+       GroupLoginsReceivedBeforeAffiliations) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kFillingAcrossGroupedSites);
+  std::vector<std::unique_ptr<PasswordForm>> forms;
+  forms.push_back(CreateForm(kTestWebURL1, u"username1", u"password"));
+  forms.push_back(CreateForm(kTestWebURL1, u"username2", u"password"));
+
+  auto handler = MakeRequestHandler();
+  handler->LoginsForFormClosure().Run(MakeCopy(forms));
+
+  EXPECT_THAT(handler->GroupClosure().Run({kGroupRealm1}),
+              ElementsAre(CreateHTMLFormDigest(kGroupRealm1)));
+  std::vector<std::unique_ptr<PasswordForm>> group_forms;
+  PasswordForm group_form =
+      *CreateForm(kGroupWebURL1, u"username4", u"password");
+  group_forms.push_back(std::make_unique<PasswordForm>(group_form));
+  std::vector<std::unique_ptr<PasswordForm>> expected_forms = std::move(forms);
+  expected_forms.push_back(std::make_unique<PasswordForm>(group_form));
+  expected_forms.back()->is_affiliation_based_match = true;
+  expected_forms.back()->is_grouped_match = true;
+  handler->NonFormLoginsClosure().Run(std::move(group_forms));
+
+  EXPECT_THAT(handler->AffiliationsClosure().Run({kAffiliatedRealm1}),
+              ElementsAre(CreateHTMLFormDigest(kAffiliatedRealm1)));
+  PasswordForm affiliated_form =
+      *CreateForm(kAffiliatedWebURL1, u"username3", u"password");
+  std::vector<std::unique_ptr<PasswordForm>> affiliated_forms;
+  affiliated_forms.push_back(std::make_unique<PasswordForm>(affiliated_form));
+  expected_forms.push_back(std::make_unique<PasswordForm>(affiliated_form));
+  expected_forms.back()->is_affiliation_based_match = true;
+
+  EXPECT_CALL(*consumer(), OnGetPasswordStoreResultsOrErrorFrom(
+                               _, LoginsResultsOrErrorAre(&expected_forms)));
+  handler->NonFormLoginsClosure().Run(std::move(affiliated_forms));
+}
+
+TEST_F(GetLoginsWithAffiliationsRequestHandlerTest,
+       GroupLoginsReceivedAfterAffiliations) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kFillingAcrossGroupedSites);
+  std::vector<std::unique_ptr<PasswordForm>> forms;
+  forms.push_back(CreateForm(kTestWebURL1, u"username1", u"password"));
+  forms.push_back(CreateForm(kTestWebURL1, u"username2", u"password"));
+
+  auto handler = MakeRequestHandler();
+  handler->LoginsForFormClosure().Run(MakeCopy(forms));
+
+  EXPECT_THAT(handler->AffiliationsClosure().Run({kAffiliatedRealm1}),
+              ElementsAre(CreateHTMLFormDigest(kAffiliatedRealm1)));
+  PasswordForm affiliated_form =
+      *CreateForm(kAffiliatedWebURL1, u"username3", u"password");
+  std::vector<std::unique_ptr<PasswordForm>> affiliated_forms;
+  affiliated_forms.push_back(std::make_unique<PasswordForm>(affiliated_form));
+  handler->NonFormLoginsClosure().Run(std::move(affiliated_forms));
+  std::vector<std::unique_ptr<PasswordForm>> expected_forms = std::move(forms);
+  expected_forms.push_back(std::make_unique<PasswordForm>(affiliated_form));
+  expected_forms.back()->is_affiliation_based_match = true;
+
+  EXPECT_THAT(handler->GroupClosure().Run({kGroupRealm1}),
+              ElementsAre(CreateHTMLFormDigest(kGroupRealm1)));
+  std::vector<std::unique_ptr<PasswordForm>> group_forms;
+  PasswordForm group_form =
+      *CreateForm(kGroupWebURL1, u"username4", u"password");
+  group_forms.push_back(std::make_unique<PasswordForm>(group_form));
+  expected_forms.push_back(std::make_unique<PasswordForm>(group_form));
+  expected_forms.back()->is_affiliation_based_match = true;
+  expected_forms.back()->is_grouped_match = true;
+
+  EXPECT_CALL(*consumer(), OnGetPasswordStoreResultsOrErrorFrom(
+                               _, LoginsResultsOrErrorAre(&expected_forms)));
+
+  handler->NonFormLoginsClosure().Run(std::move(group_forms));
+}
+
 TEST_F(GetLoginsWithAffiliationsRequestHandlerTest, ConsumerNotNotified) {
   auto handler = MakeRequestHandler();
   std::vector<std::unique_ptr<PasswordForm>> forms;
@@ -148,7 +227,7 @@
   EXPECT_CALL(*consumer(), OnGetPasswordStoreResultsOrErrorFrom).Times(0);
 
   handler->AffiliationsClosure().Run({kAffiliatedRealm1});
-  handler->AffiliatedLoginsClosure().Run(std::move(affiliated_forms));
+  handler->NonFormLoginsClosure().Run(std::move(affiliated_forms));
   handler->LoginsForFormClosure().Run(std::move(forms));
 }
 
@@ -202,7 +281,7 @@
       *CreateForm(kAffiliatedWebURL1, u"username3", u"password");
   std::vector<std::unique_ptr<PasswordForm>> affiliated_forms;
   affiliated_forms.push_back(std::make_unique<PasswordForm>(affiliated_form));
-  handler->AffiliatedLoginsClosure().Run(std::move(affiliated_forms));
+  handler->NonFormLoginsClosure().Run(std::move(affiliated_forms));
 }
 
 TEST_F(GetLoginsWithAffiliationsRequestHandlerTest,
@@ -220,7 +299,7 @@
       *CreateForm(kAffiliatedWebURL1, u"username3", u"password");
   std::vector<std::unique_ptr<PasswordForm>> affiliated_forms;
   affiliated_forms.push_back(std::make_unique<PasswordForm>(affiliated_form));
-  handler->AffiliatedLoginsClosure().Run(std::move(affiliated_forms));
+  handler->NonFormLoginsClosure().Run(std::move(affiliated_forms));
   handler->LoginsForFormClosure().Run(kBackendError);
 }
 
@@ -235,7 +314,7 @@
               OnGetPasswordStoreResultsOrErrorFrom(
                   _, VariantWith<PasswordStoreBackendError>(kBackendError)));
 
-  handler->AffiliatedLoginsClosure().Run(kBackendError);
+  handler->NonFormLoginsClosure().Run(kBackendError);
 
   std::vector<std::unique_ptr<PasswordForm>> forms;
   forms.push_back(CreateForm(kTestWebURL1, u"username1", u"password"));
@@ -258,7 +337,7 @@
   forms.push_back(CreateForm(kTestWebURL1, u"username2", u"password"));
   handler->LoginsForFormClosure().Run(std::move(forms));
 
-  handler->AffiliatedLoginsClosure().Run(kBackendError);
+  handler->NonFormLoginsClosure().Run(kBackendError);
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/passkey_credential.cc b/components/password_manager/core/browser/passkey_credential.cc
index c827215..a775f115 100644
--- a/components/password_manager/core/browser/passkey_credential.cc
+++ b/components/password_manager/core/browser/passkey_credential.cc
@@ -2,32 +2,27 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <string>
-
-#include "base/strings/utf_string_conversions.h"
 #include "components/password_manager/core/browser/passkey_credential.h"
+
+#include <string>
+#include <vector>
+
 #include "components/strings/grit/components_strings.h"
-#include "ui/base/l10n/l10n_util.h"
 
 namespace password_manager {
 
-namespace {
-
-std::u16string ToUsernameString(const PasskeyCredential::Username& username) {
-  if (username.value() && !username.value()->empty()) {
-    return base::UTF8ToUTF16(*username.value());
-  }
-  return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN);
-}
-
-}  // namespace
-
-PasskeyCredential::PasskeyCredential(const Username& username,
-                                     const DeviceName& device_name,
-                                     const BackendId& backend_id)
-    : username_(ToUsernameString(username)),
-      device_name_(device_name),
-      backend_id_(backend_id) {}
+PasskeyCredential::PasskeyCredential(Source source,
+                                     std::string rp_id,
+                                     std::vector<uint8_t> credential_id,
+                                     std::vector<uint8_t> user_id,
+                                     std::string username,
+                                     std::string display_name)
+    : source_(source),
+      rp_id_(std::move(rp_id)),
+      credential_id_(std::move(credential_id)),
+      user_id_(std::move(user_id)),
+      username_(std::move(username)),
+      display_name_(std::move(display_name)) {}
 
 PasskeyCredential::~PasskeyCredential() = default;
 
@@ -38,6 +33,19 @@
 PasskeyCredential::PasskeyCredential(PasskeyCredential&&) = default;
 PasskeyCredential& PasskeyCredential::operator=(PasskeyCredential&&) = default;
 
+int PasskeyCredential::GetAuthenticatorLabel() const {
+  switch (source_) {
+    case Source::kWindowsHello:
+      return IDS_PASSWORD_MANAGER_USE_WINDOWS_HELLO;
+    case Source::kTouchId:
+      return IDS_PASSWORD_MANAGER_USE_TOUCH_ID;
+    case Source::kAndroidPhone:
+      return IDS_PASSWORD_MANAGER_USE_SCREEN_LOCK;
+    case Source::kOther:
+      return IDS_PASSWORD_MANAGER_USE_GENERIC_DEVICE;
+  }
+}
+
 bool operator==(const PasskeyCredential& lhs,
                 const PasskeyCredential& rhs) = default;
 
diff --git a/components/password_manager/core/browser/passkey_credential.h b/components/password_manager/core/browser/passkey_credential.h
index f2364669..7bf384bd 100644
--- a/components/password_manager/core/browser/passkey_credential.h
+++ b/components/password_manager/core/browser/passkey_credential.h
@@ -5,25 +5,29 @@
 #ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSKEY_CREDENTIAL_H_
 #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSKEY_CREDENTIAL_H_
 
+#include <stdint.h>
 #include <string>
-
-#include "base/types/strong_alias.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include <vector>
 
 namespace password_manager {
 
-// Represents a Web Authentication passkey credential to be displayed in an
-// autofill selection context.
+// Represents a Web Authentication passkey credential to be displayed in
+// autofill and password manager selection contexts.
 class PasskeyCredential {
  public:
-  using Username =
-      base::StrongAlias<struct UsernameTag, absl::optional<std::string>>;
-  using DeviceName = base::StrongAlias<struct DeviceNameTag, std::u16string>;
-  using BackendId = base::StrongAlias<struct BackendIdTag, std::string>;
+  enum class Source {
+    kAndroidPhone,
+    kTouchId,
+    kWindowsHello,
+    kOther,
+  };
 
-  PasskeyCredential(const Username& username,
-                    const DeviceName& device_name,
-                    const BackendId& backend_id);
+  PasskeyCredential(Source source,
+                    std::string rp_id,
+                    std::vector<uint8_t> credential_id,
+                    std::vector<uint8_t> user_id,
+                    std::string username = "",
+                    std::string display_name = "");
   ~PasskeyCredential();
 
   PasskeyCredential(const PasskeyCredential&);
@@ -32,17 +36,43 @@
   PasskeyCredential(PasskeyCredential&&);
   PasskeyCredential& operator=(PasskeyCredential&&);
 
-  const std::u16string& username() const { return username_; }
-  const std::u16string& device_name() const { return device_name_; }
-  const std::string& id() const { return backend_id_; }
+  // Returns the l10n ID for the name of the authenticator this credential
+  // belongs to.
+  int GetAuthenticatorLabel() const;
+
+  Source source() const { return source_; }
+  const std::string& rp_id() const { return rp_id_; }
+  const std::vector<uint8_t>& credential_id() const { return credential_id_; }
+  const std::vector<uint8_t>& user_id() const { return user_id_; }
+  const std::string& username() const { return username_; }
+  const std::string& display_name() const { return display_name_; }
 
  private:
   friend bool operator==(const PasskeyCredential& lhs,
                          const PasskeyCredential& rhs);
 
-  std::u16string username_;
-  std::u16string device_name_;
-  std::string backend_id_;
+  // Authenticator type this passkey belongs to.
+  Source source_;
+
+  // The relying party identifier.
+  // https://w3c.github.io/webauthn/#relying-party-identifier
+  std::string rp_id_;
+
+  // The credential identifier.
+  // https://w3c.github.io/webauthn/#credential-id
+  std::vector<uint8_t> credential_id_;
+
+  // The user's identifier handle.
+  // https://w3c.github.io/webauthn/#user-handle
+  std::vector<uint8_t> user_id_;
+
+  // The user's name.
+  // https://w3c.github.io/webauthn/#dom-publickeycredentialentity-name
+  std::string username_;
+
+  // The user's display name.
+  // https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-displayname
+  std::string display_name_;
 };
 
 bool operator==(const PasskeyCredential& lhs, const PasskeyCredential& rhs);
diff --git a/components/password_manager/core/browser/passkey_credential_unittest.cc b/components/password_manager/core/browser/passkey_credential_unittest.cc
deleted file mode 100644
index 7955ad9..0000000
--- a/components/password_manager/core/browser/passkey_credential_unittest.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/password_manager/core/browser/passkey_credential.h"
-
-#include <string>
-
-#include "components/strings/grit/components_strings.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace password_manager {
-
-constexpr char kUsername[] = "lora";
-const char16_t kUsernameUtf16[] = u"lora";
-const char16_t kDeviceName[] = u"Lora's Pixel 7";
-constexpr char kBackendId[] = "1234";
-
-class PasskeyCredentialTest : public testing::Test {};
-
-TEST_F(PasskeyCredentialTest, CreateCredential) {
-  PasskeyCredential credential((PasskeyCredential::Username(kUsername)),
-                               PasskeyCredential::DeviceName(kDeviceName),
-                               PasskeyCredential::BackendId(kBackendId));
-  EXPECT_EQ(credential.username(), kUsernameUtf16);
-  EXPECT_EQ(credential.device_name(), kDeviceName);
-  EXPECT_EQ(credential.id(), kBackendId);
-}
-
-TEST_F(PasskeyCredentialTest, CreateCredentialWithNoUsername) {
-  PasskeyCredential credential((PasskeyCredential::Username(absl::nullopt)),
-                               PasskeyCredential::DeviceName(kDeviceName),
-                               PasskeyCredential::BackendId(kBackendId));
-  EXPECT_EQ(credential.username(),
-            l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN));
-}
-
-TEST_F(PasskeyCredentialTest, CreateCredentialWithEmptyUsername) {
-  PasskeyCredential credential((PasskeyCredential::Username("")),
-                               PasskeyCredential::DeviceName(kDeviceName),
-                               PasskeyCredential::BackendId(kBackendId));
-  EXPECT_EQ(credential.username(),
-            l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN));
-}
-
-}  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc
index 7f1dfdcc..67f342f6 100644
--- a/components/password_manager/core/browser/password_autofill_manager.cc
+++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -12,6 +12,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/base64.h"
 #include "base/functional/bind.h"
 #include "base/i18n/case_conversion.h"
 #include "base/logging.h"
@@ -728,13 +729,14 @@
     base::ranges::transform(
         *delegate->GetPasskeys(), std::back_inserter(suggestions),
         [this](const auto& passkey) {
-          autofill::Suggestion suggestion(passkey.username());
+          autofill::Suggestion suggestion(ToUsernameString(passkey.username()));
           suggestion.icon = "globeIcon";
           suggestion.frontend_id = autofill::POPUP_ITEM_ID_WEBAUTHN_CREDENTIAL;
           suggestion.custom_icon = page_favicon_;
-          suggestion.payload = autofill::Suggestion::BackendId(passkey.id());
-          suggestion.labels = {
-              {autofill::Suggestion::Text(passkey.device_name())}};
+          suggestion.payload = autofill::Suggestion::BackendId(
+              base::Base64Encode(passkey.credential_id()));
+          suggestion.labels = {{autofill::Suggestion::Text(
+              l10n_util::GetStringUTF16(passkey.GetAuthenticatorLabel()))}};
           return suggestion;
         });
   }
diff --git a/components/password_manager/core/browser/password_autofill_manager_unittest.cc b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
index a27b371..81e7106e 100644
--- a/components/password_manager/core/browser/password_autofill_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/base64.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_refptr.h"
@@ -2084,14 +2085,12 @@
   InitializePasswordAutofillManager(&client, &autofill_client);
 
   // Return a WebAuthn credential.
-  const std::string kId = "abcd";
-  const std::u16string kDeviceName = u"Nadeshiko's Pixel 7";
+  const std::vector<uint8_t> kId = {1, 2, 3, 4};
+  const std::string kIdBase64 = base::Base64Encode(kId);
   const std::string kNameUtf8 = "nadeshiko@example.com";
   const std::u16string kName = u"nadeshiko@example.com";
-  PasskeyCredential::Username passkey_name(kNameUtf8);
-  PasskeyCredential::DeviceName device_name(kDeviceName);
-  PasskeyCredential::BackendId passkey_id(kId);
-  PasskeyCredential passkey(passkey_name, device_name, passkey_id);
+  PasskeyCredential passkey(PasskeyCredential::Source::kAndroidPhone,
+                            "example.com", kId, /*user_id=*/{}, kNameUtf8);
   EXPECT_CALL(client, GetWebAuthnCredentialsDelegateForDriver)
       .WillRepeatedly(Return(&webauthn_credentials_delegate));
   absl::optional<std::vector<PasskeyCredential>> passkey_list =
@@ -2118,7 +2117,7 @@
 #endif  // !BUILDFLAG(IS_ANDROID)
                   autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY)));
   EXPECT_EQ(open_args.suggestions[0].GetPayload<Suggestion::BackendId>(),
-            Suggestion::BackendId(kId));
+            Suggestion::BackendId(kIdBase64));
   EXPECT_EQ(open_args.suggestions[0].frontend_id,
             autofill::POPUP_ITEM_ID_WEBAUTHN_CREDENTIAL);
   EXPECT_EQ(open_args.suggestions[0].main_text.value, kName);
@@ -2126,7 +2125,8 @@
       AreImagesEqual(open_args.suggestions[0].custom_icon, kTestFavicon));
   ASSERT_EQ(open_args.suggestions[0].labels.size(), 1U);
   ASSERT_EQ(open_args.suggestions[0].labels[0].size(), 1U);
-  EXPECT_EQ(open_args.suggestions[0].labels[0][0].value, kDeviceName);
+  EXPECT_EQ(open_args.suggestions[0].labels[0][0].value,
+            l10n_util::GetStringUTF16(passkey.GetAuthenticatorLabel()));
   testing::Mock::VerifyAndClearExpectations(client.mock_driver());
 
   // Check that preview of the "username" (i.e. the credential name) works.
@@ -2138,7 +2138,7 @@
   testing::Mock::VerifyAndClearExpectations(client.mock_driver());
 
   // Check that selecting the credential reports back to the client.
-  EXPECT_CALL(webauthn_credentials_delegate, SelectPasskey(kId));
+  EXPECT_CALL(webauthn_credentials_delegate, SelectPasskey(kIdBase64));
   EXPECT_CALL(
       autofill_client,
       HideAutofillPopup(autofill::PopupHidingReason::kAcceptSuggestion));
@@ -2146,7 +2146,7 @@
   password_autofill_manager_->DidAcceptSuggestion(
       autofill::test::CreateAutofillSuggestion(
           autofill::POPUP_ITEM_ID_WEBAUTHN_CREDENTIAL, kName,
-          autofill::Suggestion::BackendId(kId)),
+          autofill::Suggestion::BackendId(kIdBase64)),
       /*position=*/1);
 }
 
@@ -2202,10 +2202,10 @@
   password_autofill_manager_->OnAddPasswordFillData(data);
 
   // Enable WebAuthn autofill to return a credential.
-  PasskeyCredential passkey(
-      PasskeyCredential::Username("nadeshiko@example.com"),
-      PasskeyCredential::DeviceName(u"Nadeshiko's Pixel 7"),
-      PasskeyCredential::BackendId("abcd"));
+  PasskeyCredential passkey(PasskeyCredential::Source::kAndroidPhone,
+                            "rpid.com",
+                            /*credential_id=*/{1, 2, 3, 4},
+                            /*user_id=*/{1, 2, 3, 4}, "nadeshiko@example.com");
   absl::optional<std::vector<PasskeyCredential>> passkeys =
       std::vector{std::move(passkey)};
   EXPECT_CALL(client, GetWebAuthnCredentialsDelegateForDriver)
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc
index 2a3b14c..ca2d249 100644
--- a/components/password_manager/core/browser/password_store.cc
+++ b/components/password_manager/core/browser/password_store.cc
@@ -292,7 +292,7 @@
   }
   // If there is no helper to retrieve affiliations with, inform the
   // `request_handler` that there are no affiliated logins.
-  request_handler->AffiliatedLoginsClosure().Run({});
+  request_handler->NonFormLoginsClosure().Run({});
 
   // And request the regular logins for `form`.
   backend_->FillMatchingLoginsAsync(request_handler->LoginsForFormClosure(),
@@ -541,7 +541,7 @@
 
   auto branding_injection_for_affiliations_callback =
       base::BindOnce(&PasswordStore::InjectAffiliationAndBrandingInformation,
-                     this, request_handler->AffiliatedLoginsClosure());
+                     this, request_handler->NonFormLoginsClosure());
 
   // This callback is to be owned and executed from `affiliated_match_helper_`.
   // Since `Shutdown` resets the `affiliated_match_helper_` before shutting down
diff --git a/components/password_manager/core/browser/password_ui_utils.cc b/components/password_manager/core/browser/password_ui_utils.cc
index 4eb8434..c27248c0 100644
--- a/components/password_manager/core/browser/password_ui_utils.cc
+++ b/components/password_manager/core/browser/password_ui_utils.cc
@@ -20,6 +20,8 @@
 #include "components/password_manager/core/browser/ui/credential_ui_entry.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/elide_url.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace password_manager {
 
@@ -161,4 +163,15 @@
   return usernames;
 }
 
+std::u16string ToUsernameString(const std::u16string& username) {
+  if (!username.empty()) {
+    return username;
+  }
+  return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN);
+}
+
+std::u16string ToUsernameString(const std::string& username) {
+  return ToUsernameString(base::UTF8ToUTF16(username));
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_ui_utils.h b/components/password_manager/core/browser/password_ui_utils.h
index 487e9e8..37a9b348 100644
--- a/components/password_manager/core/browser/password_ui_utils.h
+++ b/components/password_manager/core/browser/password_ui_utils.h
@@ -71,6 +71,14 @@
     const std::string& signon_realm,
     bool is_using_account_store);
 
+// Returns the resource identifier for the label describing the platform
+// authenticator, e.g. "Use TouchID".
+int GetPlatformAuthenticatorLabel();
+
+// Returns the username or a label appropriate for display if it is empty.
+std::u16string ToUsernameString(const std::u16string& username);
+std::u16string ToUsernameString(const std::string& username);
+
 }  // namespace password_manager
 
 #endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_UI_UTILS_H_
diff --git a/components/password_manager/core/browser/password_ui_utils_unittest.cc b/components/password_manager/core/browser/password_ui_utils_unittest.cc
index a8856328..61a70e0 100644
--- a/components/password_manager/core/browser/password_ui_utils_unittest.cc
+++ b/components/password_manager/core/browser/password_ui_utils_unittest.cc
@@ -7,7 +7,9 @@
 #include <tuple>
 
 #include "components/password_manager/core/browser/password_form.h"
+#include "components/strings/grit/components_strings.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
 namespace password_manager {
@@ -86,4 +88,13 @@
   }
 }
 
+TEST(ToUsernameString, NonEmptyUsername) {
+  EXPECT_EQ(ToUsernameString("nadeshiko"), u"nadeshiko");
+}
+
+TEST(ToUsernameString, EmptyUsername) {
+  EXPECT_EQ(ToUsernameString(""),
+            l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN));
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager_strings.grdp b/components/password_manager_strings.grdp
index 8f357a0..1f42f2d2 100644
--- a/components/password_manager_strings.grdp
+++ b/components/password_manager_strings.grdp
@@ -106,6 +106,18 @@
   <message name="IDS_PASSWORD_MANAGER_PASSWORD_FOR_ACCOUNT" desc="Voice over text read if the user focuses a drop down entry to fill a password for a given account.">
     Password for <ph name="username">$1<ex>chef@google.com</ex></ph>
   </message>
+  <message name="IDS_PASSWORD_MANAGER_USE_TOUCH_ID" desc="Text that appears in the password autofill popup, for the Mac TouchID passkey option. Touch ID passkeys let users use their local computer password or fingerprint reader to verify their identity, instead of a password. Do not translate as “password”; “passkey” is a unique concept.">
+    Use Touch ID
+  </message>
+  <message name="IDS_PASSWORD_MANAGER_USE_SCREEN_LOCK" desc="Text that appears in the Android autofill keyboard extension for passkeys. When the user taps the passkey, they are challenged with their screen lock to sign in to the website, which can be PIN or biometric.">
+    Use screen lock
+  </message>
+  <message name="IDS_PASSWORD_MANAGER_USE_WINDOWS_HELLO" desc="Text that appears in the password autofill popup, for the Windows Hello passkey option. Windows Hello passkeys let users use their Windows PIN or fingerprint reader to verify their identity, instead of a password. Do not translate as “password”; “passkey” is a unique concept.">
+    Use Windows Hello
+  </message>
+  <message name="IDS_PASSWORD_MANAGER_USE_GENERIC_DEVICE" desc="Text that appears in the password autofill popup, for the ChromeOS or generic passkey option. When the user clicks on this option, Chrome will verify their identity by having them enter a PIN or scan a fingerprint. Do not translate as “password”; “passkey” is a unique concept.">
+    Use device sign-in
+  </message>
   <if expr="use_titlecase">
     <message name="IDS_PASSWORD_MANAGER_USE_DEVICE_PASSKEY" desc="Text that appears in the password autofill popup, for the option to use a different device’s passkey. Passkeys let users use a device like their phone or computer to verify their identity, instead of a password. Do not translate as “password”; “passkey” is a unique concept.">
       Use a Passkey on a Different Device
@@ -117,9 +129,6 @@
     </message>
   </if>
   <if expr="is_win">
-    <message name="IDS_PASSWORD_MANAGER_USE_WINDOWS_HELLO" desc="Text that appears in the password autofill popup, for the Windows Hello passkey option. Windows Hello passkeys let users use their Windows PIN or fingerprint reader to verify their identity, instead of a password. Do not translate as “password”; “passkey” is a unique concept.">
-      Use Windows Hello
-    </message>
     <message name="IDS_PASSWORD_MANAGER_FILLING_REAUTH" desc="Text appears in the password autofill reauthentication popup, asking user to authenticate using biometric before filling.">
       Google Chrome is trying to fill your password on <ph name="APP_NAME">$1<ex>google.com</ex></ph>.
     </message>
@@ -143,9 +152,6 @@
     </message>
   </if>
   <if expr="is_macosx">
-    <message name="IDS_PASSWORD_MANAGER_USE_TOUCH_ID" desc="Text that appears in the password autofill popup, for the Mac TouchID passkey option. Touch ID passkeys let users use their local computer password or fingerprint reader to verify their identity, instead of a password. Do not translate as “password”; “passkey” is a unique concept.">
-      Use Touch ID
-    </message>
     <message name="IDS_PASSWORD_MANAGER_FILLING_REAUTH" desc="Shown after 'Google Chrome is trying to ' (or in some languages, 'Google Chrome wants to ') in a dialog message. Text appears in the password autofill reauthentication popup, asking user to authenticate using biometric before filling.">
       fill your password on <ph name="APP_NAME">$1<ex>google.com</ex></ph>
     </message>
@@ -168,11 +174,6 @@
       You can change whether you use your screen lock for filling passwords in <ph name="SETTINGS">$1<ex>Settings</ex></ph>
     </message>
   </if>
-  <if expr="not is_win and not is_macosx and not is_android">
-    <message name="IDS_PASSWORD_MANAGER_USE_GENERIC_DEVICE" desc="Text that appears in the password autofill popup, for the ChromeOS or generic passkey option. When the user clicks on this option, Chrome will verify their identity by having them enter a PIN or scan a fingerprint. Do not translate as “password”; “passkey” is a unique concept.">
-      Use device sign-in
-    </message>
-  </if>
   <if expr="is_win or is_macosx">
     <message name="IDS_PASSWORD_MANAGER_BIOMETRIC_AUTHENTICATION_FOR_FILLING_PROMO_ACCEPT_BUTTON" desc="Text that appears in the Accept button of biometric authentication before filling popup.">
       Continue
@@ -191,9 +192,4 @@
       </message>
     </if>
   </if>
-  <if expr="is_android">
-    <message name="IDS_PASSWORD_MANAGER_USE_SCREEN_LOCK" desc="Text that appears in the Android autofill keyboard extension for passkeys. When the user taps the passkey, they are challenged with their screen lock to sign in to the website, which can be PIN or biometric.">
-      Use screen lock
-    </message>
-  </if>
 </grit-part>
diff --git a/components/performance_manager/decorators/page_load_tracker_decorator_helper.cc b/components/performance_manager/decorators/page_load_tracker_decorator_helper.cc
index eedeb980..1b5520a 100644
--- a/components/performance_manager/decorators/page_load_tracker_decorator_helper.cc
+++ b/components/performance_manager/decorators/page_load_tracker_decorator_helper.cc
@@ -100,7 +100,16 @@
     if (loading_state_ == LoadingState::kLoading)
       return;
 
-    DCHECK_EQ(loading_state_, LoadingState::kWaitingForNavigation);
+    // There are a few cases where an ongoing navigation will get upgraded to
+    // show loading ui without a DidStartLoading (e.g., if an iframe navigates,
+    // then the top-level frame begins navigating before the iframe navigation
+    // completes). If that happened, emulate the DidStartLoading now before
+    // notifying PrimaryPageChanged.
+    if (loading_state_ != LoadingState::kWaitingForNavigation) {
+      NotifyPageLoadTrackerDecoratorOnPMSequence(
+          web_contents(), &PageLoadTrackerDecorator::DidStartLoading);
+    }
+
     loading_state_ = LoadingState::kLoading;
     NotifyPageLoadTrackerDecoratorOnPMSequence(
         web_contents(), &PageLoadTrackerDecorator::PrimaryPageChanged);
diff --git a/components/privacy_sandbox/mock_privacy_sandbox_settings.h b/components/privacy_sandbox/mock_privacy_sandbox_settings.h
index 549d73b4..cd59e6ed 100644
--- a/components/privacy_sandbox/mock_privacy_sandbox_settings.h
+++ b/components/privacy_sandbox/mock_privacy_sandbox_settings.h
@@ -75,6 +75,7 @@
   MOCK_METHOD(void, SetTopicsBlockedForTesting, (), (override));
   MOCK_METHOD(void, SetPrivacySandboxEnabled, (bool), (override));
   MOCK_METHOD(bool, IsPrivacySandboxRestricted, (), (override, const));
+  MOCK_METHOD(bool, IsSubjectToM1NoticeRestricted, (), (override, const));
   MOCK_METHOD(bool, IsRestrictedNoticeEnabled, (), (override, const));
   MOCK_METHOD(void, OnCookiesCleared, (), (override));
   MOCK_METHOD(void, AddObserver, (Observer*), (override));
diff --git a/components/privacy_sandbox/privacy_sandbox_settings.h b/components/privacy_sandbox/privacy_sandbox_settings.h
index e217f26..bd4bf34 100644
--- a/components/privacy_sandbox/privacy_sandbox_settings.h
+++ b/components/privacy_sandbox/privacy_sandbox_settings.h
@@ -52,6 +52,10 @@
     // When this returns false, access control functions for Topics will
     // return as not allowed.
     virtual bool HasAppropriateTopicsConsent() const = 0;
+
+    // Whether the profile is subject to being given notice of restrictions to
+    // the standard set of Privacy Sandbox APIs.
+    virtual bool IsSubjectToM1NoticeRestricted() const = 0;
   };
 
   // Returns whether the Topics API is allowed at all. If false, Topics API
@@ -188,6 +192,11 @@
   // Virtual to allow mocking in tests.
   virtual bool IsPrivacySandboxRestricted() const = 0;
 
+  // Returns whether the privacy sandbox restricted notice should be shown,
+  // based on account characteristics. Forwards to the delegate. Virtual for
+  // mocking in tests.
+  virtual bool IsSubjectToM1NoticeRestricted() const = 0;
+
   // Returns whether the Privacy Sandbox is partially enabled based on
   // restrictions.
   virtual bool IsRestrictedNoticeEnabled() const = 0;
diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc b/components/privacy_sandbox/privacy_sandbox_settings_impl.cc
index dd53303..207098fe 100644
--- a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc
+++ b/components/privacy_sandbox/privacy_sandbox_settings_impl.cc
@@ -519,6 +519,10 @@
   return delegate_->IsPrivacySandboxRestricted();
 }
 
+bool PrivacySandboxSettingsImpl::IsSubjectToM1NoticeRestricted() const {
+  return delegate_->IsSubjectToM1NoticeRestricted();
+}
+
 bool PrivacySandboxSettingsImpl::IsRestrictedNoticeEnabled() const {
   return privacy_sandbox::kPrivacySandboxSettings4RestrictedNotice.Get();
 }
diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.h b/components/privacy_sandbox/privacy_sandbox_settings_impl.h
index 3d13077a..76aa13d6 100644
--- a/components/privacy_sandbox/privacy_sandbox_settings_impl.h
+++ b/components/privacy_sandbox/privacy_sandbox_settings_impl.h
@@ -73,6 +73,7 @@
   void SetTopicsBlockedForTesting() override;
   void SetPrivacySandboxEnabled(bool enabled) override;
   bool IsPrivacySandboxRestricted() const override;
+  bool IsSubjectToM1NoticeRestricted() const override;
   bool IsRestrictedNoticeEnabled() const override;
   void OnCookiesCleared() override;
   void AddObserver(Observer* observer) override;
diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc b/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc
index bea7eb6..b1326ec4 100644
--- a/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc
+++ b/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc
@@ -1023,6 +1023,19 @@
   EXPECT_FALSE(privacy_sandbox_settings()->IsPrivacySandboxEnabled());
 }
 
+TEST_F(PrivacySandboxSettingsMockDelegateTest, IsSubjectToM1NoticeRestricted) {
+  // The settings should return the decision made by the delegate.
+  EXPECT_CALL(*mock_delegate(), IsSubjectToM1NoticeRestricted())
+      .Times(1)
+      .WillOnce(testing::Return(true));
+  EXPECT_TRUE(privacy_sandbox_settings()->IsSubjectToM1NoticeRestricted());
+
+  EXPECT_CALL(*mock_delegate(), IsSubjectToM1NoticeRestricted())
+      .Times(1)
+      .WillOnce(testing::Return(false));
+  EXPECT_FALSE(privacy_sandbox_settings()->IsSubjectToM1NoticeRestricted());
+}
+
 class PrivacySandboxSettingLocalOverrideTest
     : public PrivacySandboxSettingsTest {
   void InitializeFeaturesBeforeStart() override {
diff --git a/components/privacy_sandbox/privacy_sandbox_test_util.h b/components/privacy_sandbox/privacy_sandbox_test_util.h
index caed6f83..a305cc2 100644
--- a/components/privacy_sandbox/privacy_sandbox_test_util.h
+++ b/components/privacy_sandbox/privacy_sandbox_test_util.h
@@ -76,6 +76,7 @@
   MOCK_METHOD(bool, IsPrivacySandboxRestricted, (), (const, override));
   MOCK_METHOD(bool, IsIncognitoProfile, (), (const, override));
   MOCK_METHOD(bool, HasAppropriateTopicsConsent, (), (const, override));
+  MOCK_METHOD(bool, IsSubjectToM1NoticeRestricted, (), (const, override));
 };
 
 // A declarative test case is a collection of key value pairs, which each define
diff --git a/components/safe_browsing/core/browser/hashprefix_realtime/ohttp_key_service.cc b/components/safe_browsing/core/browser/hashprefix_realtime/ohttp_key_service.cc
index 159a6f2..874e49a 100644
--- a/components/safe_browsing/core/browser/hashprefix_realtime/ohttp_key_service.cc
+++ b/components/safe_browsing/core/browser/hashprefix_realtime/ohttp_key_service.cc
@@ -9,6 +9,7 @@
 #include "base/rand_util.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/core/browser/utils/backoff_operator.h"
+#include "components/safe_browsing/core/common/features.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "components/safe_browsing/core/common/utils.h"
 #include "net/base/net_errors.h"
@@ -100,6 +101,20 @@
       "default."
   )");
 
+bool IsEnabled(const PrefService& pref_service) {
+  safe_browsing::SafeBrowsingState state =
+      safe_browsing::GetSafeBrowsingState(pref_service);
+  return (state == safe_browsing::SafeBrowsingState::STANDARD_PROTECTION &&
+          !base::FeatureList::IsEnabled(
+              safe_browsing::kSafeBrowsingLookupMechanismExperiment)) ||
+         // The service is enabled when enhanced protection and lookup mechanism
+         // experiment are both enabled, because Chrome needs to send HPRT
+         // requests to conduct the experiment.
+         (state == safe_browsing::SafeBrowsingState::ENHANCED_PROTECTION &&
+          base::FeatureList::IsEnabled(
+              safe_browsing::kSafeBrowsingLookupMechanismExperiment));
+}
+
 }  // namespace
 
 namespace safe_browsing {
@@ -132,15 +147,13 @@
       base::BindRepeating(&OhttpKeyService::OnSafeBrowsingStateChanged,
                           weak_factory_.GetWeakPtr()));
 
-  SetEnabled(GetSafeBrowsingState(*pref_service_) ==
-             SafeBrowsingState::STANDARD_PROTECTION);
+  SetEnabled(IsEnabled(*pref_service_));
 }
 
 OhttpKeyService::~OhttpKeyService() = default;
 
 void OhttpKeyService::OnSafeBrowsingStateChanged() {
-  SetEnabled(GetSafeBrowsingState(*pref_service_) ==
-             SafeBrowsingState::STANDARD_PROTECTION);
+  SetEnabled(IsEnabled(*pref_service_));
 }
 
 void OhttpKeyService::SetEnabled(bool enable) {
diff --git a/components/safe_browsing/core/browser/hashprefix_realtime/ohttp_key_service_unittest.cc b/components/safe_browsing/core/browser/hashprefix_realtime/ohttp_key_service_unittest.cc
index b613e2a..a02a5d8 100644
--- a/components/safe_browsing/core/browser/hashprefix_realtime/ohttp_key_service_unittest.cc
+++ b/components/safe_browsing/core/browser/hashprefix_realtime/ohttp_key_service_unittest.cc
@@ -8,10 +8,12 @@
 
 #include "base/test/bind.h"
 #include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
+#include "components/safe_browsing/core/common/features.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -45,6 +47,10 @@
 
 class OhttpKeyServiceTest : public ::testing::Test {
  public:
+  OhttpKeyServiceTest() {
+    feature_list_.InitAndDisableFeature(kSafeBrowsingLookupMechanismExperiment);
+  }
+
   void SetUp() override {
     RegisterProfilePrefs(pref_service_.registry());
     test_url_loader_factory_ =
@@ -90,6 +96,7 @@
               expected_key_value);
   }
 
+  base::test::ScopedFeatureList feature_list_;
   base::test::TaskEnvironment task_environment_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
   std::unique_ptr<OhttpKeyService> ohttp_key_service_;
@@ -441,4 +448,35 @@
   task_environment_.RunUntilIdle();
 }
 
+class OhttpKeyServiceLookupMechnismEnabledTest : public OhttpKeyServiceTest {
+ public:
+  OhttpKeyServiceLookupMechnismEnabledTest() {
+    feature_list_.InitAndEnableFeature(kSafeBrowsingLookupMechanismExperiment);
+  }
+
+ protected:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+TEST_F(OhttpKeyServiceLookupMechnismEnabledTest, AsyncFetch_PrefChanges) {
+  SetupSuccessResponse();
+
+  SetSafeBrowsingState(&pref_service_, SafeBrowsingState::ENHANCED_PROTECTION);
+  task_environment_.RunUntilIdle();
+  auto original_expiration = base::Time::Now() + base::Days(7);
+  // New key should be fetched because the service is enabled when enhanced
+  // protection and the lookup mechanism experiment are both enabled.
+  EXPECT_EQ(ohttp_key_service_->get_ohttp_key_for_testing()->expiration,
+            original_expiration);
+
+  SetSafeBrowsingState(&pref_service_, SafeBrowsingState::STANDARD_PROTECTION);
+  task_environment_.FastForwardBy(base::Days(6));
+  task_environment_.RunUntilIdle();
+
+  // The expiration is not extended because the service is disabled when
+  // standard protection and the experiment are both enabled.
+  EXPECT_EQ(ohttp_key_service_->get_ohttp_key_for_testing()->expiration,
+            original_expiration);
+}
+
 }  // namespace safe_browsing
diff --git a/components/signin/public/identity_manager/account_capabilities_test_mutator.cc b/components/signin/public/identity_manager/account_capabilities_test_mutator.cc
index fcae986f..bc24895 100644
--- a/components/signin/public/identity_manager/account_capabilities_test_mutator.cc
+++ b/components/signin/public/identity_manager/account_capabilities_test_mutator.cc
@@ -36,6 +36,18 @@
       value;
 }
 
+void AccountCapabilitiesTestMutator::
+    set_is_subject_to_chrome_privacy_sandbox_restricted_measurement_notice(
+        bool value) {
+  // TODO(crbug.com/1430845): once the actual server-defined value is used,
+  // remove this override.
+  capabilities_
+      ->capabilities_map_[kCanRunChromePrivacySandboxTrialsCapabilityName] =
+      !value;
+  capabilities_->capabilities_map_[kIsSubjectToParentalControlsCapabilityName] =
+      !value;
+}
+
 void AccountCapabilitiesTestMutator::set_can_stop_parental_supervision(
     bool value) {
   capabilities_->capabilities_map_[kCanStopParentalSupervisionCapabilityName] =
diff --git a/components/signin/public/identity_manager/account_capabilities_test_mutator.h b/components/signin/public/identity_manager/account_capabilities_test_mutator.h
index 0de584f..c4c893118 100644
--- a/components/signin/public/identity_manager/account_capabilities_test_mutator.h
+++ b/components/signin/public/identity_manager/account_capabilities_test_mutator.h
@@ -25,6 +25,8 @@
   void set_can_stop_parental_supervision(bool value);
   void set_can_toggle_auto_updates(bool value);
   void set_is_allowed_for_machine_learning(bool value);
+  void set_is_subject_to_chrome_privacy_sandbox_restricted_measurement_notice(
+      bool value);
   void set_is_subject_to_enterprise_policies(bool value);
   void set_is_subject_to_parental_controls(bool value);
 
diff --git a/components/supervised_user/core/browser/web_content_handler.cc b/components/supervised_user/core/browser/web_content_handler.cc
index ed14fe8..1f730253 100644
--- a/components/supervised_user/core/browser/web_content_handler.cc
+++ b/components/supervised_user/core/browser/web_content_handler.cc
@@ -45,6 +45,8 @@
 
 namespace supervised_user {
 
+WebContentHandler::WebContentHandler() = default;
+
 WebContentHandler::~WebContentHandler() = default;
 
 void WebContentHandler::OnLocalApprovalRequestCompleted(
diff --git a/components/supervised_user/core/browser/web_content_handler.h b/components/supervised_user/core/browser/web_content_handler.h
index 558be42..3dec612 100644
--- a/components/supervised_user/core/browser/web_content_handler.h
+++ b/components/supervised_user/core/browser/web_content_handler.h
@@ -66,10 +66,19 @@
   // TODO(b/276428131): Remove when local approvals is fully launched.
   virtual void ShowFeedback(GURL url, std::u16string reason) = 0;
 
+  // Goes back to main frame if we are on a subframe.
+  // The action applies when localWebApprovalsEnabled is disabled.
+  virtual void GoBack() = 0;
+
+  // Returns the interstitial navigation id.
+  virtual int64_t GetInterstitialNavigationId() const = 0;
+
   static const char* GetLocalApprovalDurationMillisecondsHistogram();
   static const char* GetLocalApprovalResultHistogram();
 
  protected:
+  WebContentHandler();
+
   // Processes the outcome of the local approval request.
   // Should be called by platform specific completion callback.
   // TODO(b/278079069): Refactor and convert the class to an interface.
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc
index 3b2ecd888..2c4c84b 100644
--- a/components/sync/base/sync_prefs.cc
+++ b/components/sync/base/sync_prefs.cc
@@ -138,10 +138,9 @@
   for (UserSelectableType type : UserSelectableTypeSet::All()) {
     const char* pref_name = GetPrefNameForType(type);
     DCHECK(pref_name);
-    // If the preference is managed, |sync_all_types| is ignored for this
-    // preference.
+    // If the type is managed, |sync_all_types| is ignored for this type.
     if (pref_service_->GetBoolean(pref_name) ||
-        (sync_all_types && !pref_service_->IsManagedPreference(pref_name))) {
+        (sync_all_types && !IsTypeManagedByPolicy(type))) {
       selected_types.Put(type);
     }
   }
@@ -149,6 +148,12 @@
   return selected_types;
 }
 
+bool SyncPrefs::IsTypeManagedByPolicy(UserSelectableType type) const {
+  const char* pref_name = GetPrefNameForType(type);
+  CHECK(pref_name);
+  return pref_service_->IsManagedPreference(pref_name);
+}
+
 void SyncPrefs::SetSelectedTypes(bool keep_everything_synced,
                                  UserSelectableTypeSet registered_types,
                                  UserSelectableTypeSet selected_types) {
@@ -180,16 +185,21 @@
   for (UserSelectableOsType type : UserSelectableOsTypeSet::All()) {
     const char* pref_name = GetPrefNameForOsType(type);
     DCHECK(pref_name);
-    // If the preference is managed, |sync_all_os_types| is ignored for this
-    // preference.
+    // If the type is managed, |sync_all_os_types| is ignored for this type.
     if (pref_service_->GetBoolean(pref_name) ||
-        (sync_all_os_types && !pref_service_->IsManagedPreference(pref_name))) {
+        (sync_all_os_types && !IsOsTypeManagedByPolicy(type))) {
       selected_types.Put(type);
     }
   }
   return selected_types;
 }
 
+bool SyncPrefs::IsOsTypeManagedByPolicy(UserSelectableOsType type) const {
+  const char* pref_name = GetPrefNameForOsType(type);
+  CHECK(pref_name);
+  return pref_service_->IsManagedPreference(pref_name);
+}
+
 void SyncPrefs::SetSelectedOsTypes(bool sync_all_os_types,
                                    UserSelectableOsTypeSet registered_types,
                                    UserSelectableOsTypeSet selected_types) {
diff --git a/components/sync/base/sync_prefs.h b/components/sync/base/sync_prefs.h
index 002cbb4b..f4ee33f 100644
--- a/components/sync/base/sync_prefs.h
+++ b/components/sync/base/sync_prefs.h
@@ -69,11 +69,17 @@
   void SetSyncRequested(bool is_requested);
   bool IsSyncRequestedSetExplicitly() const;
 
+  // Whether the "Sync everything" toggle is enabled. Note that even if this is
+  // true, some types may be disabled e.g. due to enterprise policy.
   bool HasKeepEverythingSynced() const;
 
-  // Returns UserSelectableTypeSet::All() if HasKeepEverythingSynced() is true.
+  // Returns UserSelectableTypeSet::All() if HasKeepEverythingSynced() is true
+  // (except if some types are force-disabled by policy).
   UserSelectableTypeSet GetSelectedTypes() const;
 
+  // Returns whether `type` is "managed" i.e. controlled by enterprise policy.
+  bool IsTypeManagedByPolicy(UserSelectableType type) const;
+
   // Sets the selection state for all |registered_types| and "keep everything
   // synced" flag.
   // |keep_everything_synced| indicates that all current and future types
@@ -92,6 +98,7 @@
   // including a separate "Sync All" toggle for OS types.
   bool IsSyncAllOsTypesEnabled() const;
   UserSelectableOsTypeSet GetSelectedOsTypes() const;
+  bool IsOsTypeManagedByPolicy(UserSelectableOsType type) const;
   void SetSelectedOsTypes(bool sync_all_os_types,
                           UserSelectableOsTypeSet registered_types,
                           UserSelectableOsTypeSet selected_types);
diff --git a/components/sync/driver/sync_user_settings.h b/components/sync/driver/sync_user_settings.h
index 346189b..91d79afb 100644
--- a/components/sync/driver/sync_user_settings.h
+++ b/components/sync/driver/sync_user_settings.h
@@ -50,6 +50,7 @@
   // has never enabled Sync, or if only Sync-the-transport is running.
   virtual bool IsSyncEverythingEnabled() const = 0;
   virtual UserSelectableTypeSet GetSelectedTypes() const = 0;
+  virtual bool IsTypeManagedByPolicy(UserSelectableType type) const = 0;
   virtual void SetSelectedTypes(bool sync_everything,
                                 UserSelectableTypeSet types) = 0;
   // Registered user selectable types are derived from registered model types.
@@ -61,6 +62,7 @@
   // toggles in the OS Settings UI.
   virtual bool IsSyncAllOsTypesEnabled() const = 0;
   virtual UserSelectableOsTypeSet GetSelectedOsTypes() const = 0;
+  virtual bool IsOsTypeManagedByPolicy(UserSelectableOsType type) const = 0;
   virtual void SetSelectedOsTypes(bool sync_all_os_types,
                                   UserSelectableOsTypeSet types) = 0;
   virtual UserSelectableOsTypeSet GetRegisteredSelectableOsTypes() const = 0;
diff --git a/components/sync/driver/sync_user_settings_impl.cc b/components/sync/driver/sync_user_settings_impl.cc
index 845d2d6..d3366d40 100644
--- a/components/sync/driver/sync_user_settings_impl.cc
+++ b/components/sync/driver/sync_user_settings_impl.cc
@@ -105,6 +105,11 @@
   return types;
 }
 
+bool SyncUserSettingsImpl::IsTypeManagedByPolicy(
+    UserSelectableType type) const {
+  return prefs_->IsTypeManagedByPolicy(type);
+}
+
 void SyncUserSettingsImpl::SetSelectedTypes(bool sync_everything,
                                             UserSelectableTypeSet types) {
   UserSelectableTypeSet registered_types = GetRegisteredSelectableTypes();
@@ -138,6 +143,11 @@
   return types;
 }
 
+bool SyncUserSettingsImpl::IsOsTypeManagedByPolicy(
+    UserSelectableOsType type) const {
+  return prefs_->IsOsTypeManagedByPolicy(type);
+}
+
 void SyncUserSettingsImpl::SetSelectedOsTypes(bool sync_all_os_types,
                                               UserSelectableOsTypeSet types) {
   UserSelectableOsTypeSet registered_types = GetRegisteredSelectableOsTypes();
diff --git a/components/sync/driver/sync_user_settings_impl.h b/components/sync/driver/sync_user_settings_impl.h
index 75919c34..6d72132c 100644
--- a/components/sync/driver/sync_user_settings_impl.h
+++ b/components/sync/driver/sync_user_settings_impl.h
@@ -37,12 +37,14 @@
   void SetFirstSetupComplete(SyncFirstSetupCompleteSource source) override;
   bool IsSyncEverythingEnabled() const override;
   UserSelectableTypeSet GetSelectedTypes() const override;
+  bool IsTypeManagedByPolicy(UserSelectableType type) const override;
   void SetSelectedTypes(bool sync_everything,
                         UserSelectableTypeSet types) override;
   UserSelectableTypeSet GetRegisteredSelectableTypes() const override;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   bool IsSyncAllOsTypesEnabled() const override;
   UserSelectableOsTypeSet GetSelectedOsTypes() const override;
+  bool IsOsTypeManagedByPolicy(UserSelectableOsType type) const override;
   void SetSelectedOsTypes(bool sync_all_os_types,
                           UserSelectableOsTypeSet types) override;
   UserSelectableOsTypeSet GetRegisteredSelectableOsTypes() const override;
diff --git a/components/sync/test/sync_user_settings_mock.h b/components/sync/test/sync_user_settings_mock.h
index 0c2e7a1..be0b4744 100644
--- a/components/sync/test/sync_user_settings_mock.h
+++ b/components/sync/test/sync_user_settings_mock.h
@@ -26,6 +26,10 @@
               (override));
   MOCK_METHOD(bool, IsSyncEverythingEnabled, (), (const override));
   MOCK_METHOD(UserSelectableTypeSet, GetSelectedTypes, (), (const override));
+  MOCK_METHOD(bool,
+              IsTypeManagedByPolicy,
+              (UserSelectableType),
+              (const override));
   MOCK_METHOD(void,
               SetSelectedTypes,
               (bool, UserSelectableTypeSet),
@@ -41,6 +45,10 @@
               GetSelectedOsTypes,
               (),
               (const override));
+  MOCK_METHOD(bool,
+              IsOsTypeManagedByPolicy,
+              (UserSelectableOsType),
+              (const override));
   MOCK_METHOD(void,
               SetSelectedOsTypes,
               (bool, UserSelectableOsTypeSet),
diff --git a/components/sync/test/test_sync_user_settings.cc b/components/sync/test/test_sync_user_settings.cc
index 3ab537f..211b304 100644
--- a/components/sync/test/test_sync_user_settings.cc
+++ b/components/sync/test/test_sync_user_settings.cc
@@ -75,6 +75,11 @@
   return selected_types_;
 }
 
+bool TestSyncUserSettings::IsTypeManagedByPolicy(
+    UserSelectableType type) const {
+  return false;
+}
+
 ModelTypeSet TestSyncUserSettings::GetPreferredDataTypes() const {
   ModelTypeSet types = UserSelectableTypesToModelTypes(GetSelectedTypes());
   types.PutAll(AlwaysPreferredUserTypes());
@@ -100,6 +105,11 @@
   return selected_os_types_;
 }
 
+bool TestSyncUserSettings::IsOsTypeManagedByPolicy(
+    UserSelectableOsType type) const {
+  return false;
+}
+
 void TestSyncUserSettings::SetSelectedOsTypes(bool sync_all_os_types,
                                               UserSelectableOsTypeSet types) {
   sync_all_os_types_enabled_ = sync_all_os_types;
diff --git a/components/sync/test/test_sync_user_settings.h b/components/sync/test/test_sync_user_settings.h
index 77220119..3dc5795 100644
--- a/components/sync/test/test_sync_user_settings.h
+++ b/components/sync/test/test_sync_user_settings.h
@@ -30,6 +30,7 @@
 
   bool IsSyncEverythingEnabled() const override;
   UserSelectableTypeSet GetSelectedTypes() const override;
+  bool IsTypeManagedByPolicy(UserSelectableType type) const override;
   void SetSelectedTypes(bool sync_everything,
                         UserSelectableTypeSet types) override;
   ModelTypeSet GetPreferredDataTypes() const;
@@ -38,6 +39,7 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   bool IsSyncAllOsTypesEnabled() const override;
   UserSelectableOsTypeSet GetSelectedOsTypes() const override;
+  bool IsOsTypeManagedByPolicy(UserSelectableOsType type) const override;
   void SetSelectedOsTypes(bool sync_all_os_types,
                           UserSelectableOsTypeSet types) override;
   UserSelectableOsTypeSet GetRegisteredSelectableOsTypes() const override;
diff --git a/components/update_client/component.cc b/components/update_client/component.cc
index 4f4fb8f8..6558c3a 100644
--- a/components/update_client/component.cc
+++ b/components/update_client/component.cc
@@ -1180,8 +1180,6 @@
 #if BUILDFLAG(ENABLE_PUFFIN_PATCHES)
   // TODO(crbug.com/1349060) once Puffin patches are fully implemented,
   // we should remove this #if.
-  VLOG(1) << "Diff Updating.. prev fp: " << component.previous_fp_
-          << " Next fp: " << component.next_fp_;
   if (!update_context.crx_cache_.has_value()) {
     main_task_runner->PostTask(
         FROM_HERE,
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index f103049c..aedd85d 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1728,6 +1728,7 @@
     "renderer_host/isolated_web_app_throttle.h",
     "renderer_host/keep_alive_handle_factory.cc",
     "renderer_host/keep_alive_handle_factory.h",
+    "renderer_host/loading_state.h",
     "renderer_host/local_network_access_util.cc",
     "renderer_host/local_network_access_util.h",
     "renderer_host/media/aec_dump_manager_impl.cc",
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
index 901b63d..b7051d28 100644
--- a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
+++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
@@ -817,24 +817,24 @@
       source_type = SourceType::kEvent;
     }
 
-    base::expected<StorableSource, SourceRegistrationError> source =
-        base::unexpected(SourceRegistrationError::kInvalidJson);
-    if (result.has_value()) {
-      if (result->is_dict()) {
-        auto registration = attribution_reporting::SourceRegistration::Parse(
-            std::move(*result).TakeDict());
-        if (registration.has_value()) {
-          source.emplace(
-              pending_decode.reporting_origin, std::move(*registration),
-              /*source_time=*/base::Time::Now(), registrations->source_origin(),
-              source_type, registrations->is_within_fenced_frame());
-        } else {
-          source = base::unexpected(registration.error());
-        }
-      } else {
-        source = base::unexpected(SourceRegistrationError::kRootWrongType);
+    auto source =
+        [&]() -> base::expected<StorableSource, SourceRegistrationError> {
+      if (!result.has_value()) {
+        return base::unexpected(SourceRegistrationError::kInvalidJson);
       }
-    }
+      if (!result->is_dict()) {
+        return base::unexpected(SourceRegistrationError::kRootWrongType);
+      }
+      auto registration = attribution_reporting::SourceRegistration::Parse(
+          std::move(*result).TakeDict());
+      if (!registration.has_value()) {
+        return base::unexpected(registration.error());
+      }
+      return StorableSource(
+          pending_decode.reporting_origin, std::move(*registration),
+          /*source_time=*/base::Time::Now(), registrations->source_origin(),
+          source_type, registrations->is_within_fenced_frame());
+    }();
 
     if (source.has_value()) {
       attribution_manager_->HandleSource(std::move(*source),
diff --git a/content/browser/buckets/bucket_host.cc b/content/browser/buckets/bucket_host.cc
index 1282527..bdded35f 100644
--- a/content/browser/buckets/bucket_host.cc
+++ b/content/browser/buckets/bucket_host.cc
@@ -214,14 +214,8 @@
     storage::QuotaErrorOr<storage::BucketInfo> bucket_info) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (!bucket_info.has_value()) {
-    bucket_info_ = {};
-    std::move(callback).Run(false);
-    return;
-  }
-
-  bucket_info_ = bucket_info.value();
-  std::move(callback).Run(true);
+  bucket_info_ = bucket_info.value_or(storage::BucketInfo());
+  std::move(callback).Run(bucket_info.has_value());
 }
 
 void BucketHost::DidGetUsageAndQuota(EstimateCallback callback,
diff --git a/content/browser/buckets/bucket_manager_host.cc b/content/browser/buckets/bucket_manager_host.cc
index 2695629..f3832dd 100644
--- a/content/browser/buckets/bucket_manager_host.cc
+++ b/content/browser/buckets/bucket_manager_host.cc
@@ -7,6 +7,7 @@
 #include "base/containers/contains.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/ranges/algorithm.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/types/pass_key.h"
 #include "components/services/storage/public/cpp/buckets/bucket_info.h"
@@ -200,8 +201,7 @@
         case storage::QuotaError::kNone:
         case storage::QuotaError::kEntryExistsError:
         case storage::QuotaError::kFileOperationError:
-          NOTREACHED();
-          ABSL_FALLTHROUGH_INTENDED;
+          NOTREACHED_NORETURN();
         case storage::QuotaError::kNotFound:
         case storage::QuotaError::kDatabaseError:
         case storage::QuotaError::kUnknownError:
@@ -228,20 +228,13 @@
 void BucketManagerHost::DidGetBuckets(
     KeysCallback callback,
     storage::QuotaErrorOr<std::set<storage::BucketInfo>> buckets) {
-  if (!buckets.has_value()) {
-    std::move(callback).Run({}, false);
-    return;
-  }
-
   std::vector<std::string> keys;
-  for (auto& bucket : buckets.value()) {
+  for (const auto& bucket : buckets.value_or(std::set<storage::BucketInfo>())) {
     if (!bucket.is_default()) {
-      keys.push_back(bucket.name);
+      keys.insert(base::ranges::upper_bound(keys, bucket.name), bucket.name);
     }
   }
-  std::sort(keys.begin(), keys.end());
-
-  std::move(callback).Run(keys, true);
+  std::move(callback).Run(keys, buckets.has_value());
 }
 
 void BucketManagerHost::DidDeleteBucket(const std::string& bucket_name,
diff --git a/content/browser/devtools/network_service_devtools_observer.cc b/content/browser/devtools/network_service_devtools_observer.cc
index 5960e61f..818d836 100644
--- a/content/browser/devtools/network_service_devtools_observer.cc
+++ b/content/browser/devtools/network_service_devtools_observer.cc
@@ -206,21 +206,15 @@
 
   // TODO(https://crbug.com/1268378): Remove this once enforcement is always
   // enabled and warnings are no more.
-  if (is_warning) {
-    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
-        rfhi,
-        blink::mojom::WebFeature::kPrivateNetworkAccessIgnoredPreflightError);
-
-    if (initiator_origin.has_value() &&
-        !initiator_origin->IsSameOriginWith(url)) {
+  if (is_warning && initiator_origin.has_value()) {
+    if (!initiator_origin->IsSameOriginWith(url)) {
       GetContentClient()->browser()->LogWebFeatureForCurrentPage(
           rfhi, blink::mojom::WebFeature::
                     kPrivateNetworkAccessIgnoredCrossOriginPreflightError);
     }
 
-    if (initiator_origin.has_value() &&
-        net::SchemefulSite(initiator_origin.value()) !=
-            net::SchemefulSite(url)) {
+    if (net::SchemefulSite(initiator_origin.value()) !=
+        net::SchemefulSite(url)) {
       GetContentClient()->browser()->LogWebFeatureForCurrentPage(
           rfhi, blink::mojom::WebFeature::
                     kPrivateNetworkAccessIgnoredCrossSitePreflightError);
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index c7d0baa..c152b26 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -735,7 +735,7 @@
   }
   if (status.HasExclusionReason(
           net::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)) {
-    if (status.HasDowngradeWarning()) {
+    if (status.HasSchemefulDowngradeWarning()) {
       blockedReasons->push_back(
           Network::SetCookieBlockedReasonEnum::SchemefulSameSiteStrict);
     } else {
@@ -745,7 +745,7 @@
   }
   if (status.HasExclusionReason(
           net::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)) {
-    if (status.HasDowngradeWarning()) {
+    if (status.HasSchemefulDowngradeWarning()) {
       blockedReasons->push_back(
           Network::SetCookieBlockedReasonEnum::SchemefulSameSiteLax);
     } else {
@@ -756,7 +756,7 @@
   if (status.HasExclusionReason(
           net::CookieInclusionStatus::
               EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX)) {
-    if (status.HasDowngradeWarning()) {
+    if (status.HasSchemefulDowngradeWarning()) {
       blockedReasons->push_back(Network::SetCookieBlockedReasonEnum::
                                     SchemefulSameSiteUnspecifiedTreatedAsLax);
     } else {
@@ -847,7 +847,7 @@
   }
   if (status.HasExclusionReason(
           net::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)) {
-    if (status.HasDowngradeWarning()) {
+    if (status.HasSchemefulDowngradeWarning()) {
       blockedReasons->push_back(
           Network::CookieBlockedReasonEnum::SchemefulSameSiteStrict);
     } else {
@@ -857,7 +857,7 @@
   }
   if (status.HasExclusionReason(
           net::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)) {
-    if (status.HasDowngradeWarning()) {
+    if (status.HasSchemefulDowngradeWarning()) {
       blockedReasons->push_back(
           Network::CookieBlockedReasonEnum::SchemefulSameSiteLax);
     } else {
@@ -867,7 +867,7 @@
   if (status.HasExclusionReason(
           net::CookieInclusionStatus::
               EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX)) {
-    if (status.HasDowngradeWarning()) {
+    if (status.HasSchemefulDowngradeWarning()) {
       blockedReasons->push_back(Network::CookieBlockedReasonEnum::
                                     SchemefulSameSiteUnspecifiedTreatedAsLax);
     } else {
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json
index a83d738..9335f39 100644
--- a/content/browser/devtools/protocol_config.json
+++ b/content/browser/devtools/protocol_config.json
@@ -99,7 +99,8 @@
             },
             {
                 "domain": "Storage",
-              "async": ["getUsageAndQuota", "clearDataForOrigin", "clearDataForStorageKey", "getCookies", "setCookies", "clearCookies", "overrideQuotaForOrigin", "getTrustTokens", "clearTrustTokens", "getInterestGroupDetails", "getSharedStorageMetadata", "getSharedStorageEntries", "setSharedStorageEntry", "deleteSharedStorageEntry", "clearSharedStorageEntries", "resetSharedStorageBudget", "getStorageBucketList"]
+                "exclude": ["runBounceTrackingMitigations"],
+                "async": ["getUsageAndQuota", "clearDataForOrigin", "clearDataForStorageKey", "getCookies", "setCookies", "clearCookies", "overrideQuotaForOrigin", "getTrustTokens", "clearTrustTokens", "getInterestGroupDetails", "getSharedStorageMetadata", "getSharedStorageEntries", "setSharedStorageEntry", "deleteSharedStorageEntry", "clearSharedStorageEntries", "resetSharedStorageBudget", "getStorageBucketList"]
             },
             {
                 "domain": "SystemInfo",
diff --git a/content/browser/fenced_frame/fenced_frame.h b/content/browser/fenced_frame/fenced_frame.h
index 0ffaf8c4..de7da47 100644
--- a/content/browser/fenced_frame/fenced_frame.h
+++ b/content/browser/fenced_frame/fenced_frame.h
@@ -61,8 +61,8 @@
   void DidChangeFramePolicy(const blink::FramePolicy& frame_policy) override;
 
   // FrameTree::Delegate.
-  void DidStartLoading(FrameTreeNode* frame_tree_node,
-                       bool should_show_loading_ui) override {}
+  void LoadingStateChanged(LoadingState new_state) override {}
+  void DidStartLoading(FrameTreeNode* frame_tree_node) override {}
   void DidStopLoading() override {}
   bool IsHidden() override;
   int GetOuterDelegateFrameTreeNodeId() override;
diff --git a/content/browser/fenced_frame/fenced_frame_config.cc b/content/browser/fenced_frame/fenced_frame_config.cc
index d2d6530..6f8cedc 100644
--- a/content/browser/fenced_frame/fenced_frame_config.cc
+++ b/content/browser/fenced_frame/fenced_frame_config.cc
@@ -297,10 +297,10 @@
 
 void FencedFrameProperties::UpdateAutomaticBeaconData(
     const std::string& event_data,
-    const std::vector<blink::FencedFrame::ReportingDestination>& destination) {
+    const std::vector<blink::FencedFrame::ReportingDestination>& destinations) {
   // For an ad component, the event data from its automatic beacon is ignored.
   automatic_beacon_info_.emplace(is_ad_component_ ? std::string{} : event_data,
-                                 destination);
+                                 destinations);
 }
 
 }  // namespace content
diff --git a/content/browser/fenced_frame/fenced_frame_config.h b/content/browser/fenced_frame/fenced_frame_config.h
index 7d79dbf..45ddc474 100644
--- a/content/browser/fenced_frame/fenced_frame_config.h
+++ b/content/browser/fenced_frame/fenced_frame_config.h
@@ -97,7 +97,8 @@
 struct CONTENT_EXPORT AutomaticBeaconInfo {
   AutomaticBeaconInfo(
       const std::string& data,
-      const std::vector<blink::FencedFrame::ReportingDestination>& destination);
+      const std::vector<blink::FencedFrame::ReportingDestination>&
+          destinations);
 
   AutomaticBeaconInfo(const AutomaticBeaconInfo&);
   AutomaticBeaconInfo(AutomaticBeaconInfo&&);
@@ -108,7 +109,7 @@
   ~AutomaticBeaconInfo();
 
   std::string data;
-  std::vector<blink::FencedFrame::ReportingDestination> destination;
+  std::vector<blink::FencedFrame::ReportingDestination> destinations;
 };
 
 // Different kinds of entities (renderers) that should receive different
@@ -348,7 +349,8 @@
   // `reserved.top_navigation` automatic beacon.
   void UpdateAutomaticBeaconData(
       const std::string& event_data,
-      const std::vector<blink::FencedFrame::ReportingDestination>& destination);
+      const std::vector<blink::FencedFrame::ReportingDestination>&
+          destinations);
 
   const absl::optional<AutomaticBeaconInfo>& automatic_beacon_info() const {
     return automatic_beacon_info_;
diff --git a/content/browser/fenced_frame/fenced_frame_reporter.cc b/content/browser/fenced_frame/fenced_frame_reporter.cc
index 943acc4..f8bdc1d 100644
--- a/content/browser/fenced_frame/fenced_frame_reporter.cc
+++ b/content/browser/fenced_frame/fenced_frame_reporter.cc
@@ -120,8 +120,8 @@
 
 AutomaticBeaconInfo::AutomaticBeaconInfo(
     const std::string& data,
-    const std::vector<blink::FencedFrame::ReportingDestination>& destination)
-    : data(data), destination(destination) {}
+    const std::vector<blink::FencedFrame::ReportingDestination>& destinations)
+    : data(data), destinations(destinations) {}
 
 AutomaticBeaconInfo::AutomaticBeaconInfo(const AutomaticBeaconInfo&) = default;
 
diff --git a/content/browser/fenced_frame/fenced_frame_url_mapping.cc b/content/browser/fenced_frame/fenced_frame_url_mapping.cc
index 4072d5c..f6190b8 100644
--- a/content/browser/fenced_frame/fenced_frame_url_mapping.cc
+++ b/content/browser/fenced_frame/fenced_frame_url_mapping.cc
@@ -17,6 +17,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/fenced_frame/fenced_frame_utils.h"
 #include "third_party/blink/public/common/interest_group/ad_display_size.h"
+#include "third_party/blink/public/common/interest_group/ad_display_size_utils.h"
 #include "ui/display/screen.h"
 #include "url/gurl.h"
 
@@ -186,6 +187,7 @@
 blink::FencedFrame::RedactedFencedFrameConfig
 FencedFrameURLMapping::AssignFencedFrameURLAndInterestGroupInfo(
     const GURL& urn_uuid,
+    absl::optional<blink::AdSize> container_size,
     const blink::AdDescriptor& ad_descriptor,
     AdAuctionData ad_auction_data,
     base::RepeatingClosure on_navigate_callback,
@@ -213,6 +215,13 @@
   config.mapped_url_.emplace(SubstituteSizeIntoURL(ad_descriptor),
                              VisibilityToEmbedder::kOpaque,
                              VisibilityToContent::kTransparent);
+  if (container_size.has_value() &&
+      blink::IsValidAdSize(container_size.value())) {
+    gfx::Size container_gfx_size = AdSizeToGfxSize(container_size.value());
+    config.container_size_.emplace(container_gfx_size,
+                                   VisibilityToEmbedder::kTransparent,
+                                   VisibilityToContent::kOpaque);
+  }
   if (ad_descriptor.size) {
     gfx::Size content_size = AdSizeToGfxSize(ad_descriptor.size.value());
     config.content_size_.emplace(content_size,
diff --git a/content/browser/fenced_frame/fenced_frame_url_mapping.h b/content/browser/fenced_frame/fenced_frame_url_mapping.h
index 2a76527..dc7e2b4d 100644
--- a/content/browser/fenced_frame/fenced_frame_url_mapping.h
+++ b/content/browser/fenced_frame/fenced_frame_url_mapping.h
@@ -24,6 +24,7 @@
 namespace blink {
 
 struct AdDescriptor;
+struct AdSize;
 
 }  // namespace blink
 
@@ -98,6 +99,7 @@
   blink::FencedFrame::RedactedFencedFrameConfig
   AssignFencedFrameURLAndInterestGroupInfo(
       const GURL& urn_uuid,
+      absl::optional<blink::AdSize> container_size,
       const blink::AdDescriptor& ad_descriptor,
       AdAuctionData auction_data,
       base::RepeatingClosure on_navigate_callback,
diff --git a/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc b/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc
index 69b6571..112175f7 100644
--- a/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc
+++ b/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc
@@ -285,7 +285,8 @@
         on_navigate_callback_invoked = true;
       });
   fenced_frame_url_mapping.AssignFencedFrameURLAndInterestGroupInfo(
-      urn_uuid, blink::AdDescriptor(top_level_url),
+      urn_uuid, /*container_size=*/absl::nullopt,
+      blink::AdDescriptor(top_level_url),
       {interest_group_owner, interest_group_name}, on_navigate_callback,
       ad_component_descriptors);
 
@@ -328,7 +329,8 @@
   auto urn_uuid = GenerateAndVerifyPendingMappedURN(&fenced_frame_url_mapping);
 
   fenced_frame_url_mapping.AssignFencedFrameURLAndInterestGroupInfo(
-      urn_uuid, blink::AdDescriptor(top_level_url),
+      urn_uuid, /*container_size=*/absl::nullopt,
+      blink::AdDescriptor(top_level_url),
       {interest_group_owner, interest_group_name},
       /*on_navigate_callback=*/base::RepeatingClosure(),
       ad_component_descriptors);
@@ -373,7 +375,8 @@
   auto urn_uuid = GenerateAndVerifyPendingMappedURN(&fenced_frame_url_mapping);
 
   fenced_frame_url_mapping.AssignFencedFrameURLAndInterestGroupInfo(
-      urn_uuid, blink::AdDescriptor(top_level_url),
+      urn_uuid, /*container_size=*/absl::nullopt,
+      blink::AdDescriptor(top_level_url),
       {interest_group_owner, interest_group_name},
       /*on_navigate_callback=*/base::RepeatingClosure(),
       ad_component_descriptors);
@@ -417,7 +420,8 @@
   auto urn_uuid = GenerateAndVerifyPendingMappedURN(&fenced_frame_url_mapping);
 
   fenced_frame_url_mapping.AssignFencedFrameURLAndInterestGroupInfo(
-      urn_uuid, blink::AdDescriptor(top_level_url),
+      urn_uuid, /*container_size=*/absl::nullopt,
+      blink::AdDescriptor(top_level_url),
       {interest_group_owner, interest_group_name},
       /*on_navigate_callback=*/base::RepeatingClosure(),
       ad_component_descriptors);
@@ -458,7 +462,8 @@
   auto urn_uuid = GenerateAndVerifyPendingMappedURN(&fenced_frame_url_mapping);
 
   fenced_frame_url_mapping.AssignFencedFrameURLAndInterestGroupInfo(
-      urn_uuid, blink::AdDescriptor(top_level_url),
+      urn_uuid, /*container_size=*/absl::nullopt,
+      blink::AdDescriptor(top_level_url),
       {interest_group_owner, interest_group_name},
       /*on_navigate_callback=*/base::RepeatingClosure(),
       ad_component_descriptors);
@@ -553,7 +558,8 @@
   auto urn_uuid = GenerateAndVerifyPendingMappedURN(&fenced_frame_url_mapping);
 
   fenced_frame_url_mapping.AssignFencedFrameURLAndInterestGroupInfo(
-      urn_uuid, blink::AdDescriptor(top_level_url),
+      urn_uuid, /*container_size=*/absl::nullopt,
+      blink::AdDescriptor(top_level_url),
       {interest_group_owner, interest_group_name},
       /*on_navigate_callback=*/base::RepeatingClosure(),
       ad_component_descriptors, fenced_frame_reporter);
diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc
index 84fc60d..afa27a0 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -1177,11 +1177,9 @@
   auto on_lookup_done = base::BindRepeating(
       [](Barrier barrier,
          storage::QuotaErrorOr<storage::BucketInfo> bucket_info) {
-        if (bucket_info.has_value()) {
-          barrier.Run(bucket_info->ToBucketLocator());
-        } else {
-          barrier.Run(absl::nullopt);
-        }
+        barrier.Run(bucket_info.has_value()
+                        ? absl::make_optional(bucket_info->ToBucketLocator())
+                        : absl::nullopt);
       },
       barrier);
 
diff --git a/content/browser/interest_group/ad_auction_service_impl.cc b/content/browser/interest_group/ad_auction_service_impl.cc
index fc142f2..cc0f393f 100644
--- a/content/browser/interest_group/ad_auction_service_impl.cc
+++ b/content/browser/interest_group/ad_auction_service_impl.cc
@@ -528,6 +528,7 @@
     AuctionRunner* auction,
     bool manually_aborted,
     absl::optional<blink::InterestGroupKey> winning_group_key,
+    absl::optional<blink::AdSize> requested_ad_size,
     absl::optional<blink::AdDescriptor> ad_descriptor,
     std::vector<blink::AdDescriptor> ad_component_descriptors,
     std::vector<std::string> errors,
@@ -599,9 +600,9 @@
 
   blink::FencedFrame::RedactedFencedFrameConfig config =
       current_fenced_frame_urls_map.AssignFencedFrameURLAndInterestGroupInfo(
-          urn_uuid, *ad_descriptor, std::move(ad_auction_data),
-          reporter->OnNavigateToWinningAdCallback(), ad_component_descriptors,
-          reporter->fenced_frame_reporter());
+          urn_uuid, requested_ad_size, *ad_descriptor,
+          std::move(ad_auction_data), reporter->OnNavigateToWinningAdCallback(),
+          ad_component_descriptors, reporter->fenced_frame_reporter());
   std::move(callback).Run(/*manually_aborted=*/false, std::move(config));
 
   // Start the InterestGroupAuctionReporter. It will run reporting scripts, but
diff --git a/content/browser/interest_group/ad_auction_service_impl.h b/content/browser/interest_group/ad_auction_service_impl.h
index 079e26a..e7fde20 100644
--- a/content/browser/interest_group/ad_auction_service_impl.h
+++ b/content/browser/interest_group/ad_auction_service_impl.h
@@ -126,6 +126,7 @@
       AuctionRunner* auction,
       bool manually_aborted,
       absl::optional<blink::InterestGroupKey> winning_group_key,
+      absl::optional<blink::AdSize> requested_ad_size,
       absl::optional<blink::AdDescriptor> ad_descriptor,
       std::vector<blink::AdDescriptor> ad_component_descriptors,
       std::vector<std::string> errors,
diff --git a/content/browser/interest_group/auction_runner.cc b/content/browser/interest_group/auction_runner.cc
index b88c09a..ae62d3b 100644
--- a/content/browser/interest_group/auction_runner.cc
+++ b/content/browser/interest_group/auction_runner.cc
@@ -302,6 +302,7 @@
   // types cannot be triggered anyway, so no need to pass it along.
   std::move(callback_).Run(this, manually_aborted,
                            /*winning_group_key=*/absl::nullopt,
+                           /*requested_ad_size=*/absl::nullopt,
                            /*ad_descriptor=*/absl::nullopt,
                            /*ad_component_descriptors=*/{},
                            auction_.TakeErrors(),
@@ -400,11 +401,11 @@
   DCHECK(reporter);
 
   state_ = State::kSucceeded;
-  std::move(callback_).Run(this, /*manually_aborted=*/false,
-                           std::move(winning_group_key),
-                           auction_.top_bid()->bid->ad_descriptor,
-                           auction_.top_bid()->bid->ad_component_descriptors,
-                           std::move(errors), std::move(reporter));
+  std::move(callback_).Run(
+      this, /*manually_aborted=*/false, std::move(winning_group_key),
+      auction_.RequestedAdSize(), auction_.top_bid()->bid->ad_descriptor,
+      auction_.top_bid()->bid->ad_component_descriptors, std::move(errors),
+      std::move(reporter));
 }
 
 void AuctionRunner::UpdateInterestGroupsPostAuction() {
diff --git a/content/browser/interest_group/auction_runner.h b/content/browser/interest_group/auction_runner.h
index 0414ac4..d00dd46 100644
--- a/content/browser/interest_group/auction_runner.h
+++ b/content/browser/interest_group/auction_runner.h
@@ -57,6 +57,9 @@
   //
   // `winning_group_id` owner and name of the winning interest group (if any).
   //
+  // `requested_ad_size` requested size for the ad auction (if any). Stored into
+  // the fenced frame config container size.
+  //
   // `ad_descriptor` URL of auction winning ad to render with optional
   // size. Null if there is no winner.
   //
@@ -73,6 +76,7 @@
       AuctionRunner* auction_runner,
       bool manually_aborted,
       absl::optional<blink::InterestGroupKey> winning_group_id,
+      absl::optional<blink::AdSize> requested_ad_size,
       absl::optional<blink::AdDescriptor> ad_descriptor,
       std::vector<blink::AdDescriptor> ad_component_descriptors,
       std::vector<std::string> errors,
diff --git a/content/browser/interest_group/auction_runner_unittest.cc b/content/browser/interest_group/auction_runner_unittest.cc
index 241a14e..c19edce7 100644
--- a/content/browser/interest_group/auction_runner_unittest.cc
+++ b/content/browser/interest_group/auction_runner_unittest.cc
@@ -1608,6 +1608,7 @@
       AuctionRunner* auction_runner,
       bool manually_aborted,
       absl::optional<InterestGroupKey> winning_group_key,
+      absl::optional<blink::AdSize> requested_ad_size,
       absl::optional<blink::AdDescriptor> ad_descriptor,
       std::vector<blink::AdDescriptor> ad_component_descriptors,
       std::vector<std::string> errors,
diff --git a/content/browser/interest_group/interest_group_auction.cc b/content/browser/interest_group/interest_group_auction.cc
index d3ea5fc4..5244e2ab 100644
--- a/content/browser/interest_group/interest_group_auction.cc
+++ b/content/browser/interest_group/interest_group_auction.cc
@@ -2146,6 +2146,10 @@
   }
 }
 
+absl::optional<blink::AdSize> InterestGroupAuction::RequestedAdSize() const {
+  return config_->non_shared_params.requested_size;
+}
+
 base::StringPiece GetRejectReasonString(
     const auction_worklet::mojom::RejectReason reject_reason) {
   base::StringPiece reject_reason_str;
diff --git a/content/browser/interest_group/interest_group_auction.h b/content/browser/interest_group/interest_group_auction.h
index caefc53f..17c0fde 100644
--- a/content/browser/interest_group/interest_group_auction.h
+++ b/content/browser/interest_group/interest_group_auction.h
@@ -494,6 +494,11 @@
   void GetInterestGroupsThatBidAndReportBidCounts(
       blink::InterestGroupSet& interest_groups) const;
 
+  // Returns the requested ad size specified by the auction config. Called
+  // after the bidding and scoring phase completes, to set the container size
+  // in the fenced frame config resulting from the auction.
+  absl::optional<blink::AdSize> RequestedAdSize() const;
+
   // Retrieves any debug reporting URLs. May only be called once, since it takes
   // ownership of stored reporting URLs. This is called internally by
   // CreateReporter() so may only be called in the case an auction has no
diff --git a/content/browser/preloading/prerender/prerender_host.h b/content/browser/preloading/prerender/prerender_host.h
index a04cc62..5847a19 100644
--- a/content/browser/preloading/prerender/prerender_host.h
+++ b/content/browser/preloading/prerender/prerender_host.h
@@ -118,8 +118,8 @@
   // now as it confuses WebContentsObserver instances because they can not
   // distinguish between the different FrameTrees.
 
-  void DidStartLoading(FrameTreeNode* frame_tree_node,
-                       bool should_show_loading_ui) override {}
+  void LoadingStateChanged(LoadingState new_state) override {}
+  void DidStartLoading(FrameTreeNode* frame_tree_node) override {}
   void DidStopLoading() override;
   bool IsHidden() override;
   FrameTree* LoadingTree() override;
diff --git a/content/browser/presentation/OWNERS b/content/browser/presentation/OWNERS
index ab9b3e3..fce1bdfd 100644
--- a/content/browser/presentation/OWNERS
+++ b/content/browser/presentation/OWNERS
@@ -1,2 +1,2 @@
 # Presentation API OWNERS
-mfoltz@chromium.org
+file://third_party/blink/renderer/modules/presentation/OWNERS
diff --git a/content/browser/renderer_host/clipboard_host_impl.cc b/content/browser/renderer_host/clipboard_host_impl.cc
index 304a31a..ff002cc83 100644
--- a/content/browser/renderer_host/clipboard_host_impl.cc
+++ b/content/browser/renderer_host/clipboard_host_impl.cc
@@ -705,6 +705,10 @@
           render_frame_host().GetBrowserContext(),
           render_frame_host().GetLastCommittedURL(), data_size_in_bytes,
           replacement_data)) {
+    // Set the source of the clipboard text/html
+    clipboard_writer_->SetDataSourceURL(
+        render_frame_host().GetMainFrame()->GetLastCommittedURL(),
+        render_frame_host().GetLastCommittedURL());
     std::move(callback).Run();
   } else {
     clipboard_writer_->WriteText(replacement_data);
diff --git a/content/browser/renderer_host/code_cache_host_impl.cc b/content/browser/renderer_host/code_cache_host_impl.cc
index 5d7c4c9..6b9e506 100644
--- a/content/browser/renderer_host/code_cache_host_impl.cc
+++ b/content/browser/renderer_host/code_cache_host_impl.cc
@@ -158,9 +158,9 @@
     const GURL& url,
     base::Time expected_response_time,
     mojo_base::BigBuffer data,
-    const url::Origin& cache_storage_origin,
     const std::string& cache_storage_cache_name,
     int render_process_id,
+    const blink::StorageKey& code_cache_storage_key,
     storage::mojom::CacheStorageControl* cache_storage_control_for_testing,
     mojo::ReportBadMessageCallback bad_message_callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -168,16 +168,6 @@
   if (!render_process_host)
     return;
 
-  // We cannot trust the renderer to give us the correct origin here.  Validate
-  // it against the ChildProcessSecurityPolicy.
-  bool origin_allowed =
-      ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin(
-          render_process_id, cache_storage_origin);
-  if (!origin_allowed) {
-    std::move(bad_message_callback).Run("Bad cache_storage origin.");
-    return;
-  }
-
   int64_t trace_id = blink::cache_storage::CreateTraceId();
   TRACE_EVENT_WITH_FLOW1(
       "CacheStorage",
@@ -193,12 +183,9 @@
           : render_process_host->GetStoragePartition()
                 ->GetCacheStorageControl();
 
-  // TODO(https://crbug.com/1199077): `CodeCacheHostImpl` will need to get the
-  // real StorageKey somehow.
   cache_storage_control->AddReceiver(
       cross_origin_embedder_policy, mojo::NullRemote(),
-      storage::BucketLocator::ForDefaultBucket(
-          blink::StorageKey::CreateFirstParty(cache_storage_origin)),
+      storage::BucketLocator::ForDefaultBucket(code_cache_storage_key),
       storage::mojom::CacheStorageOwner::kCacheAPI,
       remote.BindNewPipeAndPassReceiver());
 
@@ -238,10 +225,11 @@
     scoped_refptr<GeneratedCodeCacheContext> context,
     int render_process_id,
     const net::NetworkIsolationKey& nik,
+    const blink::StorageKey& storage_key,
     mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver,
     CodeCacheHostImpl::ReceiverSet::CodeCacheHostReceiverHandler handler) {
-  auto host =
-      std::make_unique<CodeCacheHostImpl>(render_process_id, context, nik);
+  auto host = std::make_unique<CodeCacheHostImpl>(render_process_id, context,
+                                                  nik, storage_key);
   auto* raw_host = host.get();
   auto id = receiver_set->Add(std::move(host), std::move(receiver));
   if (handler)
@@ -263,6 +251,7 @@
 void CodeCacheHostImpl::ReceiverSet::Add(
     int render_process_id,
     const net::NetworkIsolationKey& nik,
+    const blink::StorageKey& storage_key,
     mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver,
     CodeCacheHostReceiverHandler handler) {
   if (!receiver_set_) {
@@ -277,14 +266,15 @@
       generated_code_cache_context_, FROM_HERE,
       base::BindOnce(&AddCodeCacheReceiver, receiver_set_.get(),
                      generated_code_cache_context_, render_process_id, nik,
-                     std::move(receiver), std::move(handler)));
+                     storage_key, std::move(receiver), std::move(handler)));
 }
 
 void CodeCacheHostImpl::ReceiverSet::Add(
     int render_process_id,
     const net::NetworkIsolationKey& nik,
+    const blink::StorageKey& storage_key,
     mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver) {
-  Add(render_process_id, nik, std::move(receiver),
+  Add(render_process_id, nik, storage_key, std::move(receiver),
       CodeCacheHostReceiverHandler());
 }
 
@@ -295,10 +285,12 @@
 CodeCacheHostImpl::CodeCacheHostImpl(
     int render_process_id,
     scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context,
-    const net::NetworkIsolationKey& nik)
+    const net::NetworkIsolationKey& nik,
+    const blink::StorageKey& storage_key)
     : render_process_id_(render_process_id),
       generated_code_cache_context_(std::move(generated_code_cache_context)),
-      network_isolation_key_(nik) {
+      network_isolation_key_(nik),
+      storage_key_(storage_key) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
@@ -375,15 +367,14 @@
     const GURL& url,
     base::Time expected_response_time,
     mojo_base::BigBuffer data,
-    const url::Origin& cache_storage_origin,
     const std::string& cache_storage_cache_name) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   GetUIThreadTaskRunner({})->PostTask(
       FROM_HERE,
       base::BindOnce(&DidGenerateCacheableMetadataInCacheStorageOnUI, url,
                      expected_response_time, std::move(data),
-                     cache_storage_origin, cache_storage_cache_name,
-                     render_process_id_, cache_storage_control_for_testing_,
+                     cache_storage_cache_name, render_process_id_, storage_key_,
+                     cache_storage_control_for_testing_,
                      mojo::GetBadMessageCallback()));
 }
 
diff --git a/content/browser/renderer_host/code_cache_host_impl.h b/content/browser/renderer_host/code_cache_host_impl.h
index d6742b0..2eadccd 100644
--- a/content/browser/renderer_host/code_cache_host_impl.h
+++ b/content/browser/renderer_host/code_cache_host_impl.h
@@ -22,10 +22,6 @@
 
 class GURL;
 
-namespace url {
-class Origin;
-}
-
 namespace content {
 
 class GeneratedCodeCache;
@@ -34,6 +30,21 @@
 // The implementation of a CodeCacheHost, which stores and retrieves resource
 // metadata, either bytecode or native code, generated by a renderer process.
 //
+// This implements two independent caches:
+//
+//  GeneratedCodeCache:
+//    Entries are keyed by URL, cache type, and network isolation key.
+//    See: - `DidGenerateCacheableMetadata`
+//         - `FetchCachedCode`
+//         - `ClearCodeCacheEntry`
+//
+//  CacheStorage:
+//    Entries are keyed by URL, cache name, and storage key.
+//    This class only supports writing such data. Data is stored as
+//    "side data" in the cache storage cache.
+//    See: - `DidGenerateCacheableMetadataInCacheStorage`
+//         - `CacheStorageCache::WriteSideData`
+//
 // This class is sequence-friendly and is not necessarily bound to a physical
 // thread.
 class CONTENT_EXPORT CodeCacheHostImpl : public blink::mojom::CodeCacheHost {
@@ -52,10 +63,12 @@
         mojo::UniqueReceiverSet<blink::mojom::CodeCacheHost>&)>;
     void Add(int render_process_id,
              const net::NetworkIsolationKey& nik,
+             const blink::StorageKey& storage_key,
              mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver,
              CodeCacheHostReceiverHandler handler);
     void Add(int render_process_id,
              const net::NetworkIsolationKey& nik,
+             const blink::StorageKey& storage_key,
              mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver);
     void Clear();
 
@@ -72,7 +85,8 @@
   CodeCacheHostImpl(
       int render_process_id,
       scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context,
-      const net::NetworkIsolationKey& nik);
+      const net::NetworkIsolationKey& nik,
+      const blink::StorageKey& storage_key);
 
   CodeCacheHostImpl(const CodeCacheHostImpl&) = delete;
   CodeCacheHostImpl& operator=(const CodeCacheHostImpl&) = delete;
@@ -97,7 +111,6 @@
       const GURL& url,
       base::Time expected_response_time,
       mojo_base::BigBuffer data,
-      const url::Origin& cache_storage_origin,
       const std::string& cache_storage_cache_name) override;
 
   // Helpers.
@@ -117,8 +130,12 @@
 
   scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context_;
 
+  // The key used to partition code cached in the `GeneratedCodeCache`.
   const net::NetworkIsolationKey network_isolation_key_;
 
+  // The key used to partition code cached in the cache API.
+  const blink::StorageKey storage_key_;
+
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<CodeCacheHostImpl> weak_ptr_factory_{this};
diff --git a/content/browser/renderer_host/cookie_utils.cc b/content/browser/renderer_host/cookie_utils.cc
index dfdaa67..e5736f6 100644
--- a/content/browser/renderer_host/cookie_utils.cc
+++ b/content/browser/renderer_host/cookie_utils.cc
@@ -11,17 +11,43 @@
 #include "content/public/browser/cookie_access_details.h"
 #include "content/public/common/content_client.h"
 #include "net/cookies/cookie_inclusion_status.h"
+#include "services/metrics/public/cpp/metrics_utils.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 
 namespace content {
 
 namespace {
 
-void RecordContextDowngradeUKM(RenderFrameHost* rfh,
-                               CookieAccessDetails::Type access_type,
-                               const net::CookieInclusionStatus& status,
-                               const GURL& url) {
-  DCHECK(rfh);
+void RecordRedirectContextDowngradeUKM(RenderFrameHost* rfh,
+                                       CookieAccessDetails::Type access_type,
+                                       const net::CanonicalCookie& cookie,
+                                       const GURL& url) {
+  CHECK(rfh);
+  ukm::SourceId source_id = rfh->GetPageUkmSourceId();
+
+  int64_t samesite_value = static_cast<int64_t>(cookie.SameSite());
+  if (access_type == CookieAccessDetails::Type::kRead) {
+    base::TimeDelta cookie_age = base::Time::Now() - cookie.CreationDate();
+
+    ukm::builders::SamesiteRedirectContextDowngrade(source_id)
+        .SetSamesiteValueReadPerCookie(samesite_value)
+        .SetAgePerCookie(
+            ukm::GetExponentialBucketMinForUserTiming(cookie_age.InMinutes()))
+        .Record(ukm::UkmRecorder::Get());
+  } else {
+    CHECK(access_type == CookieAccessDetails::Type::kChange);
+    ukm::builders::SamesiteRedirectContextDowngrade(source_id)
+        .SetSamesiteValueWritePerCookie(samesite_value)
+        .Record(ukm::UkmRecorder::Get());
+  }
+}
+
+void RecordSchemefulContextDowngradeUKM(
+    RenderFrameHost* rfh,
+    CookieAccessDetails::Type access_type,
+    const net::CookieInclusionStatus& status,
+    const GURL& url) {
+  CHECK(rfh);
   ukm::SourceId source_id = rfh->GetPageUkmSourceId();
 
   auto downgrade_metric =
@@ -31,7 +57,7 @@
         .SetRequestPerCookie(downgrade_metric)
         .Record(ukm::UkmRecorder::Get());
   } else {
-    DCHECK(access_type == CookieAccessDetails::Type::kChange);
+    CHECK(access_type == CookieAccessDetails::Type::kChange);
     ukm::builders::SchemefulSameSiteContextDowngrade(source_id)
         .SetResponsePerCookie(downgrade_metric)
         .Record(ukm::UkmRecorder::Get());
@@ -200,13 +226,23 @@
 
     breaking_context_downgrade =
         breaking_context_downgrade ||
-        cookie->access_result.status.HasDowngradeWarning();
+        cookie->access_result.status.HasSchemefulDowngradeWarning();
 
-    if (cookie->access_result.status.HasDowngradeWarning()) {
-      // Unlike with UMA, do not record cookies that have no downgrade warning.
-      RecordContextDowngradeUKM(rfh, cookie_details->type,
-                                cookie->access_result.status,
-                                cookie_details->url);
+    if (cookie->access_result.status.HasSchemefulDowngradeWarning()) {
+      // Unlike with UMA, do not record cookies that have no schemeful downgrade
+      // warning.
+      RecordSchemefulContextDowngradeUKM(rfh, cookie_details->type,
+                                         cookie->access_result.status,
+                                         cookie_details->url);
+    }
+
+    if (status.HasWarningReason(
+            net::CookieInclusionStatus::
+                WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION) &&
+        cookie->cookie_or_line->is_cookie()) {
+      RecordRedirectContextDowngradeUKM(rfh, cookie_details->type,
+                                        cookie->cookie_or_line->get_cookie(),
+                                        cookie_details->url);
     }
 
     // In order to anticipate the potential effects of the expiry limit in
diff --git a/content/browser/renderer_host/frame_tree.cc b/content/browser/renderer_host/frame_tree.cc
index 7ba0435..b2d96099 100644
--- a/content/browser/renderer_host/frame_tree.cc
+++ b/content/browser/renderer_host/frame_tree.cc
@@ -771,12 +771,26 @@
 }
 
 bool FrameTree::IsLoadingIncludingInnerFrameTrees() const {
-  for (const FrameTreeNode* node :
-       const_cast<FrameTree*>(this)->CollectNodesForIsLoading()) {
-    if (node->IsLoading())
-      return true;
+  return GetLoadingState() != LoadingState::NONE;
+}
+
+LoadingState FrameTree::GetLoadingState() const {
+  // The overall loading state for the FrameTree matches the root node's loading
+  // state if the root is loading.
+  if (root_.GetLoadingState() != LoadingState::NONE) {
+    return root_.GetLoadingState();
   }
-  return false;
+
+  // Otherwise, check if a subframe is loading without an associated navigation
+  // in the root frame. If so, we are loading, but we don't want to show
+  // loading UI.
+  for (const FrameTreeNode* node_to_check :
+       const_cast<FrameTree*>(this)->CollectNodesForIsLoading()) {
+    if (node_to_check->IsLoading()) {
+      return LoadingState::LOADING_WITHOUT_UI;
+    }
+  }
+  return LoadingState::NONE;
 }
 
 void FrameTree::ReplicatePageFocus(bool is_focused) {
@@ -900,22 +914,22 @@
   controller().DidAccessInitialMainDocument();
 }
 
-void FrameTree::DidStartLoadingNode(FrameTreeNode& node,
-                                    bool should_show_loading_ui,
-                                    bool was_previously_loading) {
-  if (was_previously_loading)
+void FrameTree::NodeLoadingStateChanged(
+    FrameTreeNode& node,
+    LoadingState previous_frame_tree_loading_state) {
+  LoadingState new_frame_tree_loading_state = GetLoadingState();
+  if (previous_frame_tree_loading_state == new_frame_tree_loading_state) {
     return;
+  }
 
-  root()->render_manager()->SetIsLoading(IsLoadingIncludingInnerFrameTrees());
-  delegate_->DidStartLoading(&node, should_show_loading_ui);
-}
-
-void FrameTree::DidStopLoadingNode(FrameTreeNode& node) {
-  if (IsLoadingIncludingInnerFrameTrees())
-    return;
-
-  root()->render_manager()->SetIsLoading(false);
-  delegate_->DidStopLoading();
+  root()->render_manager()->SetIsLoading(new_frame_tree_loading_state !=
+                                         LoadingState::NONE);
+  delegate_->LoadingStateChanged(new_frame_tree_loading_state);
+  if (previous_frame_tree_loading_state == LoadingState::NONE) {
+    delegate_->DidStartLoading(&node);
+  } else if (new_frame_tree_loading_state == LoadingState::NONE) {
+    delegate_->DidStopLoading();
+  }
 }
 
 void FrameTree::DidCancelLoading() {
diff --git a/content/browser/renderer_host/frame_tree.h b/content/browser/renderer_host/frame_tree.h
index b6a2739..a26e26d 100644
--- a/content/browser/renderer_host/frame_tree.h
+++ b/content/browser/renderer_host/frame_tree.h
@@ -137,18 +137,22 @@
 
   class CONTENT_EXPORT Delegate {
    public:
-    // A RenderFrameHost in the specified |frame_tree_node| started loading a
-    // new document. This corresponds to browser UI starting to show a spinner
-    // or other visual indicator for loading. This method is only invoked if the
-    // FrameTree hadn't been previously loading. |should_show_loading_ui| will
-    // be true unless the load is a fragment navigation, or triggered by
-    // history.pushState/replaceState.
-    virtual void DidStartLoading(FrameTreeNode* frame_tree_node,
-                                 bool should_show_loading_ui) = 0;
+    // The FrameTree changed its LoadingState. This can be a transition between
+    // not-loading and loading (in which case it will be accompanied by either a
+    // DidStartLoading or DidStopLoading), or a transition between not showing
+    // loading UI and showing loading UI while a navigation is in progress (in
+    // which case it will be called without either DidStartLoading or
+    // DidStopLoading).
+    virtual void LoadingStateChanged(LoadingState new_state) = 0;
 
-    // This is called when all nodes in the FrameTree stopped loading. This
-    // corresponds to the browser UI stop showing a spinner or other visual
-    // indicator for loading.
+    // The FrameTree has started loading in `frame_tree_node`. Note that this
+    // is only called when the FrameTree as a whole goes from not-loading to
+    // loading. If a second FrameTreeNode begins loading, a new DidStartLoading
+    // message will not be sent.
+    virtual void DidStartLoading(FrameTreeNode* frame_tree_node) = 0;
+
+    // The FrameTree has stopped loading. Sent only when all FrameTreeNodes have
+    // stopped loading.
     virtual void DidStopLoading() = 0;
 
     // Returns the delegate's top loading tree, which should be used to infer
@@ -467,10 +471,8 @@
   // the listener installed by SetFrameRemoveListener.
   void FrameRemoved(FrameTreeNode* frame);
 
-  void DidStartLoadingNode(FrameTreeNode& node,
-                           bool should_show_loading_ui,
-                           bool was_previously_loading);
-  void DidStopLoadingNode(FrameTreeNode& node);
+  void NodeLoadingStateChanged(FrameTreeNode& node,
+                               LoadingState previous_frame_tree_loading_state);
   void DidCancelLoading();
 
   // Returns this FrameTree's total load progress. If the `root_` FrameTreeNode
@@ -481,6 +483,10 @@
   // any inner frame tree of the same WebContents is loading.
   bool IsLoadingIncludingInnerFrameTrees() const;
 
+  // Returns the LoadingState for the FrameTree as a whole, indicating whether
+  // a load is in progress, as well as whether loading UI should be shown.
+  LoadingState GetLoadingState() const;
+
   // Set page-level focus in all SiteInstances involved in rendering
   // this FrameTree, not including the current main frame's
   // SiteInstance. The focus update will be sent via the main frame's proxies
diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc
index ba54eadd..0770dcf 100644
--- a/content/browser/renderer_host/frame_tree_node.cc
+++ b/content/browser/renderer_host/frame_tree_node.cc
@@ -518,21 +518,33 @@
 }
 
 bool FrameTreeNode::IsLoading() const {
+  return GetLoadingState() != LoadingState::NONE;
+}
+
+LoadingState FrameTreeNode::GetLoadingState() const {
   RenderFrameHostImpl* current_frame_host =
       render_manager_.current_frame_host();
-
   DCHECK(current_frame_host);
 
-  if (navigation_request_)
-    return true;
+  if (navigation_request_) {
+    // If navigation_request_ is non-null, the navigation has not been moved to
+    // the RenderFrameHostImpl or sent to the renderer to be committed. This
+    // loading UI policy is provisional, as the navigation API might "intercept"
+    // a same-document commit and change it from LOADING_WITHOUT_UI to
+    // LOADING_UI_REQUESTED.
+    return navigation_request_->IsSameDocument()
+               ? LoadingState::LOADING_WITHOUT_UI
+               : LoadingState::LOADING_UI_REQUESTED;
+  }
 
   RenderFrameHostImpl* speculative_frame_host =
       render_manager_.speculative_frame_host();
   // TODO(dcheng): Shouldn't a FrameTreeNode with a speculative RenderFrameHost
   // always be considered loading?
-  if (speculative_frame_host && speculative_frame_host->is_loading())
-    return true;
-  return current_frame_host->is_loading();
+  if (speculative_frame_host && speculative_frame_host->is_loading()) {
+    return LoadingState::LOADING_UI_REQUESTED;
+  }
+  return current_frame_host->loading_state();
 }
 
 bool FrameTreeNode::HasPendingCrossDocumentNavigation() const {
@@ -566,14 +578,14 @@
   DCHECK(!navigation_request->common_params().url.SchemeIs(
       url::kJavaScriptScheme));
 
-  bool was_previously_loading =
-      frame_tree().LoadingTree()->IsLoadingIncludingInnerFrameTrees();
+  LoadingState previous_frame_tree_loading_state =
+      frame_tree().LoadingTree()->GetLoadingState();
 
   // Reset the previous NavigationRequest owned by `this`. However, there's no
   // need to reset the state: there's still an ongoing load, and the
   // RenderFrameHostManager will take care of updates to the speculative
   // RenderFrameHost in DidCreateNavigationRequest below.
-  if (was_previously_loading) {
+  if (previous_frame_tree_loading_state != LoadingState::NONE) {
     if (navigation_request_ && navigation_request_->IsNavigationStarted()) {
       // Mark the old request as aborted.
       navigation_request_->set_net_error(net::ERR_ABORTED);
@@ -587,11 +599,7 @@
     was_discarded_ = false;
   }
   render_manager()->DidCreateNavigationRequest(navigation_request_.get());
-
-  bool to_different_document = !NavigationTypeUtils::IsSameDocument(
-      navigation_request_->common_params().navigation_type);
-
-  DidStartLoading(to_different_document, was_previously_loading);
+  DidStartLoading(previous_frame_tree_loading_state);
 }
 
 void FrameTreeNode::ResetNavigationRequest(NavigationDiscardReason reason) {
@@ -614,15 +622,15 @@
   navigation_request_.reset();
 }
 
-void FrameTreeNode::DidStartLoading(bool should_show_loading_ui,
-                                    bool was_previously_loading) {
+void FrameTreeNode::DidStartLoading(
+    LoadingState previous_frame_tree_loading_state) {
   TRACE_EVENT2("navigation", "FrameTreeNode::DidStartLoading",
-               "frame_tree_node", frame_tree_node_id(),
-               "should_show_loading_ui ", should_show_loading_ui);
+               "frame_tree_node", frame_tree_node_id(), "loading_state",
+               GetLoadingState());
   base::ElapsedTimer timer;
 
-  frame_tree().LoadingTree()->DidStartLoadingNode(*this, should_show_loading_ui,
-                                                  was_previously_loading);
+  frame_tree().LoadingTree()->NodeLoadingStateChanged(
+      *this, previous_frame_tree_loading_state);
 
   // Set initial load progress and update overall progress. This will notify
   // the WebContents of the load progress change.
@@ -657,11 +665,21 @@
   current_frame_host()->browsing_context_state()->OnDidStopLoading();
 
   FrameTree* loading_tree = frame_tree().LoadingTree();
-  // When loading tree is null, ignore invoking DidStopLoadingNode as the frame
-  // tree is already deleted. This can happen when prerendering gets cancelled
-  // and DidStopLoading is called during FrameTree destruction.
-  if (loading_tree)
-    loading_tree->DidStopLoadingNode(*this);
+  // When loading tree is null, ignore invoking NodeLoadingStateChanged as the
+  // frame tree is already deleted. This can happen when prerendering gets
+  // cancelled and DidStopLoading is called during FrameTree destruction.
+  if (loading_tree && !loading_tree->IsLoadingIncludingInnerFrameTrees()) {
+    // If `loading_tree->IsLoadingIncludingInnerFrameTrees()` is now false, this
+    // was the last FrameTreeNode to be loading, and the FrameTree as a whole
+    // has now stopped loading. Notify the FrameTree.
+    // It doesn't matter whether we pass LOADING_UI_REQUESTED or
+    // LOADING_WITHOUT_UI as the previous_frame_tree_loading_state param,
+    // because the previous value is only used to detect when the FrameTree's
+    // overall loading state hasn't changed, and we know that the new state will
+    // be LoadingState::NONE.
+    loading_tree->NodeLoadingStateChanged(*this,
+                                          LoadingState::LOADING_UI_REQUESTED);
+  }
 }
 
 void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
@@ -905,7 +923,7 @@
 
 void FrameTreeNode::SetFencedFrameAutomaticBeaconReportEventData(
     const std::string& event_data,
-    const std::vector<blink::FencedFrame::ReportingDestination>& destination) {
+    const std::vector<blink::FencedFrame::ReportingDestination>& destinations) {
   absl::optional<FencedFrameProperties>& properties =
       GetFencedFramePropertiesForEditing();
   // `properties` will exist for both fenced frames as well as iframes loaded
@@ -927,7 +945,7 @@
         "origin to the mapped url from the fenced frame config.");
     return;
   }
-  properties->UpdateAutomaticBeaconData(event_data, destination);
+  properties->UpdateAutomaticBeaconData(event_data, destinations);
 }
 
 size_t FrameTreeNode::GetFencedFrameDepth(
diff --git a/content/browser/renderer_host/frame_tree_node.h b/content/browser/renderer_host/frame_tree_node.h
index 3712869..16f7e68c 100644
--- a/content/browser/renderer_host/frame_tree_node.h
+++ b/content/browser/renderer_host/frame_tree_node.h
@@ -308,6 +308,7 @@
 
   // Returns true if this node is in a loading state.
   bool IsLoading() const;
+  LoadingState GetLoadingState() const;
 
   // Returns true if this node has a cross-document navigation in progress.
   bool HasPendingCrossDocumentNavigation() const;
@@ -570,7 +571,7 @@
   // `Fence.setReportEventDataForAutomaticBeacons` JS API.
   void SetFencedFrameAutomaticBeaconReportEventData(
       const std::string& event_data,
-      const std::vector<blink::FencedFrame::ReportingDestination>& destination)
+      const std::vector<blink::FencedFrame::ReportingDestination>& destinations)
       override;
 
   // Returns the number of fenced frame boundaries above this frame. The
@@ -636,8 +637,7 @@
   void ResetAllNavigationsForFrameDetach();
 
   // RenderFrameHostOwner implementation:
-  void DidStartLoading(bool should_show_loading_ui,
-                       bool was_previously_loading) override;
+  void DidStartLoading(LoadingState previous_frame_tree_loading_state) override;
   void DidStopLoading() override;
   void RestartNavigationAsCrossDocument(
       std::unique_ptr<NavigationRequest> navigation_request) override;
diff --git a/content/browser/renderer_host/loading_state.h b/content/browser/renderer_host/loading_state.h
new file mode 100644
index 0000000..138f73a
--- /dev/null
+++ b/content/browser/renderer_host/loading_state.h
@@ -0,0 +1,28 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_LOADING_STATE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_LOADING_STATE_H_
+
+namespace content {
+
+// Used to specify the loading state of a frame, or the frame tree as a whole.
+enum class LoadingState {
+  // Not currently loading.
+  NONE,
+  // Loading currently in progress, but no loading UI should be shown. Used
+  // for most same-document navigations.
+  LOADING_WITHOUT_UI,
+  // Loading currently in progress, and loading UI is recommended. This is
+  // used for cross-document navigations, as well as asynchronous same-document
+  // navigations from the web-exposed navigation API. Note that even if a
+  // FrameTreeNode's LoadingState is LOADING_UI_REQUESTED, the FrameTree may
+  // decide the tree-wide policy is LOADING_WITHOUT_UI if the root frame is not
+  // loading. Also, the embedder is under no obligation to showing any UI.
+  LOADING_UI_REQUESTED,
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_LOADING_STATE_H_
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 5a940cbd..5af91d5d 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -3676,12 +3676,7 @@
   // the renderer process is done handling the URL.
   // TODO(crbug.com/1254130): Remove the test dependency on this behavior.
   if (!url.SchemeIs(url::kJavaScriptScheme)) {
-    bool was_loading = frame_tree_node->frame_tree()
-                           .LoadingTree()
-                           ->IsLoadingIncludingInnerFrameTrees();
     frame_tree_node->current_frame_host()->SetIsLoadingForRendererDebugURL();
-    frame_tree_node->DidStartLoading(true /* should_show_loading_ui */,
-                                     was_loading);
   }
   frame_tree_node->current_frame_host()->HandleRendererDebugURL(url);
 }
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 6ffec68..d1e2640 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -4681,11 +4681,10 @@
   if (is_loading()) {
     return;
   }
-  bool was_loading =
-      frame_tree()->LoadingTree()->IsLoadingIncludingInnerFrameTrees();
-  is_loading_ = true;
-  frame_tree_node()->DidStartLoading(true /* should_show_loading_ui */,
-                                     was_loading);
+  LoadingState previous_frame_tree_loading_state =
+      frame_tree()->LoadingTree()->GetLoadingState();
+  loading_state_ = LoadingState::LOADING_UI_REQUESTED;
+  frame_tree_node()->DidStartLoading(previous_frame_tree_loading_state);
 }
 
 void RenderFrameHostImpl::DidCommitSameDocumentNavigation(
@@ -4831,15 +4830,15 @@
     std::unique_ptr<NavigationRequest> navigation_request) {
   DCHECK(navigation_request);
 
-  is_loading_ = true;
-
   if (NavigationTypeUtils::IsSameDocument(
           navigation_request->common_params().navigation_type)) {
+    loading_state_ = LoadingState::LOADING_WITHOUT_UI;
     same_document_navigation_requests_[navigation_request->commit_params()
                                            .navigation_token] =
         std::move(navigation_request);
     return;
   }
+  loading_state_ = LoadingState::LOADING_UI_REQUESTED;
   navigation_requests_[navigation_request.get()] =
       std::move(navigation_request);
 }
@@ -7602,11 +7601,12 @@
   // BeforeUnload or Unload events.
   // TODO(fdegans): Change this to a DCHECK after LoadEventProgress has been
   // refactored in Blink. See crbug.com/466089
-  if (!is_loading_)
+  if (!is_loading()) {
     return;
+  }
 
   was_discarded_ = false;
-  is_loading_ = false;
+  loading_state_ = LoadingState::NONE;
 
   // If we have a PeakGpuMemoryTrack, close it as loading as stopped. It will
   // asynchronously receive the statistics from the GPU process, and update
@@ -8146,9 +8146,12 @@
 void RenderFrameHostImpl::SendFencedFrameReportingBeacon(
     const std::string& event_data,
     const std::string& event_type,
-    blink::FencedFrame::ReportingDestination destination) {
-  SendFencedFrameReportingBeaconInternal(event_data, event_type, destination,
-                                         /*from_renderer=*/true);
+    const std::vector<blink::FencedFrame::ReportingDestination>& destinations) {
+  for (const blink::FencedFrame::ReportingDestination& destination :
+       destinations) {
+    SendFencedFrameReportingBeaconInternal(event_data, event_type, destination,
+                                           /*from_renderer=*/true);
+  }
 }
 
 void RenderFrameHostImpl::MaybeSendFencedFrameReportingBeacon(
@@ -8206,7 +8209,7 @@
   }
 
   for (blink::FencedFrame::ReportingDestination destination :
-       info->destination) {
+       info->destinations) {
     initiator_rfh->SendFencedFrameReportingBeaconInternal(
         info->data, blink::kFencedFrameTopNavigationBeaconType, destination,
         /*from_renderer=*/false, navigation_request.GetNavigationId());
@@ -8283,7 +8286,7 @@
 
 void RenderFrameHostImpl::SetFencedFrameAutomaticBeaconReportEventData(
     const std::string& event_data,
-    const std::vector<blink::FencedFrame::ReportingDestination>& destination) {
+    const std::vector<blink::FencedFrame::ReportingDestination>& destinations) {
   if (event_data.length() > blink::kFencedFrameMaxBeaconLength) {
     mojo::ReportBadMessage(
         "The data provided to SetFencedFrameAutomaticBeaconReportEventData() "
@@ -8303,7 +8306,8 @@
   }
   CHECK(owner_);  // See `owner_` invariants about `IsActive()`.
 
-  owner_->SetFencedFrameAutomaticBeaconReportEventData(event_data, destination);
+  owner_->SetFencedFrameAutomaticBeaconReportEventData(event_data,
+                                                       destinations);
 }
 
 void RenderFrameHostImpl::OnViewTransitionOptInChanged(
@@ -10233,10 +10237,11 @@
     // When pending deletion, just set the loading state to not loading.
     // Otherwise, DidStopLoading will take care of that, as well as sending
     // notification to the FrameTreeNode about the change in loading state.
-    if (IsPendingDeletion() || IsInBackForwardCache())
-      is_loading_ = false;
-    else
+    if (IsPendingDeletion() || IsInBackForwardCache()) {
+      loading_state_ = LoadingState::NONE;
+    } else {
       DidStopLoading();
+    }
   }
 }
 
@@ -11238,19 +11243,20 @@
   InstalledAppProviderImpl::Create(*this, std::move(receiver));
 }
 
-void RenderFrameHostImpl::CreateCodeCacheHostWithIsolationKey(
+void RenderFrameHostImpl::CreateCodeCacheHostWithKeys(
     mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver,
-    const net::NetworkIsolationKey& nik) {
+    const net::NetworkIsolationKey& nik,
+    const blink::StorageKey& storage_key) {
   // Create a new CodeCacheHostImpl and bind it to the given receiver.
-  code_cache_host_receivers_.Add(GetProcess()->GetID(), nik,
+  code_cache_host_receivers_.Add(GetProcess()->GetID(), nik, storage_key,
                                  std::move(receiver),
                                  GetCodeCacheHostReceiverHandler());
 }
 
 void RenderFrameHostImpl::CreateCodeCacheHost(
     mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver) {
-  CreateCodeCacheHostWithIsolationKey(std::move(receiver),
-                                      GetNetworkIsolationKey());
+  CreateCodeCacheHostWithKeys(std::move(receiver), GetNetworkIsolationKey(),
+                              storage_key());
 }
 
 void RenderFrameHostImpl::CreateDedicatedWorkerHostFactory(
@@ -12315,12 +12321,13 @@
         same_document_params->same_document_navigation_type ==
             blink::mojom::SameDocumentNavigationType::kNavigationApiIntercept;
 
-    bool was_loading =
-        frame_tree()->LoadingTree()->IsLoadingIncludingInnerFrameTrees();
-    is_loading_ = true;
+    LoadingState previous_frame_tree_loading_state =
+        frame_tree()->LoadingTree()->GetLoadingState();
+    loading_state_ = should_show_loading_ui ? LoadingState::LOADING_UI_REQUESTED
+                                            : LoadingState::LOADING_WITHOUT_UI;
     // TODO(https://crbug.com/1405759): Explain why this is true.
     CHECK(owner_);
-    owner_->DidStartLoading(should_show_loading_ui, was_loading);
+    owner_->DidStartLoading(previous_frame_tree_loading_state);
   }
 
   if (navigation_request)
@@ -12937,10 +12944,17 @@
   mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host;
   mojom::CookieManagerInfoPtr cookie_manager_info;
   mojom::StorageInfoPtr storage_info;
-  CreateCodeCacheHostWithIsolationKey(
+
+  // Until the browser is able to compute the origin accurately in all cases
+  // (see https://crbug.com/888079), this is actually just a provisional
+  // `storage_key`. The final storage key is computed by the document loader
+  // taking into account the origin computed by the renderer.
+  auto& code_cache_storage_key = commit_params->storage_key;
+  CreateCodeCacheHostWithKeys(
       code_cache_host.InitWithNewPipeAndPassReceiver(),
       navigation_request->isolation_info_for_subresources()
-          .network_isolation_key());
+          .network_isolation_key(),
+      code_cache_storage_key);
 
   url::Origin origin_to_commit =
       navigation_request->GetOriginToCommit().value();
@@ -14366,6 +14380,13 @@
   return !GetParentOrOuterDocument();
 }
 
+void RenderFrameHostImpl::SetIsLoadingForRendererDebugURL() {
+  LoadingState previous_frame_tree_loading_state =
+      frame_tree()->LoadingTree()->GetLoadingState();
+  loading_state_ = LoadingState::LOADING_UI_REQUESTED;
+  owner_->DidStartLoading(previous_frame_tree_loading_state);
+}
+
 BackForwardCacheMetrics* RenderFrameHostImpl::GetBackForwardCacheMetrics() {
   NavigationEntryImpl* navigation_entry =
       frame_tree()->controller().GetEntryWithUniqueID(nav_entry_id());
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index e9ea753..01cc551 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -54,6 +54,7 @@
 #include "content/browser/renderer_host/cross_origin_opener_policy_access_report_manager.h"
 #include "content/browser/renderer_host/frame_navigation_entry.h"
 #include "content/browser/renderer_host/keep_alive_handle_factory.h"
+#include "content/browser/renderer_host/loading_state.h"
 #include "content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h"
 #include "content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h"
 #include "content/browser/renderer_host/navigation_discard_reason.h"
@@ -947,12 +948,13 @@
   // Returns this RenderFrameHost's loading state. This method is only used by
   // FrameTreeNode. The proper way to check whether a frame is loading is to
   // call FrameTreeNode::IsLoading.
-  bool is_loading() const { return is_loading_; }
+  bool is_loading() const { return loading_state_ != LoadingState::NONE; }
 
-  // Sets `is_loading_` to true to handle renderer debug URLs. This is needed
-  // to generate DidStopLoading events for these URLs.
-  void SetIsLoadingForRendererDebugURL() { is_loading_ = true; }
+  LoadingState loading_state() const { return loading_state_; }
 
+  // Sets `loading_state_` to LOADING_UI_REQUESTED to handle renderer debug
+  // URLs. This is needed to generate DidStopLoading events for these URLs.
+  void SetIsLoadingForRendererDebugURL();
   // Returns true if this is a top-level frame, or if this frame
   // uses a proxy to communicate with its parent frame. Local roots are
   // distinguished by owning a RenderWidgetHost, which manages input events
@@ -2007,9 +2009,10 @@
 
   void CreateCodeCacheHost(
       mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver);
-  void CreateCodeCacheHostWithIsolationKey(
+  void CreateCodeCacheHostWithKeys(
       mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver,
-      const net::NetworkIsolationKey& nik);
+      const net::NetworkIsolationKey& nik,
+      const blink::StorageKey& storage_key);
 
 #if BUILDFLAG(IS_ANDROID)
   void BindNFCReceiver(mojo::PendingReceiver<device::mojom::NFC> receiver);
@@ -2397,10 +2400,11 @@
   void SendFencedFrameReportingBeacon(
       const std::string& event_data,
       const std::string& event_type,
-      blink::FencedFrame::ReportingDestination destination) override;
+      const std::vector<blink::FencedFrame::ReportingDestination>& destinations)
+      override;
   void SetFencedFrameAutomaticBeaconReportEventData(
       const std::string& event_data,
-      const std::vector<blink::FencedFrame::ReportingDestination>& destination)
+      const std::vector<blink::FencedFrame::ReportingDestination>& destinations)
       override;
   void SendPrivateAggregationRequestsForFencedFrameEvent(
       const std::string& event_type) override;
@@ -4270,8 +4274,8 @@
   bool was_discarded_ = false;
 
   // Indicates whether this RenderFrameHost is in the process of loading a
-  // document or not.
-  bool is_loading_ = false;
+  // document or not, and if so, whether it should show loading UI.
+  LoadingState loading_state_ = LoadingState::NONE;
 
   // The unique ID of the latest NavigationEntry that this RenderFrameHost is
   // showing. This may change even when this frame hasn't committed a page,
diff --git a/content/browser/renderer_host/render_frame_host_owner.h b/content/browser/renderer_host/render_frame_host_owner.h
index 0aed0d8a..623c381 100644
--- a/content/browser/renderer_host/render_frame_host_owner.h
+++ b/content/browser/renderer_host/render_frame_host_owner.h
@@ -55,20 +55,9 @@
   RenderFrameHostOwner() = default;
   virtual ~RenderFrameHostOwner() = default;
 
-  // A RenderFrameHost started loading:
-  //
-  // - `should_show_loading_ui` indicates whether the loading indicator UI
-  //   should be shown or not. It must be true for:
-  //   * cross-document navigations
-  //   * navigations intercepted by the navigation API's intercept().
-  //
-  // - `was_previously_loading` is false if the FrameTree was not loading
-  //   before. The caller is required to provide this boolean as the delegate
-  //   should only be notified if the FrameTree went from non-loading to loading
-  //   state. However, when it is called, the FrameTree should be in a loading
-  //   state.
-  virtual void DidStartLoading(bool should_show_loading_ui,
-                               bool was_previously_loading) = 0;
+  // A RenderFrameHost started loading.
+  virtual void DidStartLoading(
+      LoadingState previous_frame_tree_loading_state) = 0;
 
   // A RenderFrameHost in this owner stopped loading.
   virtual void DidStopLoading() = 0;
@@ -138,7 +127,7 @@
   virtual void SetFencedFrameAutomaticBeaconReportEventData(
       const std::string& event_data,
       const std::vector<blink::FencedFrame::ReportingDestination>&
-          destination) = 0;
+          destinations) = 0;
 
 #if !BUILDFLAG(IS_ANDROID)
   virtual void GetVirtualAuthenticatorManager(
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 19fb72a..2cd6e0e 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -2793,37 +2793,6 @@
 
 namespace {
 
-class CodeCacheHostInterceptor
-    : public blink::mojom::CodeCacheHostInterceptorForTesting {
- public:
-  explicit CodeCacheHostInterceptor(CodeCacheHostImpl* code_cache_host_impl)
-      : code_cache_host_impl_(code_cache_host_impl) {}
-
-  ~CodeCacheHostInterceptor() override = default;
-
-  CodeCacheHost* GetForwardingInterface() override {
-    return code_cache_host_impl_;
-  }
-
-  void DidGenerateCacheableMetadataInCacheStorage(
-      const GURL& url,
-      base::Time expected_response_time,
-      mojo_base::BigBuffer data,
-      const url::Origin& cache_storage_origin,
-      const std::string& cache_storage_cache_name) override {
-    // Send the message with an overriden, bad origin.
-    GetForwardingInterface()->DidGenerateCacheableMetadataInCacheStorage(
-        url, expected_response_time, std::move(data),
-        url::Origin::Create(GURL("https://bad.com")), cache_storage_cache_name);
-  }
-
- private:
-  // These can be held as raw pointers since we use the
-  // RenderFrameHostObserver interface to clear them before they are
-  // destroyed.
-  raw_ptr<CodeCacheHostImpl> code_cache_host_impl_;
-};
-
 class CacheStorageControlForBadOrigin
     : public storage::mojom::CacheStorageControl {
  public:
@@ -2858,86 +2827,6 @@
 
 }  // namespace
 
-// Test that forces a bad origin to be sent to CodeCacheHost's
-// DidGenerateCacheableMetadataInCacheStorage method.
-class ServiceWorkerV8CodeCacheForCacheStorageBadOriginTest
-    : public ServiceWorkerV8CodeCacheForCacheStorageTest {
- public:
-  ServiceWorkerV8CodeCacheForCacheStorageBadOriginTest()
-      : cache_storage_control_(
-            std::make_unique<CacheStorageControlForBadOrigin>()) {
-    // Register a callback to be notified of new CodeCacheHostImpl objects.
-    RenderFrameHostImpl::SetCodeCacheHostReceiverHandlerForTesting(
-        base::BindRepeating(
-            &ServiceWorkerV8CodeCacheForCacheStorageBadOriginTest::
-                CreateTestCodeCacheHost,
-            base::Unretained(this)));
-  }
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    ServiceWorkerV8CodeCacheForCacheStorageTest::SetUpCommandLine(command_line);
-    // The purpose of this test is to verify how CodeCacheHostImpl behaves
-    // when it receives an origin that is different from the site locked to the
-    // process.  In order for this to work properly on platforms like android
-    // we must explicitly enable site isolation.
-    IsolateAllSitesForTesting(command_line);
-  }
-
-  ~ServiceWorkerV8CodeCacheForCacheStorageBadOriginTest() override {
-    // Disable the callback now that this object is being destroyed.
-    RenderFrameHostImpl::SetCodeCacheHostReceiverHandlerForTesting(
-        RenderFrameHostImpl::CodeCacheHostReceiverHandler());
-  }
-
-  void CreateTestCodeCacheHost(
-      CodeCacheHostImpl* code_cache_host_impl,
-      mojo::ReceiverId receiver_id,
-      mojo::UniqueReceiverSet<blink::mojom::CodeCacheHost>& receiver_set) {
-    // Override the cache_storage context to assert that CodeCacheHostImpl
-    // does not try to access it when given a bad origin.
-    code_cache_host_impl->SetCacheStorageControlForTesting(
-        cache_storage_control_.get());
-
-    // Create an interceptor that passes a bad origin to CodeCacheHostImpl.
-    auto interceptor =
-        std::make_unique<CodeCacheHostInterceptor>(code_cache_host_impl);
-    code_cache_host_interfaces_.emplace_back(
-        receiver_set.SwapImplForTesting(receiver_id, std::move(interceptor))
-            .release(),
-        base::OnTaskRunnerDeleter(
-            base::SequencedTaskRunner::GetCurrentDefault()));
-  }
-
- private:
-  std::unique_ptr<CacheStorageControlForBadOrigin> cache_storage_control_;
-
-  // Track the original CodeCacheHost interface objects so we can delete them
-  // in the test destructor.
-  std::vector<
-      std::unique_ptr<blink::mojom::CodeCacheHost, base::OnTaskRunnerDeleter>>
-      code_cache_host_interfaces_;
-};
-
-IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CodeCacheForCacheStorageBadOriginTest,
-                       V8CacheOnCacheStorage) {
-  RenderProcessHostBadMojoMessageWaiter rph_kill_waiter(
-      shell()->web_contents()->GetPrimaryMainFrame()->GetProcess());
-
-  RegisterAndActivateServiceWorker();
-
-  // First load: fetch_event_response_via_cache.js returns |cloned_response|.
-  // The V8 code cache should not be stored in CacheStorage.
-  NavigateToTestPage();
-  WaitUntilSideDataSizeIs(0);
-
-  // Second load: This will send an invalid origin for the code cache host and
-  // should trigger a process crash.
-  NavigateToTestPageWithoutWaiting();
-
-  EXPECT_EQ("Received bad user message: Bad cache_storage origin.",
-            rph_kill_waiter.Wait());
-}
-
 class ServiceWorkerCacheStorageFullCodeCacheFromInstallEventTest
     : public ServiceWorkerV8CodeCacheForCacheStorageTest {
  public:
diff --git a/content/browser/service_worker/service_worker_host.cc b/content/browser/service_worker/service_worker_host.cc
index 6bf5c722..f1192469 100644
--- a/content/browser/service_worker/service_worker_host.cc
+++ b/content/browser/service_worker/service_worker_host.cc
@@ -200,7 +200,7 @@
   }
   code_cache_host_receivers_->Add(version_->embedded_worker()->process_id(),
                                   GetNetworkIsolationKey(),
-                                  std::move(receiver));
+                                  GetBucketStorageKey(), std::move(receiver));
 }
 
 void ServiceWorkerHost::CreateBroadcastChannelProvider(
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index bd4a6817..e7f4219 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2034,7 +2034,8 @@
 }
 
 bool WebContentsImpl::ShouldShowLoadingUI() {
-  return IsLoading() && should_show_loading_ui_;
+  return primary_frame_tree_.GetLoadingState() ==
+         LoadingState::LOADING_UI_REQUESTED;
 }
 
 bool WebContentsImpl::IsDocumentOnLoadCompletedInPrimaryMainFrame() {
@@ -6872,17 +6873,14 @@
 
 // Notifies the RenderWidgetHost instance about the fact that the page is
 // loading, or done loading.
-void WebContentsImpl::LoadingStateChanged(bool should_show_loading_ui,
-                                          LoadNotificationDetails* details) {
+void WebContentsImpl::LoadingStateChanged(LoadingState new_state) {
   if (IsBeingDestroyed())
     return;
 
-  bool is_loading = IsLoading();
-
   OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::LoadingStateChanged",
-                        "is_loading", is_loading);
+                        "loading_state", new_state);
 
-  if (!is_loading) {
+  if (new_state == LoadingState::NONE) {
     load_state_ =
         net::LoadStateWithParam(net::LOAD_STATE_IDLE, std::u16string());
     load_state_host_.clear();
@@ -6890,34 +6888,11 @@
     upload_position_ = 0;
   }
 
-  should_show_loading_ui_ = should_show_loading_ui;
-
-  if (delegate_)
-    delegate_->LoadingStateChanged(this, should_show_loading_ui_);
-  NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
-
-  std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
-  if (is_loading) {
-    TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
-        "browser,navigation", "WebContentsImpl Loading", this, "URL", url,
-        "Primary Main FrameTreeNode id",
-        GetPrimaryFrameTree().root()->frame_tree_node_id());
-    SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.DidStartLoading");
-    observers_.NotifyObservers(&WebContentsObserver::DidStartLoading);
-  } else {
-    TRACE_EVENT_NESTABLE_ASYNC_END1(
-        "browser,navigation", "WebContentsImpl Loading", this, "URL", url);
-    SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.DidStopLoading");
-    observers_.NotifyObservers(&WebContentsObserver::DidStopLoading);
+  if (delegate_) {
+    delegate_->LoadingStateChanged(
+        this, new_state == LoadingState::LOADING_UI_REQUESTED);
   }
-
-  // TODO(avi): Remove. http://crbug.com/170921
-  int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP;
-  NotificationDetails det = NotificationService::NoDetails();
-  if (details)
-    det = Details<LoadNotificationDetails>(details);
-  NotificationService::current()->Notify(
-      type, Source<NavigationController>(&GetController()), det);
+  NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
 }
 
 void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_view,
@@ -7638,14 +7613,21 @@
   return prerender_host_registry_.get();
 }
 
-void WebContentsImpl::DidStartLoading(FrameTreeNode* frame_tree_node,
-                                      bool should_show_loading_ui) {
+void WebContentsImpl::DidStartLoading(FrameTreeNode* frame_tree_node) {
   OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DidStartLoading",
                         "frame_tree_node", frame_tree_node);
-  LoadingStateChanged(
-      frame_tree_node->GetFrameType() == FrameType::kPrimaryMainFrame &&
-          should_show_loading_ui,
-      nullptr);
+
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
+      "browser,navigation", "WebContentsImpl Loading", this, "URL", "NULL",
+      "Primary Main FrameTreeNode id",
+      GetPrimaryFrameTree().root()->frame_tree_node_id());
+  SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.DidStartLoading");
+  observers_.NotifyObservers(&WebContentsObserver::DidStartLoading);
+
+  // TODO(avi): Remove. http://crbug.com/170921
+  NotificationService::current()->Notify(
+      NOTIFICATION_LOAD_START, Source<NavigationController>(&GetController()),
+      NotificationService::NoDetails());
 
   // Reset the focus state from DidStartNavigation to false if a new load starts
   // afterward, in case loading logic triggers a FocusLocationBarByDefault call.
@@ -7663,6 +7645,9 @@
 
 void WebContentsImpl::DidStopLoading() {
   OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::DidStopLoading");
+  if (IsBeingDestroyed()) {
+    return;
+  }
   std::unique_ptr<LoadNotificationDetails> details;
 
   // Use the last committed entry rather than the active one, in case a
@@ -7677,7 +7662,20 @@
         GetController().GetCurrentEntryIndex());
   }
 
-  LoadingStateChanged(true /* should_show_loading_ui */, details.get());
+  std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
+  TRACE_EVENT_NESTABLE_ASYNC_END1("browser,navigation",
+                                  "WebContentsImpl Loading", this, "URL", url);
+  SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.DidStopLoading");
+  observers_.NotifyObservers(&WebContentsObserver::DidStopLoading);
+
+  // TODO(avi): Remove. http://crbug.com/170921
+  NotificationDetails det = NotificationService::NoDetails();
+  if (details) {
+    det = Details<LoadNotificationDetails>(details.get());
+  }
+  NotificationService::current()->Notify(
+      NOTIFICATION_LOAD_STOP, Source<NavigationController>(&GetController()),
+      det);
 }
 
 void WebContentsImpl::DidChangeLoadProgressForPrimaryMainFrame() {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index cebf67d..fef8a01e 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -143,7 +143,6 @@
 class WebContentsImpl;
 class WebContentsView;
 struct AXEventNotificationDetails;
-struct LoadNotificationDetails;
 struct MHTMLGenerationParams;
 class PreloadingAttempt;
 
@@ -1026,8 +1025,8 @@
 
   // FrameTree::Delegate -------------------------------------------------------
 
-  void DidStartLoading(FrameTreeNode* frame_tree_node,
-                       bool should_show_loading_ui) override;
+  void LoadingStateChanged(LoadingState new_state) override;
+  void DidStartLoading(FrameTreeNode* frame_tree_node) override;
   void DidStopLoading() override;
   bool IsHidden() override;
   int GetOuterDelegateFrameTreeNodeId() override;
@@ -1721,12 +1720,6 @@
   // Notifies the delegate that the load progress was updated.
   void SendChangeLoadProgress();
 
-  // Notifies the delegate of a change in loading state.
-  // |details| is used to provide details on the load that just finished
-  // (but can be null if not applicable).
-  void LoadingStateChanged(bool should_show_loading_ui,
-                           LoadNotificationDetails* details);
-
   // Misc non-view stuff -------------------------------------------------------
 
   // Sets the history for a specified RenderViewHost to |history_length|
@@ -1963,11 +1956,6 @@
 
   // Data for loading state ----------------------------------------------------
 
-  // Indicates whether the current navigation should show loading UI. Only valid
-  // if |is_loading_| is true and only tracks loads in the main frame.
-  // TODO(pbos): Check navigation requests and handles instead of caching this.
-  bool should_show_loading_ui_;
-
   // Indicates the process state of the primary main frame's renderer process.
   // If the process is not live due to a crash, this will be reflected by
   // IsCrashed(), though it's possible to not be live while not indicating a
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 79d5985..97ca7f97 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -704,10 +704,10 @@
   // initial load of push_state.html, and start and stop for
   // the "navigation" triggered by history.pushState(). However, the start
   // notification for the history.pushState() navigation should set
-  // should_show_loading_ui to false.
+  // should_show_loading_ui to false, as should all stop notifications.
   EXPECT_EQ("pushState", shell()->web_contents()->GetLastCommittedURL().ref());
   EXPECT_EQ(4, delegate->loadingStateChangedCount());
-  EXPECT_EQ(3, delegate->loadingStateShowLoadingUICount());
+  EXPECT_EQ(1, delegate->loadingStateShowLoadingUICount());
 }
 
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ResourceLoadComplete) {
diff --git a/content/browser/webauth/virtual_authenticator.cc b/content/browser/webauth/virtual_authenticator.cc
index 1f32f210..aab822d 100644
--- a/content/browser/webauth/virtual_authenticator.cc
+++ b/content/browser/webauth/virtual_authenticator.cc
@@ -269,15 +269,13 @@
     std::move(callback).Run(false);
     return;
   }
-  if (!result.has_value()) {
-    std::move(callback).Run(false);
-    return;
+  if (result.has_value()) {
+    state_->InjectLargeBlob(
+        &registration->second,
+        device::LargeBlob(device::fido_parsing_utils::Materialize(*result),
+                          original_size));
   }
-  state_->InjectLargeBlob(
-      &registration->second,
-      device::LargeBlob(device::fido_parsing_utils::Materialize(*result),
-                        original_size));
-  std::move(callback).Run(true);
+  std::move(callback).Run(result.has_value());
 }
 
 }  // namespace content
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc
index 0090b211..383f82c3 100644
--- a/content/browser/webid/idp_network_request_manager.cc
+++ b/content/browser/webid/idp_network_request_manager.cc
@@ -320,12 +320,8 @@
   if (!result.has_value())
     return ParseStatus::kInvalidResponseError;
 
-  const base::Value::Dict* response = result->GetIfDict();
-  if (!response) {
-    return ParseStatus::kInvalidResponseError;
-  }
-
-  return ParseStatus::kSuccess;
+  return result->GetIfDict() ? ParseStatus::kSuccess
+                             : ParseStatus::kInvalidResponseError;
 }
 
 void OnJsonParsed(
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc
index 787f8ad..e784075 100644
--- a/content/browser/worker_host/dedicated_worker_host.cc
+++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -746,7 +746,7 @@
   RenderProcessHost* rph = GetProcessHost();
   code_cache_host_receivers_.Add(rph->GetID(),
                                  isolation_info_.network_isolation_key(),
-                                 std::move(receiver));
+                                 GetStorageKey(), std::move(receiver));
 }
 
 #if !BUILDFLAG(IS_ANDROID)
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc
index 4ad8dff6..5d461d8c 100644
--- a/content/browser/worker_host/shared_worker_host.cc
+++ b/content/browser/worker_host/shared_worker_host.cc
@@ -577,7 +577,8 @@
     mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver) {
   // Create a new CodeCacheHostImpl and bind it to the given receiver.
   code_cache_host_receivers_.Add(GetProcessHost()->GetID(),
-                                 GetNetworkIsolationKey(), std::move(receiver));
+                                 GetNetworkIsolationKey(), GetStorageKey(),
+                                 std::move(receiver));
 }
 
 void SharedWorkerHost::Destruct() {
diff --git a/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java b/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java
index cec27973..02f76bca 100644
--- a/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java
+++ b/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java
@@ -4,8 +4,10 @@
 
 package org.chromium.content.browser;
 
+import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Build;
+import android.os.Process;
 import android.view.MotionEvent;
 
 import androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures;
@@ -37,6 +39,9 @@
 @JNINamespace("content")
 public class AttributionOsLevelManager {
     private static final String TAG = "AttributionManager";
+    // TODO: replace with constant in android.Manifest.permission once it becomes available in U.
+    private static final String PERMISSION_ACCESS_ADSERVICES_ATTRIBUTION =
+            "android.permission.ACCESS_ADSERVICES_ATTRIBUTION";
     private long mNativePtr;
     private MeasurementManagerFutures mManager;
 
@@ -186,6 +191,17 @@
             AttributionOsLevelManagerJni.get().onMeasurementStateReturned(0);
             return;
         }
+        if (ContextUtils.getApplicationContext().checkPermission(
+                    PERMISSION_ACCESS_ADSERVICES_ATTRIBUTION, Process.myPid(), Process.myUid())
+                != PackageManager.PERMISSION_GRANTED) {
+            // Permission may not be granted when embedded as WebView.
+            Log.i(TAG,
+                    "OS-provided attribution support is disabled. Needs "
+                            + PERMISSION_ACCESS_ADSERVICES_ATTRIBUTION + " permission. "
+                            + "See https://developer.android.com/design-for-safety/privacy-sandbox/setup-api-access");
+            AttributionOsLevelManagerJni.get().onMeasurementStateReturned(0);
+            return;
+        }
         MeasurementManagerFutures mm = getManager();
         if (mm == null) {
             AttributionOsLevelManagerJni.get().onMeasurementStateReturned(0);
diff --git a/content/test/content_unittests_bundle_data.filelist b/content/test/content_unittests_bundle_data.filelist
index a5f7b9b..a9983f8a 100644
--- a/content/test/content_unittests_bundle_data.filelist
+++ b/content/test/content_unittests_bundle_data.filelist
@@ -79,11 +79,11 @@
 data/attribution_reporting/page_with_conversion_measurement_disabled.html.mock-http-headers
 data/attribution_reporting/page_with_conversion_redirect.html
 data/attribution_reporting/page_with_disallowed_iframe.html
-data/attribution_reporting/page_with_source_registration_and_conversion.html
-data/attribution_reporting/page_with_source_registration_and_conversion.html.mock-http-headers
 data/attribution_reporting/page_with_impression_creator.html
 data/attribution_reporting/page_with_impression_creator.html.mock-http-headers
 data/attribution_reporting/page_with_impression_creator_no_referrer.html
+data/attribution_reporting/page_with_source_registration_and_conversion.html
+data/attribution_reporting/page_with_source_registration_and_conversion.html.mock-http-headers
 data/attribution_reporting/page_without_ads_apis_ot.html
 data/attribution_reporting/register_attribution_src.js
 data/attribution_reporting/register_conversion.js
@@ -782,6 +782,7 @@
 data/gpu/webcodecs/copyTo.html
 data/gpu/webcodecs/draw-image.html
 data/gpu/webcodecs/encode-color-space.html
+data/gpu/webcodecs/encode-color-space.js
 data/gpu/webcodecs/encode-decode.html
 data/gpu/webcodecs/encode.html
 data/gpu/webcodecs/encoding-modes.html
diff --git a/content/test/data/gpu/webcodecs/encode-color-space.html b/content/test/data/gpu/webcodecs/encode-color-space.html
index 4ff25ed0..f9ee23e 100644
--- a/content/test/data/gpu/webcodecs/encode-color-space.html
+++ b/content/test/data/gpu/webcodecs/encode-color-space.html
@@ -15,238 +15,8 @@
 <head>
   <title>Encode color space test</title>
   <script src="webcodecs_common.js"></script>
+  <script src="encode-color-space.js"></script>
   <script type="text/javascript">
-    'use strict';
-
-    // Use 16x16 aligned resolution since some platforms require that.
-    // See https://crbug.com/1084702.
-    // Also, some platforms require a resolution that isn't tiny (e.g. 160) to
-    // use hardware acceleration.
-    const FRAME_WIDTH = 640;
-    const FRAME_HEIGHT = 480;
-
-    function isRec709(colorSpace) {
-      return colorSpace.primaries === 'bt709' &&
-          colorSpace.transfer === 'bt709' && colorSpace.matrix === 'bt709' &&
-          colorSpace.fullRange === false;
-    }
-
-    function isSRGB(colorSpace) {
-      return colorSpace.primaries === 'bt709' &&
-          colorSpace.transfer === 'iec61966-2-1' &&
-          colorSpace.matrix === 'rgb' && colorSpace.fullRange === true;
-    }
-
-    function isRec601(colorSpace) {
-      return colorSpace.primaries === 'smpte170m' &&
-          (colorSpace.transfer === 'smpte170m' ||
-           colorSpace.transfer === 'bt709') &&
-          colorSpace.matrix === 'smpte170m' && colorSpace.fullRange === false;
-    }
-
-    function makePixelArray(byteLength) {
-      let data = new Uint8Array(byteLength);
-      for (let i = 0; i < byteLength; i++) {
-        data[i] = i;
-      }
-      return data;
-    }
-
-    function makeFrame(type, timestamp) {
-      let init = {
-        format: 'RGBA',
-        timestamp: timestamp,
-        codedWidth: FRAME_WIDTH,
-        codedHeight: FRAME_HEIGHT
-      };
-      switch (type) {
-        case 'I420': {
-          const yuvByteLength = 1.5 * FRAME_WIDTH * FRAME_HEIGHT;
-          let data = makePixelArray(yuvByteLength);
-          return new VideoFrame(data, {...init, format: 'I420'});
-        }
-        case 'RGBA': {
-          const rgbaByteLength = 4 * FRAME_WIDTH * FRAME_HEIGHT;
-          let data = makePixelArray(rgbaByteLength);
-          return new VideoFrame(data, {...init, format: 'RGBA'});
-        }
-      }
-    }
-
-    async function main(arg) {
-      const encoderConfig = {
-        codec: arg.codec,
-        hardwareAcceleration: arg.acceleration,
-        width: FRAME_WIDTH,
-        height: FRAME_HEIGHT,
-      };
-
-      TEST.log('Starting test with arguments: ' + JSON.stringify(arg));
-      let support = await VideoEncoder.isConfigSupported(encoderConfig);
-      if (!support.supported) {
-        TEST.skip('Unsupported codec: ' + arg.codec);
-        return;
-      }
-
-      const frameDuration = 16666;
-      let inputFrames = [
-        // Use I420/BT.709 first since default macOS colorspace is sRGB.
-        makeFrame('I420', 0 * frameDuration),
-        makeFrame('I420', 1 * frameDuration),
-        makeFrame('RGBA', 2 * frameDuration),
-        makeFrame('RGBA', 3 * frameDuration),
-      ];
-      let outputChunks = [];
-      let outputMetadata = [];
-      let errors = 0;
-
-      const init = {
-        output(chunk, metadata) {
-          outputChunks.push(chunk);
-          outputMetadata.push(metadata);
-        },
-        error(e) {
-          errors++;
-          TEST.log(e);
-        }
-      };
-
-      let encoder = new VideoEncoder(init);
-      encoder.configure(encoderConfig);
-
-      for (let frame of inputFrames) {
-        encoder.encode(frame);
-        await waitForNextFrame();
-      }
-      await encoder.flush();
-      encoder.close();
-
-      TEST.assert_eq(errors, 0, 'Encoding errors occurred during the test');
-      TEST.assert_eq(outputChunks.length, 4, 'Unexpected number of outputs');
-      TEST.assert_eq(
-          outputMetadata.length, 4, 'Unexpected number of output metadata');
-
-      // I420 passthrough should preserve default rec709 color space.
-      TEST.assert_eq(inputFrames[0].format, 'I420', 'inputs[0] is I420');
-      TEST.assert(isRec709(inputFrames[0].colorSpace), 'inputs[0] is rec709');
-      TEST.assert_eq(outputChunks[0].type, 'key', 'outputs[0] is key');
-      TEST.assert(
-          'decoderConfig' in outputMetadata[0],
-          'metadata[0] has decoderConfig');
-      TEST.assert(
-          isRec709(outputMetadata[0].decoderConfig.colorSpace),
-          'metadata[0] is rec709');
-
-      // Next output may or may not be a key frame w/ metadata (up to
-      // encoder). Corresponding input is still I420 rec709, so if metadata is
-      // given, we expect same colorSpace as for the previous frame.
-      TEST.assert_eq(inputFrames[1].format, 'I420', 'inputs[1] is I420');
-      TEST.assert(isRec709(inputFrames[1].colorSpace, 'inputs[1] is rec709'));
-      if ('decoderConfig' in outputMetadata[1]) {
-        TEST.assert(
-            isRec709(outputMetadata[1].decoderConfig.colorSpace),
-            'metadata[1] is rec709');
-      }
-
-      // Next output should be a key frame and have accompanying metadata
-      // because the corresponding input format changed to RGBA, which means
-      // we libyuv will convert to I420 w/ rec601 during encoding.
-      TEST.assert_eq(inputFrames[2].format, 'RGBA', 'inputs[2] is RGBA');
-      TEST.assert(isSRGB(inputFrames[2].colorSpace), 'inputs[2] is sRGB');
-
-      // TODO(https://crbug.com/1241448): Uncomment the line below once android
-      // reliably produces a key frame at the appropriate time. For now this
-      // is covered by a DCHECK (excluding android) in video_encoder.cc.
-      // TEST.assert(outputChunks[2].type == 'key', 'outputs[2] is key');
-
-      TEST.assert(
-          'decoderConfig' in outputMetadata[2],
-          'metadata[2] has decoderConfig');
-      TEST.assert(
-          isRec601(outputMetadata[2].decoderConfig.colorSpace),
-          'metadata[2] is rec601');
-
-      // Next output may or may not be a key frame w/ metadata (up to
-      // encoder). Corresponding input is still RGBA sRGB, so if metadata is
-      // given, we expect same colorSpace as for the previous frame.
-      TEST.assert_eq(inputFrames[3].format, 'RGBA', 'inputs[3] is RGBA');
-      TEST.assert(isSRGB(inputFrames[3].colorSpace), 'inputs[3] is sRGB');
-      if ('decoderConfig' in outputMetadata[3]) {
-        TEST.assert(
-            isRec601(outputMetadata[3].decoderConfig.colorSpace),
-            'metadata[3] is rec601');
-      }
-
-      // Now decode the frames and ensure the encoder embedded the right color
-      // space information in the bitstream.
-
-      // VP8 doesn't have embedded color space information in the bitstream.
-      if (arg.codec == 'vp8')
-        return;
-
-      let decodedFrames = [];
-      const decoderInit = {
-        output(frame) {
-          decodedFrames.push(frame);
-        },
-        error(e) {
-          errors++;
-          TEST.log(e);
-        }
-      };
-
-      let decoder = new VideoDecoder(decoderInit);
-      for (var i = 0; i < outputChunks.length; ++i) {
-        if ('decoderConfig' in outputMetadata[i]) {
-          let config = {...outputMetadata[i].decoderConfig};
-
-          // Removes the color space provided by the encoder so that color space
-          // information in the underlying bitstream is exposed during decode.
-          config.colorSpace = {};
-
-          config.hardwareAcceleration = arg.acceleration;
-          decoder.configure(config);
-        }
-        decoder.decode(outputChunks[i]);
-        await waitForNextFrame();
-      }
-      await decoder.flush();
-      decoder.close();
-
-      TEST.assert_eq(
-          errors, 0, 'Encoding errors occurred during the decoding test');
-      TEST.assert_eq(
-          decodedFrames.length, outputChunks.length,
-          'Unexpected number of decoded outputs');
-
-      let colorSpace = {};
-      for (var i = 0; i < decodedFrames.length; ++i) {
-        if ('decoderConfig' in outputMetadata[i])
-          colorSpace = outputMetadata[i].decoderConfig.colorSpace;
-
-        TEST.assert_eq(
-            decodedFrames[i].colorSpace.primaries, colorSpace.primaries,
-            `Frame ${i} color primaries mismatch`);
-        TEST.assert_eq(
-            decodedFrames[i].colorSpace.matrix, colorSpace.matrix,
-            `Frame ${i} color matrix mismatch`);
-        if (decodedFrames[i].colorSpace.transfer != colorSpace.transfer) {
-          // Allow functionally equivalent matches.
-          TEST.assert(
-              colorSpace.transfer == 'smpte170m' &&
-                  decodedFrames[i].colorSpace.transfer == 'bt709',
-              `Frame ${i} color transfer mismatch`)
-        } else {
-          TEST.assert_eq(
-              decodedFrames[i].colorSpace.transfer, colorSpace.transfer,
-              `Frame ${i} color transfer mismatch`);
-        }
-        TEST.assert_eq(
-            decodedFrames[i].colorSpace.fullRange, colorSpace.fullRange,
-            `Frame ${i} color fullRange mismatch`);
-      }
-      TEST.log('Test completed');
-    }
     addManualTestButton([
       {'codec': 'avc1.42001E', 'acceleration':'prefer-software'},
       {'codec': 'avc1.42001E', 'acceleration':'prefer-hardware'},
diff --git a/content/test/data/gpu/webcodecs/encode-color-space.js b/content/test/data/gpu/webcodecs/encode-color-space.js
new file mode 100644
index 0000000..53bb6271
--- /dev/null
+++ b/content/test/data/gpu/webcodecs/encode-color-space.js
@@ -0,0 +1,258 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+// Use 16x16 aligned resolution since some platforms require that.
+// See https://crbug.com/1084702.
+// Also, some platforms require a resolution that isn't tiny (e.g. 160) to
+// use hardware acceleration.
+const FRAME_WIDTH = 640;
+const FRAME_HEIGHT = 480;
+
+function isRec709(colorSpace) {
+  return colorSpace.primaries === 'bt709' && colorSpace.transfer === 'bt709' &&
+      colorSpace.matrix === 'bt709' && colorSpace.fullRange === false;
+}
+
+function isSRGB(colorSpace) {
+  return colorSpace.primaries === 'bt709' &&
+      colorSpace.transfer === 'iec61966-2-1' && colorSpace.matrix === 'rgb' &&
+      colorSpace.fullRange === true;
+}
+
+function isRec601(colorSpace) {
+  return colorSpace.primaries === 'smpte170m' &&
+      (colorSpace.transfer === 'smpte170m' ||
+       colorSpace.transfer === 'bt709') &&
+      colorSpace.matrix === 'smpte170m' && colorSpace.fullRange === false;
+}
+
+function makePixelArray(byteLength) {
+  let data = new Uint8Array(byteLength);
+  for (let i = 0; i < byteLength; i++) {
+    data[i] = i;
+  }
+  return data;
+}
+
+function makeFrame(type, timestamp) {
+  let init = {
+    format: 'RGBA',
+    timestamp: timestamp,
+    codedWidth: FRAME_WIDTH,
+    codedHeight: FRAME_HEIGHT
+  };
+  switch (type) {
+    case 'I420': {
+      const yuvByteLength = 1.5 * FRAME_WIDTH * FRAME_HEIGHT;
+      let data = makePixelArray(yuvByteLength);
+      return new VideoFrame(data, {...init, format: 'I420'});
+    }
+    case 'RGBA': {
+      const rgbaByteLength = 4 * FRAME_WIDTH * FRAME_HEIGHT;
+      let data = makePixelArray(rgbaByteLength);
+      return new VideoFrame(data, {...init, format: 'RGBA'});
+    }
+  }
+}
+
+async function main(arg) {
+  const encoderConfig = {
+    codec: arg.codec,
+    hardwareAcceleration: arg.acceleration,
+    width: FRAME_WIDTH,
+    height: FRAME_HEIGHT,
+  };
+
+  TEST.log('Starting test with arguments: ' + JSON.stringify(arg));
+  let support = await VideoEncoder.isConfigSupported(encoderConfig);
+  if (!support.supported) {
+    TEST.skip('Unsupported codec: ' + arg.codec);
+    return;
+  }
+
+  const frameDuration = 16666;
+  let inputFrames = [
+    // Use I420/BT.709 first since default macOS colorspace is sRGB.
+    makeFrame('I420', 0 * frameDuration),
+    makeFrame('I420', 1 * frameDuration),
+    makeFrame('RGBA', 2 * frameDuration),
+    makeFrame('RGBA', 3 * frameDuration),
+  ];
+  let outputChunks = [];
+  let outputMetadata = [];
+  let errors = 0;
+
+  const init = {
+    output(chunk, metadata) {
+      outputChunks.push(chunk);
+      outputMetadata.push(metadata);
+    },
+    error(e) {
+      errors++;
+      TEST.log(e);
+    }
+  };
+
+  let encoder = new VideoEncoder(init);
+  encoder.configure(encoderConfig);
+
+  for (let frame of inputFrames) {
+    encoder.encode(frame);
+    await waitForNextFrame();
+  }
+  await encoder.flush();
+  encoder.close();
+
+  TEST.assert_eq(errors, 0, 'Encoding errors occurred during the test');
+  TEST.assert_eq(outputChunks.length, 4, 'Unexpected number of outputs');
+  TEST.assert_eq(
+      outputMetadata.length, 4, 'Unexpected number of output metadata');
+
+  // I420 passthrough should preserve default rec709 color space.
+  TEST.assert_eq(inputFrames[0].format, 'I420', 'inputs[0] is I420');
+  TEST.assert(isRec709(inputFrames[0].colorSpace), 'inputs[0] is rec709');
+  TEST.assert_eq(outputChunks[0].type, 'key', 'outputs[0] is key');
+  TEST.assert(
+      'decoderConfig' in outputMetadata[0], 'metadata[0] has decoderConfig');
+  TEST.assert(
+      isRec709(outputMetadata[0].decoderConfig.colorSpace),
+      'metadata[0] is rec709');
+
+  // Next output may or may not be a key frame w/ metadata (up to
+  // encoder). Corresponding input is still I420 rec709, so if metadata is
+  // given, we expect same colorSpace as for the previous frame.
+  TEST.assert_eq(inputFrames[1].format, 'I420', 'inputs[1] is I420');
+  TEST.assert(isRec709(inputFrames[1].colorSpace, 'inputs[1] is rec709'));
+  if ('decoderConfig' in outputMetadata[1]) {
+    TEST.assert(
+        isRec709(outputMetadata[1].decoderConfig.colorSpace),
+        'metadata[1] is rec709');
+  }
+
+  // Next output should be a key frame and have accompanying metadata
+  // because the corresponding input format changed to RGBA, which means
+  // we libyuv will convert to I420 w/ rec601 during encoding.
+  TEST.assert_eq(inputFrames[2].format, 'RGBA', 'inputs[2] is RGBA');
+  TEST.assert(isSRGB(inputFrames[2].colorSpace), 'inputs[2] is sRGB');
+
+  // TODO(https://crbug.com/1241448): Uncomment the line below once android
+  // reliably produces a key frame at the appropriate time. For now this
+  // is covered by a DCHECK (excluding android) in video_encoder.cc.
+  // TEST.assert(outputChunks[2].type == 'key', 'outputs[2] is key');
+
+  TEST.assert(
+      'decoderConfig' in outputMetadata[2], 'metadata[2] has decoderConfig');
+  TEST.assert(
+      isRec601(outputMetadata[2].decoderConfig.colorSpace),
+      'metadata[2] is rec601');
+
+  // Next output may or may not be a key frame w/ metadata (up to
+  // encoder). Corresponding input is still RGBA sRGB, so if metadata is
+  // given, we expect same colorSpace as for the previous frame.
+  TEST.assert_eq(inputFrames[3].format, 'RGBA', 'inputs[3] is RGBA');
+  TEST.assert(isSRGB(inputFrames[3].colorSpace), 'inputs[3] is sRGB');
+  if ('decoderConfig' in outputMetadata[3]) {
+    TEST.assert(
+        isRec601(outputMetadata[3].decoderConfig.colorSpace),
+        'metadata[3] is rec601');
+  }
+
+  for (let frame of inputFrames) {
+    frame.close();
+  }
+
+  // Now decode the frames and ensure the encoder embedded the right color
+  // space information in the bitstream.
+
+  // VP8 doesn't have embedded color space information in the bitstream.
+  if (arg.codec == 'vp8')
+    return;
+
+  let decodedFrames = [];
+  const decoderInit = {
+    output(frame) {
+      decodedFrames.push(frame);
+    },
+    error(e) {
+      errors++;
+      TEST.log(e);
+    }
+  };
+
+  let decoder = new VideoDecoder(decoderInit);
+  for (var i = 0; i < outputChunks.length; ++i) {
+    if ('decoderConfig' in outputMetadata[i]) {
+      let config = {...outputMetadata[i].decoderConfig};
+
+      // Removes the color space provided by the encoder so that color space
+      // information in the underlying bitstream is exposed during decode.
+      config.colorSpace = {};
+
+      config.hardwareAcceleration = arg.acceleration;
+      decoder.configure(config);
+    }
+    decoder.decode(outputChunks[i]);
+    await waitForNextFrame();
+  }
+  await decoder.flush();
+  decoder.close();
+
+  TEST.assert_eq(
+      errors, 0, 'Encoding errors occurred during the decoding test');
+  TEST.assert_eq(
+      decodedFrames.length, outputChunks.length,
+      'Unexpected number of decoded outputs');
+
+  let colorSpace = {};
+  for (var i = 0; i < decodedFrames.length; ++i) {
+    if ('decoderConfig' in outputMetadata[i]) {
+      colorSpace = outputMetadata[i].decoderConfig.colorSpace;
+    }
+
+    // It's acceptable to have no bitstream color space information.
+    if (decodedFrames[i].colorSpace.primaries != null) {
+      TEST.assert_eq(
+          decodedFrames[i].colorSpace.primaries, colorSpace.primaries,
+          `Frame ${i} color primaries mismatch`);
+    }
+
+    if (decodedFrames[i].colorSpace.matrix != null) {
+      if (decodedFrames[i].colorSpace.matrix != colorSpace.matrix) {
+        // Allow functionally equivalent matches.
+        TEST.assert(
+            colorSpace.matrix == 'smpte170m' &&
+                decodedFrames[i].colorSpace.matrix == 'bt470bg',
+            `Frame ${i} color matrix mismatch`);
+      } else {
+        TEST.assert_eq(
+            decodedFrames[i].colorSpace.matrix, colorSpace.matrix,
+            `Frame ${i} color matrix mismatch`);
+      }
+    }
+
+    if (decodedFrames[i].colorSpace.transfer != null) {
+      if (decodedFrames[i].colorSpace.transfer != colorSpace.transfer) {
+        // Allow functionally equivalent matches.
+        TEST.assert(
+            colorSpace.transfer == 'smpte170m' &&
+                decodedFrames[i].colorSpace.transfer == 'bt709',
+            `Frame ${i} color transfer mismatch`)
+      } else {
+        TEST.assert_eq(
+            decodedFrames[i].colorSpace.transfer, colorSpace.transfer,
+            `Frame ${i} color transfer mismatch`);
+      }
+    }
+
+    if (decodedFrames[i].colorSpace.fullRange != null) {
+      TEST.assert_eq(
+          decodedFrames[i].colorSpace.fullRange, colorSpace.fullRange,
+          `Frame ${i} color fullRange mismatch`);
+    }
+    decodedFrames[i].close();
+  }
+  TEST.log('Test completed');
+}
diff --git a/content/test/fuzzer/code_cache_host_mojolpm_fuzzer.cc b/content/test/fuzzer/code_cache_host_mojolpm_fuzzer.cc
index 51ecf4d..9be72b3 100644
--- a/content/test/fuzzer/code_cache_host_mojolpm_fuzzer.cc
+++ b/content/test/fuzzer/code_cache_host_mojolpm_fuzzer.cc
@@ -25,6 +25,7 @@
 #include "storage/browser/quota/quota_manager.h"
 #include "storage/browser/quota/special_storage_policy.h"
 #include "storage/browser/test/mock_special_storage_policy.h"
+#include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "third_party/blink/public/mojom/loader/code_cache.mojom-mojolpm.h"
 #include "third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h"
 #include "url/origin.h"
@@ -84,8 +85,8 @@
   void AddCodeCacheHostImpl(
       uint32_t id,
       int renderer_id,
-      const Origin& origin,
       const net::NetworkIsolationKey& key,
+      const blink::StorageKey& storage_key,
       mojo::PendingReceiver<::blink::mojom::CodeCacheHost>&& receiver);
 
   // Create and bind a new instance for fuzzing. This ensures that the new
@@ -247,11 +248,11 @@
 void CodeCacheHostTestcase::AddCodeCacheHostImpl(
     uint32_t id,
     int renderer_id,
-    const Origin& origin,
     const net::NetworkIsolationKey& nik,
+    const blink::StorageKey& storage_key,
     mojo::PendingReceiver<::blink::mojom::CodeCacheHost>&& receiver) {
   auto code_cache_host = std::make_unique<content::CodeCacheHostImpl>(
-      renderer_id, generated_code_cache_context_, nik);
+      renderer_id, generated_code_cache_context_, nik, storage_key);
   code_cache_host->SetCacheStorageControlForTesting(
       cache_storage_control_wrapper_.get());
   UniqueCodeCacheReceiverSet receivers(
@@ -296,6 +297,7 @@
   } else if (origin_id == OriginId_EMPTY) {
     origin = &origin_empty_;
   }
+  auto storage_key = blink::StorageKey::CreateFirstParty(*origin);
 
   // Use of Unretained is safe since `this` is guaranteed to live at least until
   // `run_closure` is invoked.
@@ -304,8 +306,9 @@
       ->PostTaskAndReply(
           FROM_HERE,
           base::BindOnce(&CodeCacheHostTestcase::AddCodeCacheHostImpl,
-                         base::Unretained(this), id, renderer_id, *origin,
-                         net::NetworkIsolationKey(), std::move(receiver)),
+                         base::Unretained(this), id, renderer_id,
+                         net::NetworkIsolationKey(), storage_key,
+                         std::move(receiver)),
           base::BindOnce(AddCodeCacheHostInstance, id, std::move(remote),
                          std::move(run_closure)));
 }
diff --git a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt
index 33683d3..d9350ca7 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt
@@ -122,7 +122,6 @@
 # finder:enable-unused
 
 # Temporary expectation while hardware encoder color spaces are added.
-crbug.com/1377842 [ win ] WebCodecs_EncodeColorSpace_avc1.42001E_prefer-hardware [ Failure ]
 crbug.com/1377842 [ android ] WebCodecs_EncodeColorSpace_avc1.42001E_prefer-hardware [ Failure ]
 crbug.com/1377842 [ android ] WebCodecs_EncodeColorSpace_avc1.42001E_prefer-software [ Failure ]
 crbug.com/1377842 [ android ] WebCodecs_EncodeColorSpace_vp09.00.10.08_prefer-hardware [ Failure ]
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index f6fe47a2..3ef30c37 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -291,7 +291,8 @@
 
 void TestWebContents::TestSetIsLoading(bool value) {
   if (value) {
-    DidStartLoading(GetPrimaryMainFrame()->frame_tree_node(), true);
+    DidStartLoading(GetPrimaryMainFrame()->frame_tree_node());
+    LoadingStateChanged(LoadingState::LOADING_UI_REQUESTED);
   } else {
     for (FrameTreeNode* node : primary_frame_tree_.Nodes()) {
       RenderFrameHostImpl* current_frame_host =
diff --git a/content/web_test/renderer/test_runner.cc b/content/web_test/renderer/test_runner.cc
index 67b04df..f6227cd 100644
--- a/content/web_test/renderer/test_runner.cc
+++ b/content/web_test/renderer/test_runner.cc
@@ -11,7 +11,6 @@
 #include <limits>
 #include <utility>
 
-#include "base/check_deref.h"
 #include "base/command_line.h"
 #include "base/containers/contains.h"
 #include "base/containers/cxx20_erase.h"
@@ -53,7 +52,6 @@
 #include "third_party/blink/public/mojom/app_banner/app_banner.mojom.h"
 #include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
 #include "third_party/blink/public/platform/file_path_conversion.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/platform/web_cache.h"
 #include "third_party/blink/public/platform/web_data.h"
 #include "third_party/blink/public/platform/web_isolated_world_info.h"
@@ -305,7 +303,6 @@
   void RemoveSpellCheckResolvedCallback();
   void RemoveWebPageOverlay();
   void ResolveBeforeInstallPromptPromise(const std::string& platform);
-  void RunIdleTasks(v8::Local<v8::Function> callback);
   void SendBluetoothManualChooserEvent(const std::string& event,
                                        const std::string& argument);
   void SetAcceptLanguages(const std::string& accept_languages);
@@ -676,10 +673,6 @@
                  &TestRunnerBindings::RemoveWebPageOverlay)
       .SetMethod("resolveBeforeInstallPromptPromise",
                  &TestRunnerBindings::ResolveBeforeInstallPromptPromise)
-      // Immediately run all pending idle tasks, including all pending
-      // requestIdleCallback calls.  Invoke the callback when all
-      // idle tasks are complete.
-      .SetMethod("runIdleTasks", &TestRunnerBindings::RunIdleTasks)
       .SetMethod("selectionAsMarkup", &TestRunnerBindings::SelectionAsMarkup)
 
       // The Bluetooth functions are specified at
@@ -2045,15 +2038,6 @@
   }
 }
 
-void TestRunnerBindings::RunIdleTasks(v8::Local<v8::Function> v8_callback) {
-  if (invalid_)
-    return;
-  blink::scheduler::WebThreadScheduler* scheduler =
-      content::RenderThreadImpl::current()->GetWebMainThreadScheduler();
-  blink::scheduler::RunIdleTasksForTesting(
-      CHECK_DEREF(scheduler), WrapV8Closure(std::move(v8_callback)));
-}
-
 std::string TestRunnerBindings::PlatformName() {
   if (invalid_)
     return {};
diff --git a/device/fido/virtual_fido_device_authenticator.cc b/device/fido/virtual_fido_device_authenticator.cc
index d2ad4e30d..22e832d 100644
--- a/device/fido/virtual_fido_device_authenticator.cc
+++ b/device/fido/virtual_fido_device_authenticator.cc
@@ -6,6 +6,7 @@
 #include "device/fido/ctap_get_assertion_request.h"
 #include "device/fido/fido_device_authenticator.h"
 #include "device/fido/fido_request_handler_base.h"
+#include "device/fido/fido_types.h"
 
 namespace device {
 
diff --git a/docs/security/compromised-renderers.md b/docs/security/compromised-renderers.md
index 2830a95..660a4ca 100644
--- a/docs/security/compromised-renderers.md
+++ b/docs/security/compromised-renderers.md
@@ -234,9 +234,6 @@
 used by scripts executed in cross-site execution contexts.
 
 Protection techniques:
-- Validating origins sent in IPCs from a renderer process by using
-  `CanAccessDataForOrigin` in
-  `CodeCacheHostImpl::DidGenerateCacheableMetadataInCacheStorage`.
 - Using trustworthy, browser-side origin lock while writing to and fetching from
   the code cache by using `ChildProcessSecurityPolicyImpl::GetOriginLock` in
   `GetSecondaryKeyForCodeCache` in
diff --git a/extensions/browser/extension_function_dispatcher.cc b/extensions/browser/extension_function_dispatcher.cc
index 18b71ebd..39113680 100644
--- a/extensions/browser/extension_function_dispatcher.cc
+++ b/extensions/browser/extension_function_dispatcher.cc
@@ -29,6 +29,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/result_codes.h"
+#include "content/public/common/url_constants.h"
 #include "extensions/browser/api_activity_monitor.h"
 #include "extensions/browser/bad_message.h"
 #include "extensions/browser/content_script_tracker.h"
@@ -41,6 +42,7 @@
 #include "extensions/browser/process_map.h"
 #include "extensions/browser/quota_service.h"
 #include "extensions/common/constants.h"
+#include "extensions/common/context_type_adapter.h"
 #include "extensions/common/extension_api.h"
 #include "extensions/common/extension_messages.h"
 #include "extensions/common/extension_set.h"
@@ -489,11 +491,41 @@
     extension = registry->enabled_extensions().GetHostedAppByURL(*rfh_url);
   }
 
+  Feature::Context context_type =
+      MojomContextToFeatureContext(params.context_type);
+  if (!process_map->CanProcessHostContextType(extension, render_process_id,
+                                              context_type)) {
+    // TODO(https://crbug.com/1186557): Ideally, we'd be able to mark some
+    // of these as bad messages. We can't do that in all cases because there
+    // are times some of these might legitimately fail (for instance, during
+    // extension unload), but there are others that should never, ever happen
+    // (privileged extension contexts in web processes).
+    static constexpr char kInvalidContextType[] =
+        "Invalid context type provided.";
+    ResponseCallbackOnError(std::move(callback), ExtensionFunction::FAILED,
+                            kInvalidContextType);
+    return;
+  }
+
+  if (context_type == Feature::WEBUI_UNTRUSTED_CONTEXT) {
+    // TODO(https://crbug.com/1435575): We should, at minimum, be using an
+    // origin here. It'd be even better if we could have a more robust way of
+    // checking that a process can host untrusted webui.
+    if (extension || !rfh_url ||
+        !rfh_url->SchemeIs(content::kChromeUIUntrustedScheme)) {
+      constexpr char kInvalidWebUiUntrustedContext[] =
+          "Context indicated it was untrusted webui, but is invalid.";
+      ResponseCallbackOnError(std::move(callback), ExtensionFunction::FAILED,
+                              kInvalidWebUiUntrustedContext);
+      return;
+    }
+  }
+
   const bool is_worker_request = IsRequestFromServiceWorker(params);
 
   scoped_refptr<ExtensionFunction> function = CreateExtensionFunction(
       params, extension, render_process_id, is_worker_request, rfh_url,
-      *process_map, ExtensionAPI::GetSharedInstance(), std::move(callback),
+      context_type, ExtensionAPI::GetSharedInstance(), std::move(callback),
       render_frame_host);
   if (!function.get())
     return;
@@ -660,7 +692,7 @@
     int requesting_process_id,
     bool is_worker_request,
     const GURL* rfh_url,
-    const ProcessMap& process_map,
+    Feature::Context context_type,
     ExtensionAPI* api,
     ExtensionFunction::ResponseCallback callback,
     content::RenderFrameHost* render_frame_host) {
@@ -677,9 +709,6 @@
 
   function->SetArgs(params.arguments.Clone());
 
-  const Feature::Context context_type = process_map.GetMostLikelyContextType(
-      extension, requesting_process_id, rfh_url);
-
   // Determine the source URL. When possible, prefer fetching this value from
   // the RenderFrameHost, but fallback to the value in the `params` object if
   // necessary.
diff --git a/extensions/browser/extension_function_dispatcher.h b/extensions/browser/extension_function_dispatcher.h
index f662a80..19a2fb7 100644
--- a/extensions/browser/extension_function_dispatcher.h
+++ b/extensions/browser/extension_function_dispatcher.h
@@ -13,6 +13,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "extensions/browser/extension_function.h"
+#include "extensions/common/features/feature.h"
 #include "extensions/common/mojom/frame.mojom.h"
 #include "ipc/ipc_sender.h"
 
@@ -26,7 +27,6 @@
 
 class Extension;
 class ExtensionAPI;
-class ProcessMap;
 class WindowController;
 
 // ExtensionFunctionDispatcher receives requests to execute functions from
@@ -139,7 +139,7 @@
       int requesting_process_id,
       bool is_worker_request,
       const GURL* rfh_url,
-      const ProcessMap& process_map,
+      Feature::Context context_type,
       ExtensionAPI* api,
       ExtensionFunction::ResponseCallback callback,
       content::RenderFrameHost* render_frame_host);
diff --git a/extensions/browser/process_map.cc b/extensions/browser/process_map.cc
index 4f2b83b0..472bad1 100644
--- a/extensions/browser/process_map.cc
+++ b/extensions/browser/process_map.cc
@@ -16,6 +16,34 @@
 
 namespace extensions {
 
+namespace {
+
+// Returns true if `process_id` is associated with a WebUI process.
+bool ProcessHasWebUIBindings(int process_id) {
+  // TODO(crbug.com/1055656): HasWebUIBindings does not always return true for
+  // WebUIs. This should be changed to use something else.
+  return content::ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
+      process_id);
+}
+
+// Returns true if `process_id` is associated with a webview owned by the
+// extension with the specified `extension_id`.
+bool IsWebViewProcessForExtension(int process_id,
+                                  const ExtensionId& extension_id) {
+  WebViewRendererState* web_view_state = WebViewRendererState::GetInstance();
+  if (!web_view_state->IsGuest(process_id)) {
+    return false;
+  }
+
+  std::string webview_owner;
+  int owner_process_id = -1;
+  bool found_info = web_view_state->GetOwnerInfo(process_id, &owner_process_id,
+                                                 &webview_owner);
+  return found_info && webview_owner == extension_id;
+}
+
+}  // namespace
+
 // Item
 struct ProcessMap::Item {
   Item(const std::string& extension_id,
@@ -120,6 +148,61 @@
          !is_lock_screen_context_;
 }
 
+bool ProcessMap::CanProcessHostContextType(const Extension* extension,
+                                           int process_id,
+                                           Feature::Context context_type) {
+  switch (context_type) {
+    case Feature::UNSPECIFIED_CONTEXT:
+      // We never consider unspecified contexts valid. Even though they would be
+      // permissionless, they should never be able to make a request to the
+      // browser.
+      return false;
+    case Feature::OFFSCREEN_EXTENSION_CONTEXT:
+    case Feature::BLESSED_EXTENSION_CONTEXT:
+      // Offscreen documents run in the main extension process, so both of these
+      // require a privileged extension process.
+      return extension && IsPrivilegedExtensionProcess(*extension, process_id);
+    case Feature::UNBLESSED_EXTENSION_CONTEXT:
+      return extension &&
+             IsWebViewProcessForExtension(process_id, extension->id());
+    case Feature::CONTENT_SCRIPT_CONTEXT:
+    case Feature::USER_SCRIPT_CONTEXT:
+      // Currently, we assume any process can host a content script or user
+      // script.
+      // TODO(crbug.com/1186557): This could be better by looking at
+      // ContentScriptTracker for (which also means hooking user scripts up to
+      // ContentScriptTracker).
+      return !!extension;
+    case Feature::LOCK_SCREEN_EXTENSION_CONTEXT:
+      // Lock screen contexts are essentially blessed contexts that run on the
+      // lock screen profile. We don't run component hosted apps there, so no
+      // need to allow those.
+      return is_lock_screen_context_ && extension &&
+             !extension->is_hosted_app() &&
+             Contains(extension->id(), process_id);
+    case Feature::BLESSED_WEB_PAGE_CONTEXT:
+      // A blessed web page is a (non-component) hosted app process.
+      return extension && extension->is_hosted_app() &&
+             extension->location() != mojom::ManifestLocation::kComponent &&
+             Contains(extension->id(), process_id);
+    case Feature::WEBUI_UNTRUSTED_CONTEXT:
+      // Unfortunately, we have no way of checking if a *process* can host
+      // untrusted webui contexts. Callers should look at (ideally, the
+      // browser-verified) origin.
+      [[fallthrough]];
+    case Feature::WEB_PAGE_CONTEXT:
+      // Any context not associated with an extension, not running in an
+      // extension process, and without webui bindings can be considered a
+      // web page process.
+      return !extension && !Contains(process_id) &&
+             !ProcessHasWebUIBindings(process_id);
+    case Feature::WEBUI_CONTEXT:
+      // Don't consider extensions in webui (like content scripts) to be
+      // webui.
+      return !extension && ProcessHasWebUIBindings(process_id);
+  }
+}
+
 Feature::Context ProcessMap::GetMostLikelyContextType(
     const Extension* extension,
     int process_id,
@@ -130,10 +213,7 @@
   // TODO(crbug.com/1055168): Move this into the !extension if statement below
   // or document why we want to return WEBUI_CONTEXT for content scripts in
   // WebUIs.
-  // TODO(crbug.com/1055656): HasWebUIBindings does not always return true for
-  // WebUIs. This should be changed to use something else.
-  if (content::ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
-          process_id)) {
+  if (ProcessHasWebUIBindings(process_id)) {
     return Feature::WEBUI_CONTEXT;
   }
 
@@ -151,17 +231,10 @@
     // frame in a webview.
     // We (deliberately) don't add webview-hosted frames to the process map and
     // don't classify them as BLESSED_EXTENSION_CONTEXTs.
-    WebViewRendererState* web_view_state = WebViewRendererState::GetInstance();
     if (url && extension->origin().IsSameOriginWith(*url) &&
-        web_view_state->IsGuest(process_id)) {
-      std::string webview_owner;
-      int owner_process_id = -1;
-      bool found_info = web_view_state->GetOwnerInfo(
-          process_id, &owner_process_id, &webview_owner);
-      if (found_info && webview_owner == extension->id()) {
-        // Yep, it's an extension frame in a webview.
-        return Feature::UNBLESSED_EXTENSION_CONTEXT;
-      }
+        IsWebViewProcessForExtension(process_id, extension->id())) {
+      // Yep, it's an extension frame in a webview.
+      return Feature::UNBLESSED_EXTENSION_CONTEXT;
     }
 
     // Otherwise, it's a content script (the context in which an extension can
diff --git a/extensions/browser/process_map.h b/extensions/browser/process_map.h
index dc899512..4e4074d 100644
--- a/extensions/browser/process_map.h
+++ b/extensions/browser/process_map.h
@@ -119,6 +119,40 @@
   // on the web.
   bool IsPrivilegedExtensionProcess(const Extension& extension, int process_id);
 
+  // Returns true if the given `context_type` - associated with the given
+  // `extension`, if provided - is a valid for the process with the given
+  // `process_id`.
+  //
+  // Use this method to validate whether a context type claimed by the renderer
+  // is possible.
+  //
+  // Important notes:
+  // - This will return false for any invalid combinations. For instance, it is
+  //   never possible to have a web page context associated with an extension.
+  // - This relies on certain architectural guarantees. For instance, web pages
+  //   should never, ever share a process with an extension or with webui.
+  // - Multiple context types (with some difference in privilege levels) may be
+  //   valid for a given process and extension pairing. For instance, a
+  //   privileged extension process could host any of blessed extension
+  //   contexts, offscreen document contexts, and content script contexts. Thus,
+  //   a compromised renderer could, in theory, claim a more privileged context
+  //   (such as claiming to be a blessed extension context from an offscreen
+  //   document context). This *is not* a security bug; if the renderer is
+  //   compromised and could host blessed extension contexts, it could simply
+  //   create (or hijack) one.
+  // - This only looks at process-level guarantees. Thus, for contexts like
+  //   untrusted webui (chrome-untrusted:// pages), the caller is responsible
+  //   for doing additional verification (such as checking the origin).
+  //
+  // This method is preferable to GetMostLikelyContextType() as it allows the
+  // renderer to supply a context type to differentiate between possible
+  // contexts in the non-compromised-renderer case, whereas
+  // GetMostLikelyContextType() cannot (and has to just "pick" a possible
+  // context type).
+  bool CanProcessHostContextType(const Extension* extension,
+                                 int process_id,
+                                 Feature::Context context_type);
+
   // Gets the most likely context type for the process with ID |process_id|
   // which hosts Extension |extension|, if any (may be nullptr). Context types
   // are renderer (JavaScript) concepts but the browser can do a decent job in
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn
index 1b4f4835b..c2336fad 100644
--- a/extensions/common/BUILD.gn
+++ b/extensions/common/BUILD.gn
@@ -236,6 +236,8 @@
     "content_script_injection_url_getter.cc",
     "content_script_injection_url_getter.h",
     "context_data.h",
+    "context_type_adapter.cc",
+    "context_type_adapter.h",
     "cors_util.cc",
     "cors_util.h",
     "csp_validator.cc",
diff --git a/extensions/common/context_type_adapter.cc b/extensions/common/context_type_adapter.cc
new file mode 100644
index 0000000..82226a3
--- /dev/null
+++ b/extensions/common/context_type_adapter.cc
@@ -0,0 +1,72 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/context_type_adapter.h"
+
+#include "base/notreached.h"
+#include "extensions/common/features/feature.h"
+#include "extensions/common/mojom/frame.mojom.h"
+
+namespace extensions {
+
+mojom::ContextType FeatureContextToMojomContext(
+    Feature::Context feature_context) {
+  switch (feature_context) {
+    case Feature::BLESSED_EXTENSION_CONTEXT:
+      return mojom::ContextType::kPrivilegedExtension;
+    case Feature::UNBLESSED_EXTENSION_CONTEXT:
+      return mojom::ContextType::kUnprivilegedExtension;
+    case Feature::CONTENT_SCRIPT_CONTEXT:
+      return mojom::ContextType::kContentScript;
+    case Feature::WEB_PAGE_CONTEXT:
+      return mojom::ContextType::kWebPage;
+    case Feature::BLESSED_WEB_PAGE_CONTEXT:
+      return mojom::ContextType::kPrivilegedWebPage;
+    case Feature::WEBUI_CONTEXT:
+      return mojom::ContextType::kWebUi;
+    case Feature::WEBUI_UNTRUSTED_CONTEXT:
+      return mojom::ContextType::kUntrustedWebUi;
+    case Feature::LOCK_SCREEN_EXTENSION_CONTEXT:
+      return mojom::ContextType::kLockscreenExtension;
+    case Feature::OFFSCREEN_EXTENSION_CONTEXT:
+      return mojom::ContextType::kOffscreenExtension;
+    case Feature::USER_SCRIPT_CONTEXT:
+      return mojom::ContextType::kUserScript;
+    case Feature::UNSPECIFIED_CONTEXT:
+      // We never expect to receive an unspecified context. We separate this
+      // NOTREACHED_NORETURN() (and don't just `break;`) to get separate reports
+      // if we do ever hit this.
+      NOTREACHED_NORETURN();
+  }
+
+  NOTREACHED_NORETURN();
+}
+
+Feature::Context MojomContextToFeatureContext(
+    mojom::ContextType mojom_context) {
+  switch (mojom_context) {
+    case mojom::ContextType::kPrivilegedExtension:
+      return Feature::BLESSED_EXTENSION_CONTEXT;
+    case mojom::ContextType::kUnprivilegedExtension:
+      return Feature::UNBLESSED_EXTENSION_CONTEXT;
+    case mojom::ContextType::kContentScript:
+      return Feature::CONTENT_SCRIPT_CONTEXT;
+    case mojom::ContextType::kWebPage:
+      return Feature::WEB_PAGE_CONTEXT;
+    case mojom::ContextType::kPrivilegedWebPage:
+      return Feature::BLESSED_WEB_PAGE_CONTEXT;
+    case mojom::ContextType::kWebUi:
+      return Feature::WEBUI_CONTEXT;
+    case mojom::ContextType::kUntrustedWebUi:
+      return Feature::WEBUI_UNTRUSTED_CONTEXT;
+    case mojom::ContextType::kLockscreenExtension:
+      return Feature::LOCK_SCREEN_EXTENSION_CONTEXT;
+    case mojom::ContextType::kOffscreenExtension:
+      return Feature::OFFSCREEN_EXTENSION_CONTEXT;
+    case mojom::ContextType::kUserScript:
+      return Feature::USER_SCRIPT_CONTEXT;
+  }
+}
+
+}  // namespace extensions
diff --git a/extensions/common/context_type_adapter.h b/extensions/common/context_type_adapter.h
new file mode 100644
index 0000000..df82a0c
--- /dev/null
+++ b/extensions/common/context_type_adapter.h
@@ -0,0 +1,23 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_CONTEXT_TYPE_ADAPTER_H_
+#define EXTENSIONS_COMMON_CONTEXT_TYPE_ADAPTER_H_
+
+#include "extensions/common/features/feature.h"
+#include "extensions/common/mojom/frame.mojom-forward.h"
+
+namespace extensions {
+
+// Converts a Feature::Context into a mojom::ContextType.
+// NOTE: Feature::UNSPECIFIED_CONTEXT is unsupported and will crash.
+mojom::ContextType FeatureContextToMojomContext(
+    Feature::Context feature_context);
+
+// Converts a mojom::ContextType into a Feature::Context.
+Feature::Context MojomContextToFeatureContext(mojom::ContextType mojom_context);
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_CONTEXT_TYPE_ADAPTER_H_
diff --git a/extensions/common/mojom/frame.mojom b/extensions/common/mojom/frame.mojom
index 1a26e78..e89e5c9 100644
--- a/extensions/common/mojom/frame.mojom
+++ b/extensions/common/mojom/frame.mojom
@@ -16,6 +16,21 @@
 import "url/mojom/url.mojom";
 import "third_party/blink/public/mojom/devtools/console_message.mojom";
 
+// The context type associated with a running JS context.
+// This should match the values in Feature::Context.
+enum ContextType {
+  kPrivilegedExtension,
+  kUnprivilegedExtension,
+  kContentScript,
+  kWebPage,
+  kPrivilegedWebPage,
+  kWebUi,
+  kUntrustedWebUi,
+  kLockscreenExtension,
+  kOffscreenExtension,
+  kUserScript,
+};
+
 // Allows an extension to execute code in a tab.
 struct ExecuteCodeParams {
   // The ID of the requesting injection host.
@@ -49,6 +64,11 @@
   // in which case extension_id will indicate the ID of the associated
   // extension. Or, they can originate from hosted apps or normal web pages.
   url.mojom.Url source_url;
+  // The context type associated with the sender. Note that this is *not* to
+  // be treated as a security boundary (since it might come from a compromised
+  // renderer), but can be used to differentiate between different types of
+  // contexts within the same renderer (e.g. content script vs web page).
+  ContextType context_type;
   // Unique request id to match requests and responses.
   int32 request_id;
   // True if request has a callback specified.
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc
index 77a7de8e..5c04c65 100644
--- a/extensions/renderer/native_extension_bindings_system.cc
+++ b/extensions/renderer/native_extension_bindings_system.cc
@@ -14,6 +14,7 @@
 #include "components/crx_file/id_util.h"
 #include "content/public/common/content_switches.h"
 #include "extensions/common/constants.h"
+#include "extensions/common/context_type_adapter.h"
 #include "extensions/common/extension_api.h"
 #include "extensions/common/extension_messages.h"
 #include "extensions/common/features/feature.h"
@@ -840,6 +841,10 @@
     std::unique_ptr<APIRequestHandler::Request> request,
     v8::Local<v8::Context> context) {
   ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);
+  CHECK_NE(Feature::UNSPECIFIED_CONTEXT, script_context->context_type())
+      << "Attempting to send a request from an unspecified context type. "
+      << "Request: " << request->method_name
+      << ", Context: " << script_context->GetDebugString();
 
   GURL url;
   blink::WebLocalFrame* frame = script_context->web_frame();
@@ -853,6 +858,8 @@
   params->arguments = std::move(request->arguments_list);
   params->extension_id = script_context->GetExtensionID();
   params->source_url = url;
+  params->context_type =
+      FeatureContextToMojomContext(script_context->context_type());
   params->request_id = request->request_id;
   params->has_callback = request->has_async_response_handler;
   params->user_gesture = request->has_user_gesture;
diff --git a/fuchsia_web/runners/cast/test/BUILD.gn b/fuchsia_web/runners/cast/test/BUILD.gn
index 7aa2f6a..1671db0 100644
--- a/fuchsia_web/runners/cast/test/BUILD.gn
+++ b/fuchsia_web/runners/cast/test/BUILD.gn
@@ -55,7 +55,6 @@
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.media:fuchsia.media_hlcpp",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.memorypressure:fuchsia.memorypressure_hlcpp",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.net.interfaces:fuchsia.net.interfaces_hlcpp",
-    "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.sys:fuchsia.sys_hlcpp",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.sysmem:fuchsia.sysmem_hlcpp",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.tracing.provider:fuchsia.tracing.provider_hlcpp",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.composition:fuchsia.ui.composition_hlcpp",
diff --git a/fuchsia_web/runners/common/web_component.h b/fuchsia_web/runners/common/web_component.h
index 4dd4621..b4951b4 100644
--- a/fuchsia_web/runners/common/web_component.h
+++ b/fuchsia_web/runners/common/web_component.h
@@ -5,7 +5,6 @@
 #ifndef FUCHSIA_WEB_RUNNERS_COMMON_WEB_COMPONENT_H_
 #define FUCHSIA_WEB_RUNNERS_COMMON_WEB_COMPONENT_H_
 
-#include <fuchsia/sys/cpp/fidl.h>
 #include <fuchsia/ui/app/cpp/fidl.h>
 #include <fuchsia/web/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
diff --git a/fuchsia_web/webinstance_host/web_instance_host.cc b/fuchsia_web/webinstance_host/web_instance_host.cc
index f97b779b..c7cfb52b 100644
--- a/fuchsia_web/webinstance_host/web_instance_host.cc
+++ b/fuchsia_web/webinstance_host/web_instance_host.cc
@@ -6,7 +6,6 @@
 
 #include <fuchsia/component/decl/cpp/fidl.h>
 #include <fuchsia/io/cpp/fidl.h>
-#include <fuchsia/sys/cpp/fidl.h>
 #include <lib/fit/function.h>
 #include <lib/sys/cpp/component_context.h>
 #include <lib/sys/cpp/outgoing_directory.h>
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md
index e3ccaa75..a45954f 100644
--- a/infra/config/generated/cq-builders.md
+++ b/infra/config/generated/cq-builders.md
@@ -81,6 +81,8 @@
 
 * [win-libfuzzer-asan-rel](https://ci.chromium.org/p/chromium/builders/try/win-libfuzzer-asan-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""win-libfuzzer-asan-rel""))
 
+* [win-presubmit](https://ci.chromium.org/p/chromium/builders/try/win-presubmit) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""win-presubmit""))
+
 * [win-rel](https://ci.chromium.org/p/chromium/builders/try/win-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""win-rel""))
 
 * [win_chromium_compile_dbg_ng](https://ci.chromium.org/p/chromium/builders/try/win_chromium_compile_dbg_ng) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""win_chromium_compile_dbg_ng""))
@@ -550,6 +552,3 @@
 * [mac12-arm64-rel](https://ci.chromium.org/p/chromium/builders/try/mac12-arm64-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""mac12-arm64-rel""))
   * Experiment percentage: 100.0
 
-* [win-presubmit](https://ci.chromium.org/p/chromium/builders/try/win-presubmit) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""win-presubmit""))
-  * Experiment percentage: 100.0
-
diff --git a/infra/config/generated/cq-usage/default.cfg b/infra/config/generated/cq-usage/default.cfg
index e9763a4..910e4c137 100644
--- a/infra/config/generated/cq-usage/default.cfg
+++ b/infra/config/generated/cq-usage/default.cfg
@@ -110,6 +110,9 @@
         name: "chromium/try/win-libfuzzer-asan-rel"
       }
       builders {
+        name: "chromium/try/win-presubmit"
+      }
+      builders {
         name: "chromium/try/win-rel"
       }
       builders {
diff --git a/infra/config/generated/cq-usage/full.cfg b/infra/config/generated/cq-usage/full.cfg
index c94f2c7..c9151f8 100644
--- a/infra/config/generated/cq-usage/full.cfg
+++ b/infra/config/generated/cq-usage/full.cfg
@@ -2518,6 +2518,9 @@
         }
       }
       builders {
+        name: "chromium/try/win-presubmit"
+      }
+      builders {
         name: "chromium/try/win-rel"
         location_filters {
           gerrit_host_regexp: ".*"
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg
index c7cef6b..834c89db 100644
--- a/infra/config/generated/luci/commit-queue.cfg
+++ b/infra/config/generated/luci/commit-queue.cfg
@@ -3950,7 +3950,6 @@
       }
       builders {
         name: "chromium/try/win-presubmit"
-        experiment_percentage: 100
       }
       builders {
         name: "chromium/try/win-rel"
@@ -4311,7 +4310,6 @@
     projects {
       name: "chromium/src"
       ref_regexp: "refs/branch-heads/.*"
-      ref_regexp_exclude: "refs/branch-heads/5005"
       ref_regexp_exclude: "refs/branch-heads/5359"
       ref_regexp_exclude: "refs/branch-heads/5414"
       ref_regexp_exclude: "refs/branch-heads/5481"
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 1d3d3a76..a31844ec 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -47022,7 +47022,10 @@
         '    ]'
         '  },'
         '  "recipe": "presubmit",'
-        '  "repo_name": "chromium"'
+        '  "repo_name": "chromium",'
+        '  "sheriff_rotations": ['
+        '    "chromium"'
+        '  ]'
         '}'
       execution_timeout_secs: 21600
       build_numbers: YES
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index 4dd4fd47..5450a71 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -272,10 +272,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -1239,10 +1235,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -1989,10 +1981,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -2466,10 +2454,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -2825,10 +2809,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -3435,10 +3415,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -3779,10 +3755,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -4228,10 +4200,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -4573,10 +4541,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -5126,10 +5090,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -5519,10 +5479,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -5928,10 +5884,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -6274,10 +6226,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -6731,10 +6679,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -7295,10 +7239,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -7769,10 +7709,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -8150,10 +8086,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -8519,10 +8451,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -9012,10 +8940,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -9861,10 +9785,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -10292,10 +10212,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -10697,10 +10613,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -11092,10 +11004,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -11716,10 +11624,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -12084,10 +11988,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -12498,10 +12398,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -12922,10 +12818,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -13366,10 +13258,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -13710,10 +13598,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -14199,10 +14083,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -14574,10 +14454,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -14953,10 +14829,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -15487,10 +15359,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -15861,10 +15729,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -16276,10 +16140,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -16655,10 +16515,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -17065,10 +16921,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
@@ -17417,10 +17269,6 @@
     links {
       name: "Branch Consoles"
       links {
-        text: "m102"
-        url: "/p/chromium-m102/g/main/console"
-      }
-      links {
         text: "m108"
         url: "/p/chromium-m108/g/main/console"
       }
diff --git a/infra/config/generated/luci/realms.cfg b/infra/config/generated/luci/realms.cfg
index c58a159..ff45aba7 100644
--- a/infra/config/generated/luci/realms.cfg
+++ b/infra/config/generated/luci/realms.cfg
@@ -369,7 +369,6 @@
   name: "pools/ci"
   bindings {
     role: "role/swarming.poolUser"
-    principals: "project:chromium-m102"
     principals: "project:chromium-m108"
     principals: "project:chromium-m109"
     principals: "project:chromium-m110"
@@ -422,7 +421,6 @@
   bindings {
     role: "role/swarming.poolUser"
     principals: "group:chromium-led-users"
-    principals: "project:chromium-m102"
     principals: "project:chromium-m108"
     principals: "project:chromium-m109"
     principals: "project:chromium-m110"
diff --git a/infra/config/generated/sheriff-rotations/chromium.txt b/infra/config/generated/sheriff-rotations/chromium.txt
index 89e72cd..af9671f 100644
--- a/infra/config/generated/sheriff-rotations/chromium.txt
+++ b/infra/config/generated/sheriff-rotations/chromium.txt
@@ -131,6 +131,7 @@
 ci/win-archive-rel
 ci/win-asan
 ci/win-official
+ci/win-presubmit
 ci/win32-archive-dbg
 ci/win32-archive-rel
 ci/win32-official
diff --git a/infra/config/milestones.json b/infra/config/milestones.json
index 2581b7a..0c0be92 100644
--- a/infra/config/milestones.json
+++ b/infra/config/milestones.json
@@ -1,9 +1,4 @@
 {
-    "102": {
-        "name": "m102",
-        "project": "chromium-m102",
-        "ref": "refs/branch-heads/5005"
-    },
     "108": {
         "name": "m108",
         "project": "chromium-m108",
diff --git a/infra/config/subprojects/chromium/ci/checks.star b/infra/config/subprojects/chromium/ci/checks.star
index 5b25e072..1bb7fbb9 100644
--- a/infra/config/subprojects/chromium/ci/checks.star
+++ b/infra/config/subprojects/chromium/ci/checks.star
@@ -44,10 +44,7 @@
     builderless = True,
     cores = 32,
     os = os.WINDOWS_DEFAULT,
-
-    # Adding sheriff rotations to none for the time being until we confirm
-    # this works
-    sheriff_rotations = None,
+    sheriff_rotations = sheriff_rotations.CHROMIUM,
     console_view_entry = consoles.console_view_entry(
         console_view = "checks",
         category = "presubmit",
diff --git a/infra/config/subprojects/chromium/try/presubmit.star b/infra/config/subprojects/chromium/try/presubmit.star
index 96196043b..8bc13a21 100644
--- a/infra/config/subprojects/chromium/try/presubmit.star
+++ b/infra/config/subprojects/chromium/try/presubmit.star
@@ -154,7 +154,6 @@
     },
     tryjob = try_.job(
         disable_reuse = False,
-        experiment_percentage = 100,
     ),
 )
 
diff --git a/ios/build/chrome_build.gni b/ios/build/chrome_build.gni
index 3511341..5e7abb5 100644
--- a/ios/build/chrome_build.gni
+++ b/ios/build/chrome_build.gni
@@ -12,16 +12,10 @@
 assert(xcode_version_int >= 1310, "Xcode 13.1 or higher is required.")
 
 declare_args() {
-  # Enable widget extensions.
+  # Enable notification center widget extensions.
   ios_enable_content_widget_extension = true
   ios_enable_search_widget_extension = true
 
-  # Enable iOS 14, WidgetKit extension.
-  ios_enable_widget_kit_extension = true
-
-  # Enable iOS 16 lockscreen extensions.
-  ios_enable_lockscreen_extension = true
-
   # Enable share extension.
   ios_enable_share_extension = true
 
@@ -31,6 +25,15 @@
   # Enable intents extension.
   ios_enable_intents_extension = false
 
+  # Enable iOS 14, WidgetKit extension.
+  ios_enable_widget_kit_extension = true
+
+  # Enable iOS 16 lockscreen widget in WidgetKit extension.
+  ios_enable_lockscreen_widget = true
+
+  # Enable iOS shortcut widget in WidgetKit extension.
+  ios_enable_shortcuts_widget = false
+
   # Label of the target providing implementation for AccountVerificationProvider.
   # Overridden when using the Google-internal repository to build Chrome on iOS.
   ios_account_verification_provider_target = "//ios/chrome/credential_provider_extension:account_verification_provider_implementation"
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index 5c3147b..d5988029 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -534,12 +534,6 @@
     {"Enabled for email", kEnableExpKitTextClassifierEmail,
      std::size(kEnableExpKitTextClassifierEmail), nullptr}};
 
-const FeatureEntry::FeatureParam kEnableExperienceKitMapsWithSrp[] = {
-    {kExperienceKitMapsVariationName, kEnableExperienceKitMapsVariationSrp}};
-const FeatureEntry::FeatureVariation kEnableExperienceKitMapsVariations[] = {
-    {"with search result page", kEnableExperienceKitMapsWithSrp,
-     std::size(kEnableExperienceKitMapsWithSrp), nullptr}};
-
 const FeatureEntry::FeatureParam kFollowingFeedSortTypeGroupedByPublisher[] = {
     {kFollowingFeedDefaultSortTypeGroupedByPublisher, "true"},
     {kFollowingFeedDefaultSortTypeSortByLatest, "false"}};
@@ -1055,15 +1049,6 @@
      FEATURE_WITH_PARAMS_VALUE_TYPE(kEnableExpKitTextClassifier,
                                     kEnableExpKitTextClassifierVariations,
                                     "ExpKitTextClassifier")},
-    {"experience-kit-maps", flag_descriptions::kMapsExperienceKitName,
-     flag_descriptions::kMapsExperienceKitDescription, flags_ui::kOsIos,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(kMapsExperienceKit,
-                                    kEnableExperienceKitMapsVariations,
-                                    "IOSExperienceKitMaps")},
-    {"enable-long-press-surrounding-text",
-     flag_descriptions::kLongPressSurroundingTextName,
-     flag_descriptions::kLongPressSurroundingTextDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(web::features::kLongPressSurroundingText)},
     {"one-tap-experience-maps", flag_descriptions::kOneTapForMapsName,
      flag_descriptions::kOneTapForMapsDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(web::features::kOneTapForMaps)},
@@ -1294,6 +1279,9 @@
     {"tab-grid-recency-sort", flag_descriptions::kTabGridRecencySortName,
      flag_descriptions::kTabGridRecencySortDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kTabGridRecencySort)},
+    {"tab-grid-new-transitions", flag_descriptions::kTabGridNewTransitionsName,
+     flag_descriptions::kTabGridNewTransitionsDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(kTabGridNewTransitions)},
     {"enable-pinned-tabs", flag_descriptions::kEnablePinnedTabsName,
      flag_descriptions::kEnablePinnedTabsDescription, flags_ui::kOsIos,
      FEATURE_WITH_PARAMS_VALUE_TYPE(kEnablePinnedTabs,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 4edb027..4b6a2a86c 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -217,17 +217,6 @@
     "When enabled, a Magic Stack will be shown in the Home surface displaying "
     "a variety of modules.";
 
-extern const char kMapsExperienceKitName[] = "Experience Kit Maps";
-extern const char kMapsExperienceKitDescription[] =
-    "When enabled, long pressing on an address will trigger Experience Kit Maps"
-    "location and directions handling. Requires "
-    "#enable-long-press-surrounding-text to be enabled.";
-
-extern const char kLongPressSurroundingTextName[] =
-    "Enable Long Press Surrounding Text";
-extern const char kLongPressSurroundingTextDescription[] =
-    "When enabled, long pressing a text will analyze larger part of the text.";
-
 const char kCredentialProviderExtensionPromoName[] =
     "Enable the Credential Provider Extension promo.";
 const char kCredentialProviderExtensionPromoDescription[] =
@@ -1058,6 +1047,11 @@
 const char kTabGridRecencySortDescription[] =
     "When enabled, the tabs in the Tab Grid are sorted differently.";
 
+const char kTabGridNewTransitionsName[] = "Enable new TabGrid transitions";
+const char kTabGridNewTransitionsDescription[] =
+    "When enabled, the new Tab Grid to Browser (and vice versa) transitions"
+    "are used.";
+
 const char kTabInactivityThresholdName[] = "Change Tab inactivity threshold";
 const char kTabInactivityThresholdDescription[] =
     "When enabled, the tabs older than the threshold are considered inactive "
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 9101982..b32151a60 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -181,15 +181,6 @@
 extern const char kEnableUIButtonConfigurationName[];
 extern const char kEnableUIButtonConfigurationDescription[];
 
-// Title and description for the flag to enable long press surrounding text.
-extern const char kLongPressSurroundingTextName[];
-extern const char kLongPressSurroundingTextDescription[];
-
-// Title and description for the flag to enable experience kit maps location and
-// directions.
-extern const char kMapsExperienceKitName[];
-extern const char kMapsExperienceKitDescription[];
-
 // Title and description for the flag to enable the Credential
 // Provider Extension promo.
 extern const char kCredentialProviderExtensionPromoName[];
@@ -923,6 +914,11 @@
 extern const char kTabGridRecencySortName[];
 extern const char kTabGridRecencySortDescription[];
 
+// Title and description for the flag to enable the new transitions in the
+// TabGrid.
+extern const char kTabGridNewTransitionsName[];
+extern const char kTabGridNewTransitionsDescription[];
+
 // Title and description for the flag to determine tab inactivity in the
 // TabGrid.
 extern const char kTabInactivityThresholdName[];
diff --git a/ios/chrome/browser/passwords/password_controller_egtest.mm b/ios/chrome/browser/passwords/password_controller_egtest.mm
index af4cde0..47d70d8 100644
--- a/ios/chrome/browser/passwords/password_controller_egtest.mm
+++ b/ios/chrome/browser/passwords/password_controller_egtest.mm
@@ -100,12 +100,24 @@
   if ([self
           isRunningTest:@selector(testShowAccountStorageNoticeBeforeSaving)] ||
       [self
-          isRunningTest:@selector(testShowAccountStorageNoticeBeforeFilling)]) {
+          isRunningTest:@selector(testShowAccountStorageNoticeBeforeFilling)] ||
+      [self isRunningTest:@selector
+            (testShowAccountStorageNoticeBeforeFillingBottomSheet)]) {
     config.features_enabled.push_back(
         password_manager::features::kEnablePasswordsAccountStorage);
     config.features_enabled.push_back(
         password_manager::features::kIOSShowPasswordStorageInSaveInfobar);
   }
+  if ([self
+          isRunningTest:@selector(testShowAccountStorageNoticeBeforeFilling)]) {
+    config.features_disabled.push_back(
+        password_manager::features::kIOSPasswordBottomSheet);
+  }
+  if ([self isRunningTest:@selector
+            (testShowAccountStorageNoticeBeforeFillingBottomSheet)]) {
+    config.features_enabled.push_back(
+        password_manager::features::kIOSPasswordBottomSheet);
+  }
   return config;
 }
 
@@ -203,6 +215,38 @@
                                                           @"user ••••••••")];
 }
 
+- (void)testShowAccountStorageNoticeBeforeFillingBottomSheet {
+  [PasswordManagerAppInterface
+      storeCredentialWithUsername:@"user"
+                         password:@"password"
+                              URL:net::NSURLWithGURL(self.testServer->GetURL(
+                                      "/simple_login_form.html"))];
+  [PasswordManagerAppInterface setAccountStorageNoticeShown:NO];
+  [SigninEarlGreyUI signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1]
+                                enableSync:NO];
+  [self loadLoginPage];
+
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
+      performAction:chrome_test_util::TapWebElementWithId(kFormPassword)];
+
+  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:
+                      grey_accessibilityLabel(l10n_util::GetNSString(
+                          IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_TITLE))];
+
+  [[EarlGrey selectElementWithMatcher:
+                 grey_accessibilityLabel(l10n_util::GetNSString(
+                     IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_BUTTON_TEXT))]
+      performAction:grey_tap()];
+
+  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:grey_accessibilityID(
+                                                          @"user ••••••••")];
+
+  [[EarlGrey
+      selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString(
+                                   IDS_IOS_PASSWORD_BOTTOM_SHEET_USE_PASSWORD))]
+      performAction:grey_tap()];
+}
+
 // Tests that update password prompt is shown on submitting the new password
 // for an already stored login.
 - (void)testUpdatePromptAppearsOnFormSubmission {
diff --git a/ios/chrome/browser/shared/public/features/features.h b/ios/chrome/browser/shared/public/features/features.h
index de818f5..88453b3 100644
--- a/ios/chrome/browser/shared/public/features/features.h
+++ b/ios/chrome/browser/shared/public/features/features.h
@@ -135,25 +135,18 @@
 // Feature flag to enable Apple Calendar event in experience kit.
 BASE_DECLARE_FEATURE(kEnableExpKitAppleCalendar);
 
-// Parameter name for the parameter controlling whether or not experience kit
-// maps should be enabled in search result pages or not.
-extern const char kExperienceKitMapsVariationName[];
-
-// Variation to enable experience kit Maps in search result pages.
-extern const char kEnableExperienceKitMapsVariationSrp[];
-
-// Feature flag to enable Maps in experience kit.
-BASE_DECLARE_FEATURE(kMapsExperienceKit);
-
-// Feature flag to enable Mini Map in experience kit.
-BASE_DECLARE_FEATURE(kEnableMiniMap);
-
 // When enabled sort tab by last usage in the TabGrid.
 BASE_DECLARE_FEATURE(kTabGridRecencySort);
 
 // Whether the tab grid tabs should be sorted by recency.
 bool IsTabGridSortedByRecency();
 
+// When enabled uses new transitions in the TabGrid.
+BASE_DECLARE_FEATURE(kTabGridNewTransitions);
+
+// Whether the new tab grid tabs transitions should be enabled.
+bool IsNewTabGridTransitionsEnabled();
+
 // Feature to enable multiline gradient support in fade truncating label.
 BASE_DECLARE_FEATURE(kMultilineFadeTruncatingLabel);
 
diff --git a/ios/chrome/browser/shared/public/features/features.mm b/ios/chrome/browser/shared/public/features/features.mm
index 431a6ab..e334a580 100644
--- a/ios/chrome/browser/shared/public/features/features.mm
+++ b/ios/chrome/browser/shared/public/features/features.mm
@@ -172,17 +172,6 @@
              "EnableExpKitAppleCalendar",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-const char kExperienceKitMapsVariationName[] = "ExperienceKitMapsVariant";
-extern const char kEnableExperienceKitMapsVariationSrp[] = "with SRP";
-
-BASE_FEATURE(kMapsExperienceKit,
-             "MapsExperienceKit",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
-BASE_FEATURE(kEnableMiniMap,
-             "EnableMiniMap",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 BASE_FEATURE(kTabGridRecencySort,
              "TabGridRecencySort",
              base::FEATURE_DISABLED_BY_DEFAULT);
@@ -191,6 +180,14 @@
   return base::FeatureList::IsEnabled(kTabGridRecencySort);
 }
 
+BASE_FEATURE(kTabGridNewTransitions,
+             "TabGridNewTransitions",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
+bool IsNewTabGridTransitionsEnabled() {
+  return base::FeatureList::IsEnabled(kTabGridNewTransitions);
+}
+
 BASE_FEATURE(kMultilineFadeTruncatingLabel,
              "MultilineFadeTruncatingLabel",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_coordinator.mm b/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_coordinator.mm
index 3c9b24c3..599ce2c 100644
--- a/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_coordinator.mm
+++ b/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_coordinator.mm
@@ -585,7 +585,7 @@
                       image:nil
              arrowDirection:BubbleArrowDirectionDown
                   alignment:BubbleAlignmentLeading
-                 bubbleType:BubbleViewTypeDefault
+                 bubbleType:BubbleViewTypeWithClose
           dismissalCallback:dismissalCallback];
   bubbleViewControllerPresenter.voiceOverAnnouncement = l10n_util::GetNSString(
       IDS_AUTOFILL_IPH_EXTERNAL_ACCOUNT_PROFILE_SUGGESTION);
diff --git a/ios/chrome/browser/ui/bring_android_tabs/tab_list_from_android_view_controller.mm b/ios/chrome/browser/ui/bring_android_tabs/tab_list_from_android_view_controller.mm
index 311ca49..2490c656 100644
--- a/ios/chrome/browser/ui/bring_android_tabs/tab_list_from_android_view_controller.mm
+++ b/ios/chrome/browser/ui/bring_android_tabs/tab_list_from_android_view_controller.mm
@@ -91,7 +91,10 @@
 - (void)presentationControllerDidDismiss:
     (UIPresentationController*)presentationController {
   int numberDeselected =
-      [self.tableView numberOfRowsInSection:TabListSectionIdentifier] -
+      [self.tableView
+          numberOfRowsInSection:
+              [self.tableViewModel
+                  sectionForSectionIdentifier:kSectionIdentifierEnumZero]] -
       [self.tableView indexPathsForSelectedRows].count;
   [_delegate
       tabListFromAndroidViewControllerDidDismissWithSwipe:YES
@@ -188,7 +191,10 @@
 // Called when the cancel button is tapped.
 - (void)cancelButtonTapped {
   int numberDeselected =
-      [self.tableView numberOfRowsInSection:TabListSectionIdentifier] -
+      [self.tableView
+          numberOfRowsInSection:
+              [self.tableViewModel
+                  sectionForSectionIdentifier:kSectionIdentifierEnumZero]] -
       [self.tableView indexPathsForSelectedRows].count;
   [_delegate
       tabListFromAndroidViewControllerDidDismissWithSwipe:NO
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index 2f73652b..6459fdfa 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -2613,38 +2613,6 @@
   [self updateContentPaddingForTopToolbarHeight:top bottomToolbarHeight:bottom];
 }
 
-// Updates the frame of the web view so that it's `offset` from the bottom of
-// the container view.
-- (void)updateWebViewFrameForBottomOffset:(CGFloat)offset {
-  if (!self.currentWebState)
-    return;
-
-  // Move the frame of the container view such that the bottom is aligned with
-  // the top of the bottom toolbar.
-  id<CRWWebViewProxy> webViewProxy = self.currentWebState->GetWebViewProxy();
-  CGRect webViewFrame = webViewProxy.frame;
-  CGFloat oldOriginY = CGRectGetMinY(webViewFrame);
-  webViewProxy.contentOffset = CGPointMake(0.0, -offset);
-  // Update the contentOffset so that the scroll position is maintained
-  // relative to the screen.
-  CRWWebViewScrollViewProxy* scrollViewProxy = webViewProxy.scrollViewProxy;
-  CGFloat originDelta = CGRectGetMinY(webViewProxy.frame) - oldOriginY;
-  CGPoint contentOffset = scrollViewProxy.contentOffset;
-  contentOffset.y += originDelta;
-  scrollViewProxy.contentOffset = contentOffset;
-}
-
-// Updates the web view's viewport by changing the safe area insets.
-- (void)updateBrowserSafeAreaForTopToolbarHeight:(CGFloat)topToolbarHeight
-                             bottomToolbarHeight:(CGFloat)bottomToolbarHeight {
-  UIViewController* containerViewController =
-      self.browserContainerViewController;
-  containerViewController.additionalSafeAreaInsets = UIEdgeInsetsMake(
-      topToolbarHeight - self.rootSafeAreaInsets.top -
-          self.currentWebState->GetWebViewProxy().contentOffset.y,
-      0, 0, 0);
-}
-
 // Updates the padding of the web view proxy. This either resets the frame of
 // the WKWebView or the contentInsets of the WKWebView's UIScrollView, depending
 // on the the proxy's `shouldUseViewContentInset` property.
@@ -2675,22 +2643,6 @@
   return -(topHeader.frame.origin.y - self.headerOffset);
 }
 
-// Returns the insets into `view` that result in the visible viewport.
-- (UIEdgeInsets)viewportInsetsForView:(UIView*)view {
-  DCHECK(view);
-  UIEdgeInsets viewportInsets =
-      self.fullscreenController->GetCurrentViewportInsets();
-  // TODO(crbug.com/917548): Use BVC for viewport inset coordinate space rather
-  // than the content area.
-  CGRect viewportFrame = [view
-      convertRect:UIEdgeInsetsInsetRect(self.contentArea.bounds, viewportInsets)
-         fromView:self.contentArea];
-  return UIEdgeInsetsMake(
-      CGRectGetMinY(viewportFrame), CGRectGetMinX(viewportFrame),
-      CGRectGetMaxY(view.bounds) - CGRectGetMaxY(viewportFrame),
-      CGRectGetMaxX(view.bounds) - CGRectGetMaxX(viewportFrame));
-}
-
 #pragma mark - MainContentUI
 
 - (MainContentUIState*)mainContentUIState {
diff --git a/ios/chrome/browser/ui/infobars/modals/autofill_address_profile/infobar_save_address_profile_table_view_controller.mm b/ios/chrome/browser/ui/infobars/modals/autofill_address_profile/infobar_save_address_profile_table_view_controller.mm
index 3cf02b5..5b118c5 100644
--- a/ios/chrome/browser/ui/infobars/modals/autofill_address_profile/infobar_save_address_profile_table_view_controller.mm
+++ b/ios/chrome/browser/ui/infobars/modals/autofill_address_profile/infobar_save_address_profile_table_view_controller.mm
@@ -122,13 +122,16 @@
   self.styler.cellBackgroundColor = [UIColor colorNamed:kBackgroundColor];
   self.tableView.sectionHeaderHeight = 0;
   self.tableView.sectionFooterHeight = 0;
-  [self.tableView
-      setSeparatorInset:UIEdgeInsetsMake(
-                            0,
-                            self.isUpdateModal
-                                ? kTableViewHorizontalSpacing
-                                : kInfobarSaveAddressProfileSeparatorInset,
-                            0, 0)];
+  if (self.isUpdateModal && [self shouldShowOldSection]) {
+    [self.tableView
+        setSeparatorInset:UIEdgeInsetsMake(0, kTableViewHorizontalSpacing, 0,
+                                           0)];
+  } else {
+    [self.tableView
+        setSeparatorInset:UIEdgeInsetsMake(
+                              0, kInfobarSaveAddressProfileSeparatorInset, 0,
+                              0)];
+  }
 
   if (!self.isMigrationToAccount || self.currentAddressProfileSaved) {
     // Do not show the cancel button when the migration prompt is presented and
@@ -334,20 +337,14 @@
 - (void)loadUpdateAddressModal {
   DCHECK([self.profileDataDiff count] > 0);
 
-  // Determines whether the old section is to be shown or not.
-  BOOL showOld = NO;
-  for (NSNumber* type in self.profileDataDiff) {
-    if ([self.profileDataDiff[type][1] length] > 0) {
-      showOld = YES;
-    }
-  }
-
   TableViewModel* model = self.tableViewModel;
 
   [model addSectionWithIdentifier:SectionIdentifierFields];
   [model addItem:[self updateModalDescriptionItem]
       toSectionWithIdentifier:SectionIdentifierFields];
 
+  BOOL showOld = [self shouldShowOldSection];
+
   if (showOld) {
     TableViewTextItem* newTitleItem = [self
         titleWithTextItem:
@@ -583,6 +580,18 @@
   return @[ editOption ];
 }
 
+// Returns YES if the old section is shown in the update modal.
+- (BOOL)shouldShowOldSection {
+  // Determines whether the old section is to be shown or not.
+  for (NSNumber* type in self.profileDataDiff) {
+    if ([self.profileDataDiff[type][1] length] > 0) {
+      return YES;
+    }
+  }
+
+  return NO;
+}
+
 #pragma mark - Item Constructors
 
 // Returns a `SettingsImageDetailTextItem` for the fields to be shown in the
diff --git a/ios/chrome/browser/ui/settings/sync/sync_encryption_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/sync/sync_encryption_table_view_controller_unittest.mm
index 7751a9f5..67d9b143 100644
--- a/ios/chrome/browser/ui/settings/sync/sync_encryption_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/sync/sync_encryption_table_view_controller_unittest.mm
@@ -8,12 +8,10 @@
 
 #import "base/functional/bind.h"
 #import "components/strings/grit/components_strings.h"
-#import "components/sync/test/test_sync_service.h"
 #import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #import "ios/chrome/browser/main/test_browser.h"
 #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_text_item.h"
 #import "ios/chrome/browser/shared/ui/table_view/chrome_table_view_controller_test.h"
-#import "ios/chrome/browser/sync/sync_service_factory.h"
 #import "ios/chrome/grit/ios_strings.h"
 #import "ios/web/public/test/web_task_environment.h"
 #import "testing/gtest/include/gtest/gtest.h"
@@ -34,10 +32,6 @@
 
     browser_state_ = TestChromeBrowserState::Builder().Build();
     browser_ = std::make_unique<TestBrowser>(browser_state_.get());
-    syncer::TestSyncService* test_sync_service =
-        static_cast<syncer::TestSyncService*>(
-            SyncServiceFactory::GetForBrowserState(browser_state_.get()));
-    test_sync_service->SetIsUsingExplicitPassphrase(true);
 
     CreateController();
   }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn
index e023000..1fb2ff7 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn
@@ -20,7 +20,6 @@
     "grid_empty_view.h",
     "grid_header.h",
     "grid_header.mm",
-    "grid_image_data_source.h",
     "grid_layout.h",
     "grid_layout.mm",
     "grid_shareable_items_provider.h",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_image_data_source.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_image_data_source.h
deleted file mode 100644
index a0779fb4..0000000
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_image_data_source.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_GRID_IMAGE_DATA_SOURCE_H_
-#define IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_GRID_IMAGE_DATA_SOURCE_H_
-
-#import <UIKit/UIKit.h>
-
-// Protocol that the grid UI uses to asynchronously pull images for cells in the
-// grid.
-@protocol GridImageDataSource
-// Requests the receiver to provide a snapshot image corresponding to
-// `identifier`. `completion` is called with the image if it exists.
-- (void)snapshotForIdentifier:(NSString*)identifier
-                   completion:(void (^)(UIImage*))completion;
-
-// Asks the receiver to pre-fetch all of the snapshots for tabs that are
-// currently visible. Visible tabs identifiers are provided via
-// `visibleGridItems` array.
-- (void)preloadSnapshotsForVisibleGridItems:(NSSet<NSString*>*)visibleGridItems;
-
-// Tells the receiver to dispose of any pre-loaded snapshots it may have cached.
-- (void)clearPreloadedSnapshots;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_GRID_IMAGE_DATA_SOURCE_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h
index e0bb12d..7474e41 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h
@@ -18,7 +18,6 @@
 @protocol TabContextMenuProvider;
 @protocol TabCollectionDragDropHandler;
 @protocol GridEmptyView;
-@protocol GridImageDataSource;
 @protocol GridShareableItemsProvider;
 @class GridTransitionLayout;
 @class GridViewController;
@@ -111,8 +110,6 @@
 @property(nonatomic, strong) UIView<GridEmptyView>* emptyStateView;
 // Returns YES if the grid has no items.
 @property(nonatomic, readonly, getter=isGridEmpty) BOOL gridEmpty;
-// Currently visible items in the grid.
-@property(nonatomic, readonly) NSSet<NSString*>* visibleGridItems;
 // The visual look of the grid.
 @property(nonatomic, assign) GridTheme theme;
 // The current mode for the grid.
@@ -133,8 +130,6 @@
 @property(nonatomic, weak) id<TabCollectionDragDropHandler> dragDropHandler;
 // Tracks if a drop animation is in progress.
 @property(nonatomic, assign) BOOL dropAnimationInProgress;
-// Data source for images.
-@property(nonatomic, weak) id<GridImageDataSource> imageDataSource;
 // Data source for acquiring data to power PriceCardView
 @property(nonatomic, weak) id<PriceCardDataSource> priceCardDataSource;
 // YES if the selected cell is visible in the grid.
@@ -168,8 +163,12 @@
 // Returns the layout of the grid for use in an animated transition.
 - (GridTransitionLayout*)transitionLayout;
 
-// Notifies the ViewController that its content is being displayed or hidden.
+// Notifies the ViewController that its content might soon be displayed.
+- (void)prepareForAppearance;
+// Notifies the ViewController that its content is being displayed.
 - (void)contentWillAppearAnimated:(BOOL)animated;
+- (void)contentDidAppear;
+// Notifies the ViewController that its content is being hidden.
 - (void)contentWillDisappear;
 
 // Notifies the grid that it is about to be dismissed.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
index 7eab10df..93b20f79 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
@@ -34,7 +34,6 @@
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_constants.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_empty_view.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_header.h"
-#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_image_data_source.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_layout.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_shareable_items_provider.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller+private.h"
@@ -336,10 +335,11 @@
   return self.items.count == 0;
 }
 
-- (NSSet<NSString*>*)visibleGridItems {
+// Returns the items whose associated cell is visible.
+- (NSSet<TabSwitcherItem*>*)visibleGridItems {
   NSArray<NSIndexPath*>* visibleItemsIndexPaths =
       [self.collectionView indexPathsForVisibleItems];
-  return [self itemIdentifiersFromIndexPaths:visibleItemsIndexPaths];
+  return [self itemsFromIndexPaths:visibleItemsIndexPaths];
 }
 
 - (void)setMode:(TabGridMode)mode {
@@ -483,10 +483,10 @@
                                          selectionItem:selectionItem];
 }
 
-- (void)prepareForDismissal {
-  // Stop animating the collection view to prevent the insertion animation from
-  // interfering with the tab presentation animation.
-  self.currentLayout.animatesItemUpdates = NO;
+- (void)prepareForAppearance {
+  for (TabSwitcherItem* item in [self visibleGridItems]) {
+    [item prefetchSnapshot];
+  }
 }
 
 - (void)contentWillAppearAnimated:(BOOL)animated {
@@ -507,9 +507,21 @@
   self.lastInsertedItemID = nil;
 }
 
+- (void)contentDidAppear {
+  for (TabSwitcherItem* item in self.items) {
+    [item clearPrefetchedSnapshot];
+  }
+}
+
 - (void)contentWillDisappear {
 }
 
+- (void)prepareForDismissal {
+  // Stop animating the collection view to prevent the insertion animation from
+  // interfering with the tab presentation animation.
+  self.currentLayout.animatesItemUpdates = NO;
+}
+
 #pragma mark - UICollectionViewDataSource
 
 - (NSInteger)numberOfSectionsInCollectionView:
@@ -1724,28 +1736,16 @@
   }];
 
   __weak __typeof(self) weakSelf = self;
-  TabSwitcherImageFetchingCompletionBlock completion =
-      ^(TabSwitcherItem* innerItem, UIImage* snapshot) {
-        // Only update the icon if the cell is not already reused for another
-        // item.
-        if ([cell hasIdentifier:innerItem.identifier]) {
-          if (weakSelf.thumbStripEnabled) {
-            [cell fadeInSnapshot:snapshot];
-          } else {
-            cell.snapshot = snapshot;
-          }
-        }
-      };
-  if (_mode == TabGridModeInactive) {
-    [item fetchSnapshot:completion];
-  } else {
-    // TODO(crbug.com/1421321): Migrate to using
-    // `-[TabSwitcherItem fetchSnapshot:]`.
-    [self.imageDataSource snapshotForIdentifier:item.identifier
-                                     completion:^(UIImage* snapshot) {
-                                       completion(item, snapshot);
-                                     }];
-  }
+  [item fetchSnapshot:^(TabSwitcherItem* innerItem, UIImage* snapshot) {
+    // Only update the icon if the cell is not already reused for another item.
+    if ([cell hasIdentifier:innerItem.identifier]) {
+      if (weakSelf.thumbStripEnabled) {
+        [cell fadeInSnapshot:snapshot];
+      } else {
+        cell.snapshot = snapshot;
+      }
+    }
+  }];
 
   NSString* itemIdentifier = item.identifier;
   [self.priceCardDataSource
@@ -1955,20 +1955,20 @@
                               base::SysNSStringToUTF16(resultsCount));
 }
 
-// Converts `indexPaths` into corresponding item identifiers.
-- (NSSet<NSString*>*)itemIdentifiersFromIndexPaths:
+// Returns the items at the given index paths.
+- (NSSet<TabSwitcherItem*>*)itemsFromIndexPaths:
     (NSArray<NSIndexPath*>*)indexPaths {
-  NSMutableSet<NSString*>* itemIdentifiers = [NSMutableSet set];
+  NSMutableSet<TabSwitcherItem*>* items = [[NSMutableSet alloc] init];
 
   [indexPaths enumerateObjectsUsingBlock:^(NSIndexPath* indexPath,
                                            NSUInteger index, BOOL* stop) {
     NSUInteger itemIndex = base::checked_cast<NSUInteger>(indexPath.item);
     if (itemIndex < self.items.count) {
-      [itemIdentifiers addObject:self.items[itemIndex].identifier];
+      [items addObject:self.items[itemIndex]];
     }
   }];
 
-  return [itemIdentifiers copy];
+  return items;
 }
 
 // Returns the size that should be dedicated the the Inactive Tabs button
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_coordinator.mm
index 12fa170..9619068 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_coordinator.mm
@@ -7,6 +7,8 @@
 #import <QuartzCore/QuartzCore.h>
 #import <UIKit/UIKit.h>
 
+#import "base/metrics/user_metrics.h"
+#import "base/metrics/user_metrics_action.h"
 #import "base/notreached.h"
 #import "base/strings/sys_string_conversions.h"
 #import "ios/chrome/browser/application_context/application_context.h"
@@ -339,6 +341,7 @@
 
 - (void)gridViewController:(GridViewController*)gridViewController
        didSelectItemWithID:(NSString*)itemID {
+  base::RecordAction(base::UserMetricsAction("MobileTabGridOpenInactiveTab"));
   [_delegate inactiveTabsCoordinator:self didSelectItemWithID:itemID];
   [_delegate inactiveTabsCoordinatorDidFinish:self];
 }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
index 95c0429..abedc94fe 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
@@ -15,7 +15,6 @@
 #import "ios/chrome/browser/tabs/features.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_handler.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.h"
-#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_image_data_source.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_cell.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_constants.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_layout.h"
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
index 82b9d2f..9627eec 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
@@ -780,9 +780,7 @@
     baseViewController.pinnedTabsDragDropHandler = self.pinnedTabsMediator;
   }
 
-  baseViewController.regularTabsImageDataSource = self.regularTabsMediator;
   baseViewController.priceCardDataSource = self.priceCardMediator;
-  baseViewController.incognitoTabsImageDataSource = self.incognitoTabsMediator;
 
   baseViewController.regularTabsShareableItemsProvider =
       self.regularTabsMediator;
@@ -1147,8 +1145,6 @@
 - (void)inactiveTabsCoordinator:
             (InactiveTabsCoordinator*)inactiveTabsCoordinator
             didSelectItemWithID:(NSString*)itemID {
-  // TODO(crbug.com/1418021): Add metrics when the user activate back an
-  // inactive tab and bring it back to the active tab list.
   WebStateList* regularWebStateList = self.regularBrowser->GetWebStateList();
   int toInsertIndex = regularWebStateList->count();
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
index 388b65f..9e7ef4a 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
@@ -9,7 +9,6 @@
 
 #import "ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_handler.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_commands.h"
-#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_image_data_source.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_shareable_items_provider.h"
 
 class Browser;
@@ -48,7 +47,6 @@
 
 // Mediates between model layer and tab grid UI layer.
 @interface TabGridMediator : NSObject <GridCommands,
-                                       GridImageDataSource,
                                        GridShareableItemsProvider,
                                        TabCollectionDragDropHandler>
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
index 71ae55fe..cd14546 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
@@ -183,9 +183,6 @@
 // The number of tabs in `closedSessionWindow` that are synced by
 // TabRestoreService.
 @property(nonatomic, assign) int syncedClosedTabsCount;
-// Short-term cache for grid thumbnails.
-@property(nonatomic, strong)
-    NSMutableDictionary<NSString*, UIImage*>* appearanceCache;
 @end
 
 @implementation TabGridMediator {
@@ -219,7 +216,6 @@
         std::make_unique<base::ScopedMultiSourceObservation<
             web::WebState, web::WebStateObserver>>(
             _webStateObserverBridge.get());
-    _appearanceCache = [[NSMutableDictionary alloc] init];
   }
   return self;
 }
@@ -447,7 +443,6 @@
 
 - (void)snapshotCache:(SnapshotCache*)snapshotCache
     didUpdateSnapshotForIdentifier:(NSString*)identifier {
-  [self.appearanceCache removeObjectForKey:identifier];
   web::WebState* webState = GetWebState(
       self.webStateList, WebStateSearchCriteria{
                              .identifier = identifier,
@@ -508,6 +503,8 @@
     }
 
     if (browser->IsInactive()) {
+      base::RecordAction(
+          base::UserMetricsAction("MobileTabGridOpenInactiveTabSearchResult"));
       index = itemWebStateList->count();
       MoveTabToBrowser(itemID, self.browser, index);
     } else {
@@ -1000,53 +997,6 @@
   [itemProvider loadObjectOfClass:[NSURL class] completionHandler:loadHandler];
 }
 
-#pragma mark - GridImageDataSource
-
-- (void)snapshotForIdentifier:(NSString*)identifier
-                   completion:(void (^)(UIImage*))completion {
-  if (self.appearanceCache[identifier]) {
-    completion(self.appearanceCache[identifier]);
-    return;
-  }
-  web::WebState* webState =
-      GetWebState(self.webStateList, WebStateSearchCriteria{
-                                         .identifier = identifier,
-                                     });
-  if (webState) {
-    SnapshotTabHelper::FromWebState(webState)->RetrieveColorSnapshot(
-        ^(UIImage* image) {
-          completion(image);
-        });
-  }
-}
-
-- (void)preloadSnapshotsForVisibleGridItems:
-    (NSSet<NSString*>*)visibleGridItems {
-  int startIndex = self.webStateList->GetIndexOfFirstNonPinnedWebState();
-  int endIndex = self.webStateList->count() - 1;
-
-  for (int i = startIndex; i <= endIndex; i++) {
-    web::WebState* web_state = self.webStateList->GetWebStateAt(i);
-    NSString* identifier = web_state->GetStableIdentifier();
-
-    BOOL isWebStateHidden = ![visibleGridItems containsObject:identifier];
-    if (isWebStateHidden) {
-      continue;
-    }
-
-    __weak __typeof(self) weakSelf = self;
-    auto cacheImage = ^(UIImage* image) {
-      weakSelf.appearanceCache[identifier] = image;
-    };
-
-    [self snapshotForIdentifier:identifier completion:cacheImage];
-  }
-}
-
-- (void)clearPreloadedSnapshots {
-  [self.appearanceCache removeAllObjects];
-}
-
 #pragma mark - GridShareableItemsProvider
 
 - (BOOL)isItemWithIdentifierSharable:(NSString*)identifier {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h
index 9ec1157..e4a2a04 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h
@@ -17,7 +17,6 @@
 
 @protocol ApplicationCommands;
 @protocol GridCommands;
-@protocol GridImageDataSource;
 @protocol PriceCardDataSource;
 @protocol GridShareableItemsProvider;
 class GURL;
@@ -142,10 +141,6 @@
 @property(nonatomic, weak) id<TabCollectionDragDropHandler>
     pinnedTabsDragDropHandler;
 
-// Data sources provide lazy access to heavy-weight resources.
-@property(nonatomic, weak) id<GridImageDataSource> regularTabsImageDataSource;
-@property(nonatomic, weak) id<GridImageDataSource> incognitoTabsImageDataSource;
-
 // Data source for acquiring data which power the PriceCardView
 @property(nonatomic, weak) id<PriceCardDataSource> priceCardDataSource;
 
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 939cd26..1c0b462c 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
@@ -38,7 +38,6 @@
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/disabled_tab_view_controller.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_commands.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_constants.h"
-#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_image_data_source.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_constants.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.h"
@@ -346,11 +345,6 @@
   return UIStatusBarStyleLightContent;
 }
 
-- (void)didReceiveMemoryWarning {
-  [self.regularTabsImageDataSource clearPreloadedSnapshots];
-  [self.incognitoTabsImageDataSource clearPreloadedSnapshots];
-}
-
 - (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {
   [super traitCollectionDidChange:previousTraitCollection];
   [self.traitCollectionObserver viewController:self
@@ -488,28 +482,7 @@
 #pragma mark - Public Methods
 
 - (void)prepareForAppearance {
-  NSSet<NSString*>* visibleGridItems = [self visibleGridItemsForActivePage];
-
-  switch (self.activePage) {
-    case TabGridPageIncognitoTabs:
-      [self.incognitoTabsImageDataSource
-          preloadSnapshotsForVisibleGridItems:visibleGridItems];
-      break;
-    case TabGridPageRegularTabs:
-      [self.regularTabsImageDataSource
-          preloadSnapshotsForVisibleGridItems:visibleGridItems];
-      break;
-    case TabGridPageRemoteTabs:
-      // Nothing to do.
-      break;
-  }
-}
-
-- (NSSet<NSString*>*)visibleGridItemsForActivePage {
-  GridViewController* activeGridViewController =
-      [self gridViewControllerForPage:self.activePage];
-
-  return [activeGridViewController visibleGridItems];
+  [[self gridViewControllerForPage:self.activePage] prepareForAppearance];
 }
 
 - (void)contentWillAppearAnimated:(BOOL)animated {
@@ -545,9 +518,8 @@
     [self setInsetForRemoteTabs];
   }
 
-  // Let image sources know the initial appearance is done.
-  [self.regularTabsImageDataSource clearPreloadedSnapshots];
-  [self.incognitoTabsImageDataSource clearPreloadedSnapshots];
+  // Let the active grid view know the initial appearance is done.
+  [[self gridViewControllerForPage:self.activePage] contentDidAppear];
 }
 
 - (void)contentWillDisappearAnimated:(BOOL)animated {
@@ -630,12 +602,6 @@
   return self.regularTabsViewController;
 }
 
-- (void)setRegularTabsImageDataSource:
-    (id<GridImageDataSource>)regularTabsImageDataSource {
-  self.regularTabsViewController.imageDataSource = regularTabsImageDataSource;
-  _regularTabsImageDataSource = regularTabsImageDataSource;
-}
-
 - (void)setPriceCardDataSource:(id<PriceCardDataSource>)priceCardDataSource {
   self.regularTabsViewController.priceCardDataSource = priceCardDataSource;
   _priceCardDataSource = priceCardDataSource;
@@ -649,13 +615,6 @@
   return self.incognitoTabsViewController;
 }
 
-- (void)setIncognitoTabsImageDataSource:
-    (id<GridImageDataSource>)incognitoTabsImageDataSource {
-  self.incognitoTabsViewController.imageDataSource =
-      incognitoTabsImageDataSource;
-  _incognitoTabsImageDataSource = incognitoTabsImageDataSource;
-}
-
 - (id<RecentTabsConsumer>)remoteTabsConsumer {
   return self.remoteTabsViewController;
 }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_item.h b/ios/chrome/browser/ui/tab_switcher/tab_switcher_item.h
index 62b6048..a58cd9c 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_item.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_item.h
@@ -42,6 +42,13 @@
 // operation completes.
 - (void)fetchSnapshot:(TabSwitcherImageFetchingCompletionBlock)completion;
 
+// Prefetches the snapshot. Once the asynchronous fetch has returned, the next
+// call to `fetchSnapshot:` can be synchronous.
+- (void)prefetchSnapshot;
+
+// Clears the potential prefetched snapshot.
+- (void)clearPrefetchedSnapshot;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_SWITCHER_ITEM_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_item.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_item.mm
index 1d46a238..6b3c583 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_item.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_item.mm
@@ -33,4 +33,12 @@
   completion(self, nil);
 }
 
+- (void)prefetchSnapshot {
+  // Subclasses should override this method. It is OK not to call super.
+}
+
+- (void)clearPrefetchedSnapshot {
+  // Subclasses should override this method. It is OK not to call super.
+}
+
 @end
diff --git a/ios/chrome/browser/ui/tab_switcher/web_state_tab_switcher_item.mm b/ios/chrome/browser/ui/tab_switcher/web_state_tab_switcher_item.mm
index e92b57b..e9c38e99 100644
--- a/ios/chrome/browser/ui/tab_switcher/web_state_tab_switcher_item.mm
+++ b/ios/chrome/browser/ui/tab_switcher/web_state_tab_switcher_item.mm
@@ -17,7 +17,10 @@
 #endif
 
 @implementation WebStateTabSwitcherItem {
+  // The web state represented by this item.
   base::WeakPtr<web::WebState> _webState;
+  // The potentially prefetched snapshot for the web state.
+  UIImage* _prefetchedSnapshot;
 }
 
 - (instancetype)initWithWebState:(web::WebState*)webState {
@@ -32,6 +35,12 @@
     }
     self.title = tab_util::GetTabTitle(webState);
     self.showsActivity = webState->IsLoading();
+
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(lowMemoryWarningReceived:)
+               name:UIApplicationDidReceiveMemoryWarningNotification
+             object:nil];
   }
   return self;
 }
@@ -77,6 +86,11 @@
     return;
   }
 
+  if (_prefetchedSnapshot) {
+    completion(self, _prefetchedSnapshot);
+    return;
+  }
+
   __weak __typeof(self) weakSelf = self;
   SnapshotTabHelper::FromWebState(webState)->RetrieveColorSnapshot(
       ^(UIImage* snapshot) {
@@ -101,4 +115,31 @@
   return nil;
 }
 
+- (void)prefetchSnapshot {
+  web::WebState* webState = _webState.get();
+  if (!webState) {
+    return;
+  }
+
+  __weak __typeof(self) weakSelf = self;
+  SnapshotTabHelper::FromWebState(webState)->RetrieveColorSnapshot(
+      ^(UIImage* snapshot) {
+        WebStateTabSwitcherItem* strongSelf = weakSelf;
+        if (!strongSelf) {
+          return;
+        }
+        strongSelf->_prefetchedSnapshot = snapshot;
+      });
+}
+
+- (void)clearPrefetchedSnapshot {
+  _prefetchedSnapshot = nil;
+}
+
+#pragma mark - Private
+
+- (void)lowMemoryWarningReceived:(NSNotification*)notification {
+  [self clearPrefetchedSnapshot];
+}
+
 @end
diff --git a/ios/chrome/browser/widget_kit/widget_metrics_util.mm b/ios/chrome/browser/widget_kit/widget_metrics_util.mm
index 343dcc7..d9d987bc 100644
--- a/ios/chrome/browser/widget_kit/widget_metrics_util.mm
+++ b/ios/chrome/browser/widget_kit/widget_metrics_util.mm
@@ -30,7 +30,8 @@
   kLockscreenLauncherIncognito = 5,
   kLockscreenLauncherVoiceSearch = 6,
   kLockscreenLauncherGame = 7,
-  kMaxValue = kLockscreenLauncherGame,
+  kShortcuts = 8,
+  kMaxValue = kShortcuts,
 };
 
 WidgetKitExtensionKind UMAKindForWidgetKind(NSString* kind) {
@@ -46,6 +47,9 @@
   if ([kind isEqualToString:@"QuickActionsWidget"]) {
     return WidgetKitExtensionKind::kQuickActions;
   }
+  if ([kind isEqualToString:@"ShortcutsWidget"]) {
+    return WidgetKitExtensionKind::kShortcuts;
+  }
   if ([kind isEqualToString:@"LockscreenLauncherSearchWidget"]) {
     return WidgetKitExtensionKind::kLockscreenLauncherSearch;
   }
diff --git a/ios/chrome/widget_kit_extension/BUILD.gn b/ios/chrome/widget_kit_extension/BUILD.gn
index 84625245..172116e 100644
--- a/ios/chrome/widget_kit_extension/BUILD.gn
+++ b/ios/chrome/widget_kit_extension/BUILD.gn
@@ -13,12 +13,16 @@
 import("//ios/chrome/tools/strings/generate_localizable_strings.gni")
 import("//ios/public/provider/chrome/browser/build_config.gni")
 
-config("ios_available_lockscreen_extension") {
-  swiftflags = [ "-DIOS_AVAILABLE_LOCKSCREEN_EXTENSION" ]
+config("ios_available_lockscreen_widget") {
+  swiftflags = [ "-DIOS_AVAILABLE_LOCKSCREEN_WIDGET" ]
 }
 
-config("ios_enable_lockscreen_extension") {
-  swiftflags = [ "-DIOS_ENABLE_LOCKSCREEN_EXTENSION" ]
+config("ios_enable_lockscreen_widget") {
+  swiftflags = [ "-DIOS_ENABLE_LOCKSCREEN_WIDGET" ]
+}
+
+config("ios_enable_shortcuts_widget") {
+  swiftflags = [ "-DIOS_ENABLE_SHORTCUTS_WIDGET" ]
 }
 
 tweak_info_plist("tweak_info_plist") {
@@ -83,11 +87,16 @@
   # Swift does not have the equivalent of __IPHONE_16_0, so use a
   # custom define instead.
   if (xcode_version_int >= 1400) {
-    configs += [ ":ios_available_lockscreen_extension" ]
+    configs += [ ":ios_available_lockscreen_widget" ]
   }
 
-  if (ios_enable_lockscreen_extension) {
-    configs += [ ":ios_enable_lockscreen_extension" ]
+  if (ios_enable_lockscreen_widget) {
+    configs += [ ":ios_enable_lockscreen_widget" ]
+  }
+
+  if (ios_enable_shortcuts_widget) {
+    configs += [ ":ios_enable_shortcuts_widget" ]
+    sources += [ "shortcuts_widget.swift" ]
   }
 
   frameworks = [
diff --git a/ios/chrome/widget_kit_extension/lockscreen_launcher_widget.swift b/ios/chrome/widget_kit_extension/lockscreen_launcher_widget.swift
index f50f265..2c0066d 100644
--- a/ios/chrome/widget_kit_extension/lockscreen_launcher_widget.swift
+++ b/ios/chrome/widget_kit_extension/lockscreen_launcher_widget.swift
@@ -6,8 +6,8 @@
 import SwiftUI
 import WidgetKit
 
-#if IOS_ENABLE_LOCKSCREEN_EXTENSION
-  #if IOS_AVAILABLE_LOCKSCREEN_EXTENSION
+#if IOS_ENABLE_LOCKSCREEN_WIDGET
+  #if IOS_AVAILABLE_LOCKSCREEN_WIDGET
 
     enum LockscreenLauncherWidgetType {
       case search, incognito, voiceSearch, dinoGame
@@ -137,5 +137,5 @@
       }
     }
 
-  #endif  // IOS_AVAILABLE_LOCKSCREEN_EXTENSION
-#endif  // IOS_ENABLE_LOCKSCREEN_EXTENSION
+  #endif  // IOS_AVAILABLE_LOCKSCREEN_WIDGET
+#endif  // IOS_ENABLE_LOCKSCREEN_WIDGET
diff --git a/ios/chrome/widget_kit_extension/main.swift b/ios/chrome/widget_kit_extension/main.swift
index 4e2b105..bba77b7b 100644
--- a/ios/chrome/widget_kit_extension/main.swift
+++ b/ios/chrome/widget_kit_extension/main.swift
@@ -44,8 +44,11 @@
     QuickActionsWidget()
     SearchWidget()
     DinoGameWidget()
-    #if IOS_ENABLE_LOCKSCREEN_EXTENSION
-      #if IOS_AVAILABLE_LOCKSCREEN_EXTENSION
+    #if IOS_ENABLE_SHORTCUTS_WIDGET
+      ShortcutsWidget()
+    #endif
+    #if IOS_ENABLE_LOCKSCREEN_WIDGET
+      #if IOS_AVAILABLE_LOCKSCREEN_WIDGET
         LockscreenLauncherSearchWidget()
         LockscreenLauncherIncognitoWidget()
         LockscreenLauncherVoiceSearchWidget()
diff --git a/ios/chrome/widget_kit_extension/shortcuts_widget.swift b/ios/chrome/widget_kit_extension/shortcuts_widget.swift
new file mode 100644
index 0000000..f3e674b
--- /dev/null
+++ b/ios/chrome/widget_kit_extension/shortcuts_widget.swift
@@ -0,0 +1,36 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import Foundation
+import SwiftUI
+import WidgetKit
+
+struct ShortcutsWidget: Widget {
+  // Changing 'kind' or deleting this widget will cause all installed instances of this widget to
+  // stop updating and show the placeholder state.
+  let kind: String = "ShortcutsWidget"
+
+  var body: some WidgetConfiguration {
+    StaticConfiguration(
+      kind: kind,
+      provider: Provider()
+    ) { entry in
+      ShortcutsWidgetEntryView(entry: entry)
+    }
+    .configurationDisplayName(
+      Text("Shortcuts Widget")
+    )
+    .description(Text("Shortcuts Widget Description"))
+    .supportedFamilies([.systemMedium])
+  }
+}
+
+struct ShortcutsWidgetEntryView: View {
+
+  let entry: Provider.Entry
+
+  var body: some View {
+    EmptyView()
+  }
+}
diff --git a/ios/web/common/features.h b/ios/web/common/features.h
index ef20540f..18d04ea 100644
--- a/ios/web/common/features.h
+++ b/ios/web/common/features.h
@@ -61,10 +61,6 @@
 // should be used instead of directly checking this feature.
 BASE_DECLARE_FEATURE(kUseLoadSimulatedRequestForOfflinePage);
 
-// Feature flag that enables getting more of the surrounding text when the user
-// long presses at a certain location.
-BASE_DECLARE_FEATURE(kLongPressSurroundingText);
-
 // Feature flag to enable Emails detection.
 BASE_DECLARE_FEATURE(kEnableEmails);
 
diff --git a/ios/web/common/features.mm b/ios/web/common/features.mm
index f661054..0624f77f 100644
--- a/ios/web/common/features.mm
+++ b/ios/web/common/features.mm
@@ -61,10 +61,6 @@
              "UseLoadSimulatedRequestForErrorPageNavigation",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-BASE_FEATURE(kLongPressSurroundingText,
-             "LongPressSurroundingText",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 BASE_FEATURE(kEnableEmails,
              "EnableEmailsExperience",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/ios/web/content/navigation/content_navigation_item.h b/ios/web/content/navigation/content_navigation_item.h
index cd744fb..fac3a7b 100644
--- a/ios/web/content/navigation/content_navigation_item.h
+++ b/ios/web/content/navigation/content_navigation_item.h
@@ -69,9 +69,9 @@
 
   bool HasPostData() const override;
 
-  NSDictionary* GetHttpRequestHeaders() const override;
+  HttpRequestHeaders* GetHttpRequestHeaders() const override;
 
-  void AddHttpRequestHeaders(NSDictionary* additional_headers) override;
+  void AddHttpRequestHeaders(HttpRequestHeaders* additional_headers) override;
 
   HttpsUpgradeType GetHttpsUpgradeType() const override;
   void SetHttpsUpgradeType(HttpsUpgradeType https_upgrade_type) override;
@@ -86,7 +86,7 @@
   // NavigationEntry isn't changed, the functions are still semantically
   // const.
   mutable Referrer referrer_;
-  mutable NSDictionary* headers_ = nil;
+  mutable HttpRequestHeaders* headers_ = nil;
   mutable FaviconStatus favicon_status_;
   mutable SSLStatus ssl_status_;
 
diff --git a/ios/web/content/navigation/content_navigation_item.mm b/ios/web/content/navigation/content_navigation_item.mm
index c0a1112..9bac5f8 100644
--- a/ios/web/content/navigation/content_navigation_item.mm
+++ b/ios/web/content/navigation/content_navigation_item.mm
@@ -197,11 +197,12 @@
 }
 
 void ContentNavigationItem::AddHttpRequestHeaders(
-    NSDictionary* additional_headers) {
+    HttpRequestHeaders* additional_headers) {
   NOTREACHED();
 }
 
-NSDictionary* ContentNavigationItem::GetHttpRequestHeaders() const {
+NavigationItem::HttpRequestHeaders*
+ContentNavigationItem::GetHttpRequestHeaders() const {
   auto headers_string = entry_->GetExtraHeaders();
   if (!headers_string.empty()) {
     net::HttpRequestHeaders headers;
diff --git a/ios/web/js_features/context_menu/context_menu_java_script_feature.mm b/ios/web/js_features/context_menu/context_menu_java_script_feature.mm
index 153e5db..d8ec706 100644
--- a/ios/web/js_features/context_menu/context_menu_java_script_feature.mm
+++ b/ios/web/js_features/context_menu/context_menu_java_script_feature.mm
@@ -75,8 +75,6 @@
   parameters.push_back(base::Value(point.y));
   parameters.push_back(base::Value(web_content_size.width));
   parameters.push_back(base::Value(web_content_size.height));
-  parameters.push_back(base::Value(
-      base::FeatureList::IsEnabled(web::features::kLongPressSurroundingText)));
   CallJavaScriptFunction(main_frame, "contextMenu.findElementAtPoint",
                          parameters);
 }
diff --git a/ios/web/js_features/context_menu/context_menu_js_unittest.mm b/ios/web/js_features/context_menu/context_menu_js_unittest.mm
index bcf82e6..fca40ea 100644
--- a/ios/web/js_features/context_menu/context_menu_js_unittest.mm
+++ b/ios/web/js_features/context_menu/context_menu_js_unittest.mm
@@ -218,7 +218,7 @@
  protected:
   // Returns details of the DOM element at the given `point` in the web view
   // viewport's coordinate space.
-  base::Value FindElementAtPoint(CGPoint point, BOOL surroundingTextEnabled) {
+  base::Value FindElementAtPoint(CGPoint point) {
     bool gCrWeb_injected = web::test::WaitForInjectedScripts(web_view());
     if (!gCrWeb_injected) {
       // This EXPECT_TRUE call will always fail. However, add the conditional to
@@ -234,7 +234,7 @@
     // Clear previous script message response.
     script_message_handler_.lastReceivedScriptMessage = nil;
 
-    ExecuteFindElementFromPointJavaScript(point, surroundingTextEnabled);
+    ExecuteFindElementFromPointJavaScript(point);
 
     // Wait for response.
     EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
@@ -261,11 +261,10 @@
   // remove this retry logic.
   void CheckElementResult(CGPoint point,
                           const base::Value& expected_result,
-                          const std::vector<const char*>& ignored_keys,
-                          BOOL surroundingTextEnabled) {
+                          const std::vector<const char*>& ignored_keys) {
     constexpr int kNumTries = 13;
     for (int i = 0; i < kNumTries; ++i) {
-      base::Value result = FindElementAtPoint(point, surroundingTextEnabled);
+      base::Value result = FindElementAtPoint(point);
       for (const char* key : ignored_keys) {
         result.RemoveKey(key);
       }
@@ -277,12 +276,9 @@
     }
   }
 
-  void CheckElementResult(CGPoint point,
-                          const base::Value& expected_result,
-                          BOOL surroundingTextEnabled) {
+  void CheckElementResult(CGPoint point, const base::Value& expected_result) {
     return CheckElementResult(point, expected_result,
-                              std::vector<const char*>(),
-                              surroundingTextEnabled);
+                              std::vector<const char*>());
   }
 
   // Returns web view's content size from the current web state.
@@ -297,16 +293,12 @@
 
   // Executes __gCrWeb.findElementAtPoint script with the given `point` in the
   // web view viewport's coordinate space.
-  id ExecuteFindElementFromPointJavaScript(CGPoint point,
-                                           BOOL surroundingTextEnabled) {
+  id ExecuteFindElementFromPointJavaScript(CGPoint point) {
     CGSize size = GetWebViewContentSize();
-    const char* enableSurroundingText =
-        surroundingTextEnabled ? "true" : "false";
-    NSString* script =
-        [NSString stringWithFormat:@"__gCrWeb.contextMenu.findElementAtPoint('%"
-                                   @"s', %g, %g, %g, %g, %s)",
-                                   kRequestId, point.x, point.y, size.width,
-                                   size.height, enableSurroundingText];
+    NSString* script = [NSString
+        stringWithFormat:@"__gCrWeb.contextMenu.findElementAtPoint('%"
+                         @"s', %g, %g, %g, %g)",
+                         kRequestId, point.x, point.y, size.width, size.height];
 
     return web::test::ExecuteJavaScript(web_view(), script);
   }
@@ -315,9 +307,9 @@
   CRWFakeScriptMessageHandler* script_message_handler_;
 };
 
-#pragma mark - Long press with Surrounding text enabled
+#pragma mark - Long press with Surrounding text
 
-TEST_F(ContextMenuJsFindElementAtPointTest, FetchSurroundingTextEnabled) {
+TEST_F(ContextMenuJsFindElementAtPointTest, FetchSurroundingText) {
   NSString* html =
       @"<html><head>"
        "<meta name=\"viewport\" content=\"user-scalable=no, width=100\">"
@@ -341,37 +333,10 @@
   ignored_keys.push_back(kContextMenuElementInnerText);
   ignored_keys.push_back(kContextMenuElementTextOffset);
   ignored_keys.push_back(kContextMenuElementSurroundingTextOffset);
-  CheckElementResult(kPointInsideSurroundingText, expected_value, ignored_keys,
-                     true);
+  CheckElementResult(kPointInsideSurroundingText, expected_value, ignored_keys);
 }
 
-#pragma mark - Long press with Surrounding text disabled
-
-TEST_F(ContextMenuJsFindElementAtPointTest, FetchSurroundingTextDisabled) {
-  NSString* html =
-      @"<html><head>"
-       "<meta name=\"viewport\" content=\"user-scalable=no, width=100\">"
-       "</head><body><div>This is the address's first line</div>"
-       "<p>Lorem ipsum<span>dolor sit amet. 49 WEST</span>27TH STREET "
-       "reprehenderit sed cumque magni ut omnis sint est deserunt eveniet non "
-       "omnis esse et debitis labore et Quis consequatur.</p>"
-       "</body></html>";
-
-  ASSERT_TRUE(LoadHtml(html));
-
-  base::Value expected_value(base::Value::Type::DICT);
-  expected_value.SetStringKey(kContextMenuElementRequestId, kRequestId);
-  expected_value.SetStringKey(kContextMenuElementTagName, "P");
-
-  std::vector<const char*> ignored_keys;
-  ignored_keys.push_back(kContextMenuElementInnerText);
-  ignored_keys.push_back(kContextMenuElementTextOffset);
-  ignored_keys.push_back(kContextMenuElementSurroundingTextOffset);
-  CheckElementResult(kPointInsideSurroundingText, expected_value, ignored_keys,
-                     false);
-}
-
-#pragma mark - Surrounding text
+#pragma mark - Surrounding text edge cases
 
 TEST_F(ContextMenuJsFindElementAtPointTest, ExtractSurroundingText) {
   NSString* elementId = @"parc";
@@ -413,7 +378,7 @@
   expected_value.SetStringKey(kContextMenuElementReferrerPolicy, "default");
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that the correct src is found for picture elements.
@@ -435,7 +400,7 @@
   expected_value.SetStringKey(kContextMenuElementReferrerPolicy, "default");
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that the correct src is found for elements with background-image.
@@ -453,7 +418,7 @@
   expected_value.SetStringKey(kContextMenuElementReferrerPolicy, "default");
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that the correct src is found for images behind transparent layers.
@@ -474,7 +439,7 @@
   expected_value.SetStringKey(kContextMenuElementReferrerPolicy, "default");
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that opaque objects block image selection underneath.
@@ -496,7 +461,7 @@
   std::vector<const char*> ignored_keys;
   ignored_keys.push_back(kContextMenuElementTextOffset);
 
-  CheckElementResult(kPointOnImage, expected_value, ignored_keys, false);
+  CheckElementResult(kPointOnImage, expected_value, ignored_keys);
 }
 
 // Tests that the correct title is found for an image.
@@ -516,7 +481,7 @@
   expected_value.SetStringKey(kContextMenuElementTitle, image_title);
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that the correct natural size is found for an image.
@@ -532,7 +497,7 @@
   expected_value.SetStringKey(kContextMenuElementReferrerPolicy, "default");
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that image details are not returned for a point outside of the document
@@ -545,7 +510,7 @@
   base::Value expected_value(base::Value::Type::DICT);
   expected_value.SetStringKey(kContextMenuElementRequestId, kRequestId);
 
-  CheckElementResult(kPointOutsideDocument, expected_value, false);
+  CheckElementResult(kPointOutsideDocument, expected_value);
 }
 
 // Tests that image details are not returned for a point outside of the element.
@@ -557,7 +522,7 @@
   base::Value expected_value(base::Value::Type::DICT);
   expected_value.SetStringKey(kContextMenuElementRequestId, kRequestId);
 
-  CheckElementResult(kPointOutsideImage, expected_value, false);
+  CheckElementResult(kPointOutsideImage, expected_value);
 }
 
 #pragma mark - Image with link
@@ -578,7 +543,7 @@
   expected_value.SetStringKey(kContextMenuElementHyperlink, image_link);
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that an image link does not return image and link details for a point
@@ -593,7 +558,7 @@
   base::Value expected_value(base::Value::Type::DICT);
   expected_value.SetStringKey(kContextMenuElementRequestId, kRequestId);
 
-  CheckElementResult(kPointOutsideDocument, expected_value, false);
+  CheckElementResult(kPointOutsideDocument, expected_value);
 }
 
 // Tests that an image link does not return image and link details for a point
@@ -608,7 +573,7 @@
   base::Value expected_value(base::Value::Type::DICT);
   expected_value.SetStringKey(kContextMenuElementRequestId, kRequestId);
 
-  CheckElementResult(kPointOutsideImage, expected_value, false);
+  CheckElementResult(kPointOutsideImage, expected_value);
 }
 
 // Tests that an image link returns details for both the image and the link
@@ -633,7 +598,7 @@
   expected_value.SetStringKey(kContextMenuElementHyperlink, image_link);
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that an image link returns details for both the image and the link when
@@ -659,7 +624,7 @@
   expected_value.SetStringKey(kContextMenuElementHyperlink, image_link);
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that an image link returns details for only the image and not the link
@@ -685,7 +650,7 @@
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
   // Make sure the returned JSON does not have an 'href' key.
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that an image link returns details for only the image and not the link
@@ -710,7 +675,7 @@
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
   // Make sure the returned JSON does not have an 'href' key.
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that an image link returns details for only the image and not the link
@@ -730,7 +695,7 @@
   expected_value.SetStringKey(kContextMenuElementTagName, "img");
 
   // Make sure the returned JSON does not have an 'href' key.
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that only the parent link details are returned for an image with
@@ -753,7 +718,7 @@
   expected_value.SetStringKey(kContextMenuElementHyperlink, image_link);
   expected_value.SetStringKey(kContextMenuElementTagName, "a");
 
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 #pragma mark - SVG shape links
@@ -770,7 +735,7 @@
   expected_value.SetStringKey(kContextMenuElementHyperlink, link);
   expected_value.SetStringKey(kContextMenuElementTagName, "a");
 
-  CheckElementResult(kPointOnSvgLink, expected_value, false);
+  CheckElementResult(kPointOnSvgLink, expected_value);
 }
 
 // Tests that an SVG shape xlink returns details for the link.
@@ -785,7 +750,7 @@
   expected_value.SetStringKey(kContextMenuElementHyperlink, link);
   expected_value.SetStringKey(kContextMenuElementTagName, "a");
 
-  CheckElementResult(kPointOnSvgLink, expected_value, false);
+  CheckElementResult(kPointOnSvgLink, expected_value);
 }
 
 // Tests that a point within an SVG element but outside a linked shape does not
@@ -803,7 +768,7 @@
   std::vector<const char*> ignored_keys;
   ignored_keys.push_back(kContextMenuElementTextOffset);
 
-  CheckElementResult(kPointOutsideSvgLink, expected_value, ignored_keys, false);
+  CheckElementResult(kPointOutsideSvgLink, expected_value, ignored_keys);
 }
 
 #pragma mark -
@@ -825,7 +790,7 @@
   base::Value expected_value(base::Value::Type::DICT);
   expected_value.SetStringKey(kContextMenuElementRequestId, kRequestId);
 
-  CheckElementResult(kPointOnImage, expected_value, false);
+  CheckElementResult(kPointOnImage, expected_value);
 }
 
 // Tests that __gCrWeb.findElementAtPoint reports "never" as the referrer
@@ -838,7 +803,7 @@
 
   ASSERT_TRUE(LoadHtml(html));
 
-  base::Value result = FindElementAtPoint(kPointOnImage, false);
+  base::Value result = FindElementAtPoint(kPointOnImage);
   ASSERT_TRUE(result.is_dict());
   std::string* policy = result.FindStringKey(kContextMenuElementReferrerPolicy);
   ASSERT_TRUE(policy);
@@ -883,8 +848,7 @@
   expected_value.SetStringKey(kContextMenuElementTagName, "a");
 
   // Link is at bottom of the page content.
-  CheckElementResult(CGPointMake(50.0, content_height - 100), expected_value,
-                     false);
+  CheckElementResult(CGPointMake(50.0, content_height - 100), expected_value);
 }
 
 // Tests that __gCrWeb.findElementAtPoint finds a link inside shadow DOM
@@ -903,7 +867,7 @@
   expected_value.SetStringKey(kContextMenuElementHyperlink, link);
   expected_value.SetStringKey(kContextMenuElementTagName, "a");
 
-  CheckElementResult(kPointOnShadowDomLink, expected_value, false);
+  CheckElementResult(kPointOnShadowDomLink, expected_value);
 }
 
 // Tests that a point within shadow DOM content but not on a link does not
@@ -923,8 +887,7 @@
   std::vector<const char*> ignored_keys;
   ignored_keys.push_back(kContextMenuElementTextOffset);
 
-  CheckElementResult(kPointOutsideShadowDomLink, expected_value, ignored_keys,
-                     false);
+  CheckElementResult(kPointOutsideShadowDomLink, expected_value, ignored_keys);
 }
 
 // Tests that a callout information about a link is displayed when
@@ -943,7 +906,7 @@
   expected_value.SetStringKey(kContextMenuElementHyperlink, link);
   expected_value.SetStringKey(kContextMenuElementTagName, "a");
 
-  CheckElementResult(kPointOnLink, expected_value, false);
+  CheckElementResult(kPointOnLink, expected_value);
 }
 
 // Tests that a callout information about a link is displayed when
@@ -964,7 +927,7 @@
   expected_value.SetStringKey(kContextMenuElementHyperlink, link);
   expected_value.SetStringKey(kContextMenuElementTagName, "a");
 
-  CheckElementResult(kPointOnLink, expected_value, false);
+  CheckElementResult(kPointOnLink, expected_value);
 }
 
 // Tests that no callout information about a link is displayed when
@@ -982,12 +945,14 @@
   base::Value expected_value(base::Value::Type::DICT);
   expected_value.SetStringKey(kContextMenuElementRequestId, kRequestId);
   expected_value.SetStringKey(kContextMenuElementInnerText, "link");
+  expected_value.SetStringKey(kContextMenuElementSurroundingText, "link");
   expected_value.SetStringKey(kContextMenuElementTagName, "P");
 
   std::vector<const char*> ignored_keys;
   ignored_keys.push_back(kContextMenuElementTextOffset);
+  ignored_keys.push_back(kContextMenuElementSurroundingTextOffset);
 
-  CheckElementResult(kPointOnLink, expected_value, ignored_keys, false);
+  CheckElementResult(kPointOnLink, expected_value, ignored_keys);
 }
 
 // Tests that -webkit-touch-callout property can be inherited from ancester
@@ -1004,12 +969,14 @@
   base::Value expected_value(base::Value::Type::DICT);
   expected_value.SetStringKey(kContextMenuElementRequestId, kRequestId);
   expected_value.SetStringKey(kContextMenuElementInnerText, "link");
+  expected_value.SetStringKey(kContextMenuElementSurroundingText, "link");
   expected_value.SetStringKey(kContextMenuElementTagName, "P");
 
   std::vector<const char*> ignored_keys;
   ignored_keys.push_back(kContextMenuElementTextOffset);
+  ignored_keys.push_back(kContextMenuElementSurroundingTextOffset);
 
-  CheckElementResult(kPointOnLink, expected_value, ignored_keys, false);
+  CheckElementResult(kPointOnLink, expected_value, ignored_keys);
 }
 
 // Tests that setting -webkit-touch-callout property can override the value
@@ -1031,7 +998,7 @@
   expected_value.SetStringKey(kContextMenuElementHyperlink, link);
   expected_value.SetStringKey(kContextMenuElementTagName, "a");
 
-  CheckElementResult(kPointOnLink, expected_value, false);
+  CheckElementResult(kPointOnLink, expected_value);
 }
 
 }  // namespace web
diff --git a/ios/web/js_features/context_menu/resources/all_frames_context_menu.ts b/ios/web/js_features/context_menu/resources/all_frames_context_menu.ts
index f74faf0..779108e2 100644
--- a/ios/web/js_features/context_menu/resources/all_frames_context_menu.ts
+++ b/ios/web/js_features/context_menu/resources/all_frames_context_menu.ts
@@ -76,9 +76,8 @@
   // This is defined for any text element and is an index to the tapped
   // character in `innerText`.
   textOffset?: number;
-  // `surroundingText` and `surroundingTextOffset` can be set if extra text was
-  // asked for before and after `innerText`. Note that `innerText` is contained
-  // in `surroundingText`.
+  // `surroundingText` and `surroundingTextOffset` before and after `innerText`.
+  // Note that `innerText` is contained in `surroundingText`.
   surroundingText?: string;
   surroundingTextOffset?: number;
 }
@@ -174,12 +173,9 @@
  * @param element - the element whose details will be returned.
  * @param x - horizontal center of the selected point in page coordinates.
  * @param y - Vertical center of the selected point in page coordinates.
- * @param extractSurroundingText - enables getting the surrounding characters if
- *               true.
  */
 function getResponseForTextElement(
-    element: Element, x: number, y: number,
-    extractSurroundingText: boolean): FindElementTextResult {
+    element: Element, x: number, y: number): FindElementTextResult {
   const result: FindElementTextResult = {
     tagName: element.tagName,
   };
@@ -192,12 +188,9 @@
       if (textNode.nodeType === Node.TEXT_NODE) {
         result.textOffset = range.startOffset;
         result.innerText = textNode.nodeValue ?? '';
-
-        if (extractSurroundingText) {
-          const textAndStartPos = getSurroundingText(range);
-          result.surroundingText = textAndStartPos.text;
-          result.surroundingTextOffset = textAndStartPos.position;
-        }
+        const textAndStartPos = getSurroundingText(range);
+        result.surroundingText = textAndStartPos.text;
+        result.surroundingTextOffset = textAndStartPos.position;
       }
     }
   }
@@ -215,11 +208,9 @@
  *                 coordinates.
  * @param y - vertical center of the selected point in page
  *                 coordinates.
- * @param extractSurroundingText - enables getting the surrounding characters if
- *               true.
  */
 function findElementAtPointInPageCoordinates(
-    requestId: string, x: number, y: number, extractSurroundingText: boolean) {
+    requestId: string, x: number, y: number) {
   const hitCoordinates = spiralCoordinates(x, y);
   const processedElements = new Set<Element>();
   const firstDefaultElement: Element[] = [];
@@ -233,7 +224,7 @@
                                                  coordinateDetails.y;
     const elementWasFound = findElementAtPoint(
         requestId, window.document, processedElements, coordinateX, coordinateY,
-        x, y, firstDefaultElement, extractSurroundingText);
+        x, y, firstDefaultElement);
 
     // Exit early if an element was found.
     if (elementWasFound) {
@@ -247,7 +238,7 @@
         requestId,
         getResponseForTextElement(
             firstDefaultElement[0], x - window.pageXOffset,
-            y - window.pageYOffset, extractSurroundingText));
+            y - window.pageYOffset));
     return;
   }
 
@@ -267,14 +258,11 @@
  * @param centerX - the X coordinate of the center of the target.
  * @param centerY - the Y coordinate of the center of the target.
  * @param firstDefaultElement - contains the first default element found if any.
- * @param extractSurroundingText - enables getting the surrounding characters if
- *               true.
  */
 function findElementAtPoint(
     requestId: string, root: Document|ShadowRoot,
     processedElements: Set<Element>, pointX: number, pointY: number,
-    centerX: number, centerY: number, firstDefaultElement: Element[],
-    extractSurroundingText: boolean): boolean {
+    centerX: number, centerY: number, firstDefaultElement: Element[]): boolean {
   const elements = root.elementsFromPoint(pointX, pointY);
   let foundLinkElement: HTMLAnchorElement|SVGAElement|null = null;
   for (let elementIndex = 0;
@@ -309,15 +297,13 @@
         // keep iterating.
         if (findElementAtPoint(
                 requestId, element.shadowRoot, processedElements, pointX,
-                pointY, centerX, centerY, firstDefaultElement,
-                extractSurroundingText)) {
+                pointY, centerX, centerY, firstDefaultElement)) {
           return true;
         }
       }
 
       if (processElementForFindElementAtPoint(
-              requestId, centerX, centerY, element as HTMLElement,
-              extractSurroundingText)) {
+              requestId, centerX, centerY, element as HTMLElement)) {
         return true;
       }
 
@@ -354,12 +340,10 @@
  * @param centerX - the X coordinate of the center of the target.
  * @param centerY - the Y coordinate of the center of the target.
  * @param element - element in the page.
- * @param extractSurroundingText - enables getting the surrounding characters if
- *               true.
  */
 function processElementForFindElementAtPoint(
     requestId: string, centerX: number, centerY: number,
-    element: HTMLElement|null, extractSurroundingText: boolean): boolean {
+    element: HTMLElement|null): boolean {
   if (!element || !element.tagName) {
     return false;
   }
@@ -373,7 +357,6 @@
       requestId: requestId,
       x: centerX - element.offsetLeft,
       y: centerY - element.offsetTop,
-      extractSurroundingText: extractSurroundingText
     };
     // The message will not be sent if `targetOrigin` is null, so use * which
     // allows the message to be delievered to the contentWindow regardless of
@@ -607,7 +590,7 @@
       payload.type === 'org.chromium.contextMenuMessage') {
     findElementAtPointInPageCoordinates(
         payload.requestId, payload.x + window.pageXOffset,
-        payload.y + window.pageYOffset, payload.extractSurroundingText);
+        payload.y + window.pageYOffset);
   }
 });
 
diff --git a/ios/web/js_features/context_menu/resources/main_frame_context_menu.ts b/ios/web/js_features/context_menu/resources/main_frame_context_menu.ts
index 8eec901..4b076cf5 100644
--- a/ios/web/js_features/context_menu/resources/main_frame_context_menu.ts
+++ b/ios/web/js_features/context_menu/resources/main_frame_context_menu.ts
@@ -20,15 +20,13 @@
  *                 coordinates.
  * @param y - vertical center of the selected point in web view
  *                 coordinates.
- * @param surroundingTextEnabled - enables getting the surrounding characters if
- *               true.
  */
 function findElementAtPoint(
     requestId: string, x: number, y: number, webViewWidth: number,
-    _webViewHeight: number, surroundingTextEnabled: boolean) {
+    _webViewHeight: number) {
   const scale = getPageWidth() / webViewWidth;
   gCrWeb.contextMenuAllFrames.findElementAtPointInPageCoordinates(
-      requestId, x * scale, y * scale, surroundingTextEnabled);
+      requestId, x * scale, y * scale);
 }
 
 /**
diff --git a/ios/web/text_fragments/text_fragments_java_script_feature.mm b/ios/web/text_fragments/text_fragments_java_script_feature.mm
index 5b546f7f..b02a65c 100644
--- a/ios/web/text_fragments/text_fragments_java_script_feature.mm
+++ b/ios/web/text_fragments/text_fragments_java_script_feature.mm
@@ -11,7 +11,7 @@
 #import "components/shared_highlighting/ios/parsing_utils.h"
 #import "ios/web/public/js_messaging/script_message.h"
 #import "ios/web/public/js_messaging/web_frame.h"
-#import "ios/web/public/js_messaging/web_frame_util.h"
+#import "ios/web/public/js_messaging/web_frames_manager.h"
 #import "ios/web/text_fragments/text_fragments_manager_impl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -53,7 +53,7 @@
     std::string background_color_hex_rgb,
     std::string foreground_color_hex_rgb) {
   DCHECK(web_state);
-  auto* frame = web::GetMainFrame(web_state);
+  WebFrame* frame = GetWebFramesManager(web_state)->GetMainWebFrame();
   if (!frame) {
     return;
   }
@@ -77,7 +77,7 @@
 void TextFragmentsJavaScriptFeature::RemoveHighlights(WebState* web_state,
                                                       const GURL& new_url) {
   DCHECK(web_state);
-  auto* frame = web::GetMainFrame(web_state);
+  WebFrame* frame = GetWebFramesManager(web_state)->GetMainWebFrame();
   if (!frame) {
     return;
   }
diff --git a/ios/web/text_fragments/text_fragments_manager_impl.h b/ios/web/text_fragments/text_fragments_manager_impl.h
index fd0cd886..87d1379 100644
--- a/ios/web/text_fragments/text_fragments_manager_impl.h
+++ b/ios/web/text_fragments/text_fragments_manager_impl.h
@@ -9,6 +9,7 @@
 
 #import "base/memory/weak_ptr.h"
 #import "base/values.h"
+#import "ios/web/public/js_messaging/web_frames_manager.h"
 #import "ios/web/public/text_fragments/text_fragments_manager.h"
 #import "ios/web/public/web_state_observer.h"
 #import "ios/web/text_fragments/text_fragments_java_script_feature.h"
@@ -24,6 +25,7 @@
 // Class in charge of highlighting text fragments when they are present in
 // WebStates' loaded URLs.
 class TextFragmentsManagerImpl : public TextFragmentsManager,
+                                 public WebFramesManager::Observer,
                                  public WebStateObserver {
  public:
   explicit TextFragmentsManagerImpl(WebState* web_state);
@@ -56,11 +58,13 @@
       NSString* text,
       std::vector<shared_highlighting::TextFragment> fragments);
 
+  // WebFramesManager::Observer
+  void WebFrameBecameAvailable(WebFramesManager* web_frames_manager,
+                               WebFrame* web_frame) override;
+
   // WebStateObserver methods:
   void DidFinishNavigation(WebState* web_state,
                            NavigationContext* navigation_context) override;
-  void WebFrameDidBecomeAvailable(WebState* web_state,
-                                  WebFrame* web_frame) override;
   void WebStateDestroyed(WebState* web_state) override;
 
   void SetJSFeatureForTesting(TextFragmentsJavaScriptFeature* feature);
diff --git a/ios/web/text_fragments/text_fragments_manager_impl.mm b/ios/web/text_fragments/text_fragments_manager_impl.mm
index 8132579c..0bb4aa5 100644
--- a/ios/web/text_fragments/text_fragments_manager_impl.mm
+++ b/ios/web/text_fragments/text_fragments_manager_impl.mm
@@ -13,7 +13,7 @@
 #import "components/shared_highlighting/core/common/shared_highlighting_metrics.h"
 #import "ios/web/common/features.h"
 #import "ios/web/public/js_messaging/web_frame.h"
-#import "ios/web/public/js_messaging/web_frame_util.h"
+#import "ios/web/public/js_messaging/web_frames_manager.h"
 #import "ios/web/public/navigation/navigation_context.h"
 #import "ios/web/public/navigation/navigation_item.h"
 #import "ios/web/public/navigation/navigation_manager.h"
@@ -41,6 +41,9 @@
     : web_state_(web_state) {
   DCHECK(web_state_);
   web_state_->AddObserver(this);
+  web::WebFramesManager* web_frames_manager =
+      GetJSFeature()->GetWebFramesManager(web_state);
+  web_frames_manager->AddObserver(this);
 }
 
 TextFragmentsManagerImpl::~TextFragmentsManagerImpl() {
@@ -109,6 +112,14 @@
   }
 }
 
+void TextFragmentsManagerImpl::WebFrameBecameAvailable(
+    WebFramesManager* web_frames_manager,
+    WebFrame* web_frame) {
+  if (web_frame->IsMainFrame() && deferred_processing_params_) {
+    DoHighlight();
+  }
+}
+
 void TextFragmentsManagerImpl::DidFinishNavigation(
     WebState* web_state,
     NavigationContext* navigation_context) {
@@ -125,14 +136,7 @@
     return;
   }
   deferred_processing_params_ = std::move(params);
-  if (web::GetMainFrame(web_state_)) {
-    DoHighlight();
-  }
-}
-
-void TextFragmentsManagerImpl::WebFrameDidBecomeAvailable(WebState* web_state,
-                                                          WebFrame* web_frame) {
-  if (web_frame->IsMainFrame() && deferred_processing_params_) {
+  if (GetJSFeature()->GetWebFramesManager(web_state_)->GetMainWebFrame()) {
     DoHighlight();
   }
 }
diff --git a/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm b/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm
index 804234c..5f4c7ff 100644
--- a/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm
+++ b/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm
@@ -21,6 +21,7 @@
 #import "ios/web/public/test/fakes/fake_web_frames_manager.h"
 #import "ios/web/public/test/fakes/fake_web_state.h"
 #import "ios/web/public/test/web_test.h"
+#import "ios/web/text_fragments/text_fragments_java_script_feature.h"
 #import "services/metrics/public/cpp/ukm_builders.h"
 #import "testing/gmock/include/gmock/gmock.h"
 #import "testing/gtest/include/gtest/gtest.h"
@@ -97,8 +98,12 @@
     auto fake_navigation_manager = std::make_unique<FakeNavigationManager>();
     fake_navigation_manager->SetLastCommittedItem(&last_committed_item_);
     web_state_->SetNavigationManager(std::move(fake_navigation_manager));
+    TextFragmentsJavaScriptFeature* feature =
+        TextFragmentsJavaScriptFeature::GetInstance();
     auto fake_web_frames_manager = std::make_unique<FakeWebFramesManager>();
-    web_state_->SetWebFramesManager(std::move(fake_web_frames_manager));
+    web_frames_manager_ = fake_web_frames_manager.get();
+    web_state_->SetWebFramesManager(feature->GetSupportedContentWorld(),
+                                    std::move(fake_web_frames_manager));
   }
 
   TextFragmentsManagerImpl* CreateDefaultManager() {
@@ -162,17 +167,16 @@
   }
 
   void AddMainWebFrame(TextFragmentsManagerImpl* fragments_mgr) {
-    FakeWebFramesManager* frames_mgr = static_cast<FakeWebFramesManager*>(
-        web_state_->GetPageWorldWebFramesManager());
-    frames_mgr->AddWebFrame(
+    web_frames_manager_->AddWebFrame(
         FakeWebFrame::CreateMainWebFrame(GURL("https://chromium.org")));
-    fragments_mgr->WebFrameDidBecomeAvailable(web_state_,
-                                              frames_mgr->GetMainWebFrame());
+    fragments_mgr->WebFrameDidBecomeAvailable(
+        web_state_, web_frames_manager_->GetMainWebFrame());
   }
 
   MockJSFeature feature_;
   web::FakeNavigationContext context_;
   FakeWebState* web_state_;
+  FakeWebFramesManager* web_frames_manager_;
   base::test::ScopedFeatureList feature_list_;
   NavigationItemImpl last_committed_item_;
 };
diff --git a/media/base/win/color_space_util_win.cc b/media/base/win/color_space_util_win.cc
index 27ac3ba..99b01268 100644
--- a/media/base/win/color_space_util_win.cc
+++ b/media/base/win/color_space_util_win.cc
@@ -37,6 +37,29 @@
   }
 }
 
+MFVideoPrimaries ColorSpaceToMFPrimary(gfx::ColorSpace::PrimaryID color_space) {
+  switch (color_space) {
+    case gfx::ColorSpace::PrimaryID::BT709:
+      return MFVideoPrimaries_BT709;
+    case gfx::ColorSpace::PrimaryID::BT470M:
+      return MFVideoPrimaries_BT470_2_SysM;
+    case gfx::ColorSpace::PrimaryID::BT470BG:
+      return MFVideoPrimaries_BT470_2_SysBG;
+    case gfx::ColorSpace::PrimaryID::SMPTE170M:
+      return MFVideoPrimaries_SMPTE170M;
+    case gfx::ColorSpace::PrimaryID::SMPTE240M:
+      return MFVideoPrimaries_SMPTE240M;
+    case gfx::ColorSpace::PrimaryID::BT2020:
+      return MFVideoPrimaries_BT2020;
+    case gfx::ColorSpace::PrimaryID::XYZ_D50:
+      return MFVideoPrimaries_XYZ;
+    case gfx::ColorSpace::PrimaryID::P3:
+      return MFVideoPrimaries_DCI_P3;
+    default:
+      return MFVideoPrimaries_Unknown;
+  }
+}
+
 gfx::ColorSpace::TransferID MFTransferToColorSpace(uint32_t mf_transfer) {
   switch (mf_transfer) {
     case MFVideoTransFunc_18:
@@ -60,6 +83,30 @@
   }
 }
 
+MFVideoTransferFunction ColorSpaceToMFTransfer(
+    gfx::ColorSpace::TransferID color_space) {
+  switch (color_space) {
+    case gfx::ColorSpace::TransferID::GAMMA18:
+      return MFVideoTransFunc_18;
+    case gfx::ColorSpace::TransferID::GAMMA22:
+      return MFVideoTransFunc_22;
+    case gfx::ColorSpace::TransferID::BT709:
+      return MFVideoTransFunc_709;
+    case gfx::ColorSpace::TransferID::SMPTE240M:
+      return MFVideoTransFunc_240M;
+    case gfx::ColorSpace::TransferID::SRGB:
+      return MFVideoTransFunc_sRGB;
+    case gfx::ColorSpace::TransferID::GAMMA28:
+      return MFVideoTransFunc_28;
+    case gfx::ColorSpace::TransferID::BT2020_10:
+      return MFVideoTransFunc_2020;
+    case gfx::ColorSpace::TransferID::PQ:
+      return MFVideoTransFunc_2084;
+    default:
+      return MFVideoTransFunc_Unknown;
+  }
+}
+
 gfx::ColorSpace::MatrixID MFMatrixToColorSpace(uint32_t mf_matrix) {
   switch (mf_matrix) {
     case MFVideoTransferMatrix_BT709:
@@ -77,6 +124,24 @@
   }
 }
 
+MFVideoTransferMatrix ColorSpaceToMFMatrix(
+    gfx::ColorSpace::MatrixID color_space) {
+  switch (color_space) {
+    case gfx::ColorSpace::MatrixID::BT709:
+      return MFVideoTransferMatrix_BT709;
+    case gfx::ColorSpace::MatrixID::SMPTE170M:
+      return MFVideoTransferMatrix_BT601;
+    case gfx::ColorSpace::MatrixID::SMPTE240M:
+      return MFVideoTransferMatrix_SMPTE240M;
+    case gfx::ColorSpace::MatrixID::BT2020_NCL:
+      return MFVideoTransferMatrix_BT2020_10;
+    case gfx::ColorSpace::MatrixID::BT2020_CL:
+      return MFVideoTransferMatrix_BT2020_12;
+    default:
+      return MFVideoTransferMatrix_Unknown;
+  }
+}
+
 gfx::ColorSpace::RangeID MFRangeToColorSpace(uint32_t mf_range) {
   switch (mf_range) {
     case MFNominalRange_0_255:
@@ -92,6 +157,18 @@
   }
 }
 
+MFNominalRange ColorSpaceToMFRange(gfx::ColorSpace::RangeID color_space) {
+  switch (color_space) {
+    case gfx::ColorSpace::RangeID::FULL:
+      return MFNominalRange_0_255;
+    case gfx::ColorSpace::RangeID::DERIVED:
+    case gfx::ColorSpace::RangeID::LIMITED:
+      return MFNominalRange_16_235;
+    default:
+      return MFNominalRange_Unknown;
+  }
+}
+
 }  // anonymous namespace
 
 gfx::ColorSpace GetMediaTypeColorSpace(IMFMediaType* media_type) {
@@ -124,4 +201,15 @@
   return guesser.GuessGfxColorSpace();
 }
 
+void GetMediaTypeColorValues(const gfx::ColorSpace& color_space,
+                             MFVideoPrimaries* out_primaries,
+                             MFVideoTransferFunction* out_transfer,
+                             MFVideoTransferMatrix* out_matrix,
+                             MFNominalRange* out_range) {
+  *out_primaries = ColorSpaceToMFPrimary(color_space.GetPrimaryID());
+  *out_transfer = ColorSpaceToMFTransfer(color_space.GetTransferID());
+  *out_matrix = ColorSpaceToMFMatrix(color_space.GetMatrixID());
+  *out_range = ColorSpaceToMFRange(color_space.GetRangeID());
+}
+
 }  // namespace media
\ No newline at end of file
diff --git a/media/base/win/color_space_util_win.h b/media/base/win/color_space_util_win.h
index 790ba2e7..b20c482 100644
--- a/media/base/win/color_space_util_win.h
+++ b/media/base/win/color_space_util_win.h
@@ -5,7 +5,7 @@
 #ifndef MEDIA_BASE_WIN_COLOR_SPACE_UTIL_WIN_H_
 #define MEDIA_BASE_WIN_COLOR_SPACE_UTIL_WIN_H_
 
-class IMFMediaType;
+#include <mfidl.h>
 
 #include "media/base/media_export.h"
 #include "ui/gfx/color_space.h"
@@ -14,6 +14,13 @@
 
 MEDIA_EXPORT gfx::ColorSpace GetMediaTypeColorSpace(IMFMediaType* media_type);
 
+// Converts a gfx::ColorSpace to individual MFVideo* keys.
+MEDIA_EXPORT void GetMediaTypeColorValues(const gfx::ColorSpace& color_space,
+                                          MFVideoPrimaries* out_primaries,
+                                          MFVideoTransferFunction* out_transfer,
+                                          MFVideoTransferMatrix* out_matrix,
+                                          MFNominalRange* out_range);
+
 }  // namespace media
 
 #endif  // MEDIA_BASE_WIN_COLOR_SPACE_UTIL_WIN_H_
\ No newline at end of file
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index a5951ea..386b958a 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -274,6 +274,7 @@
     ]
     deps += [
       "//gpu/ipc/common:common",
+      "//media/base/win:color_space_util_win",
       "//media/parsers",
       "//third_party/angle:includes",
       "//third_party/libvpx:libvpxrc",
diff --git a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
index 838c32a3..af6b7c56 100644
--- a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
+++ b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
@@ -32,6 +32,7 @@
 #include "media/base/media_switches.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_util.h"
+#include "media/base/win/color_space_util_win.h"
 #include "media/base/win/mf_helpers.h"
 #include "media/base/win/mf_initializer.h"
 #include "media/filters/win/media_foundation_utils.h"
@@ -1182,6 +1183,7 @@
   // There's no point in trying to feed more than one input here,
   // because MF encoder never accepts more than one input in a row.
   auto& next_input = pending_input_queue_.front();
+
   HRESULT hr = ProcessInput(next_input);
   if (hr == MF_E_NOTACCEPTING) {
     return;
@@ -1215,6 +1217,12 @@
           << "Prepared sample timestamp doesn't match frame timestamp.";
     }
   } else {
+    const auto frame_cs = input.frame->ColorSpace();
+    if (encoder_color_space_.value_or(gfx::ColorSpace()) != frame_cs) {
+      encoder_color_space_ = frame_cs;
+      SetEncoderColorSpace();
+    }
+
     // Prepare input sample if it hasn't been done yet.
     HRESULT hr = PopulateInputSampleBuffer(input);
     RETURN_ON_HR_FAILURE(hr, "Couldn't populate input sample buffer", hr);
@@ -1768,6 +1776,10 @@
     }
   }
 
+  if (encoder_color_space_) {
+    md.encoded_color_space = *encoder_color_space_;
+  }
+
   client_->BitstreamBufferReady(buffer_ref->id, md);
 }
 
@@ -2038,4 +2050,51 @@
   return QISearch(this, kQI, riid, ppv);
 }
 
+void MediaFoundationVideoEncodeAccelerator::SetEncoderColorSpace() {
+  DCHECK(encoder_color_space_);
+  if (!encoder_color_space_->IsValid()) {
+    return;
+  }
+
+  MFVideoPrimaries primary;
+  MFVideoTransferFunction transfer;
+  MFVideoTransferMatrix matrix;
+  MFNominalRange range;
+  GetMediaTypeColorValues(*encoder_color_space_, &primary, &transfer, &matrix,
+                          &range);
+
+  // Set appropriate color space keys. Note: This may do nothing depending on
+  // the hardware MFT. It's expected that if the MFT does not support color
+  // space info that it either won't write any color info in the bitstream or it
+  // will write the values for UNSPECIFIED (see VideoColorSpace).
+  auto set_color_space = [&](IMFMediaType* type) {
+    auto hr = type->SetUINT32(MF_MT_VIDEO_PRIMARIES, primary);
+    RETURN_ON_HR_FAILURE(hr, "Couldn't set primaries", hr);
+    hr = type->SetUINT32(MF_MT_TRANSFER_FUNCTION, transfer);
+    RETURN_ON_HR_FAILURE(hr, "Couldn't set transfer", hr);
+    hr = type->SetUINT32(MF_MT_YUV_MATRIX, matrix);
+    RETURN_ON_HR_FAILURE(hr, "Couldn't set matrix", hr);
+    hr = type->SetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, range);
+    RETURN_ON_HR_FAILURE(hr, "Couldn't set range", hr);
+    return hr;
+  };
+
+  // Set input and output color spaces to the same value so we don't
+  // inadvertently enable any kind of color space conversion.
+  RETURN_ON_HR_FAILURE(set_color_space(imf_output_media_type_.Get()),
+                       "Couldn't set output color space", );
+  RETURN_ON_HR_FAILURE(encoder_->SetOutputType(output_stream_id_,
+                                               imf_output_media_type_.Get(), 0),
+                       "Couldn't change output media type", );
+
+  RETURN_ON_HR_FAILURE(set_color_space(imf_input_media_type_.Get()),
+                       "Couldn't set input color space", );
+  RETURN_ON_HR_FAILURE(
+      encoder_->SetInputType(input_stream_id_, imf_input_media_type_.Get(), 0),
+      "Couldn't change input media type", );
+
+  DVLOG(1) << "Set encoder color space to: "
+           << encoder_color_space_->ToString();
+}
+
 }  // namespace media
diff --git a/media/gpu/windows/media_foundation_video_encode_accelerator_win.h b/media/gpu/windows/media_foundation_video_encode_accelerator_win.h
index 3b474255..01b81ec4 100644
--- a/media/gpu/windows/media_foundation_video_encode_accelerator_win.h
+++ b/media/gpu/windows/media_foundation_video_encode_accelerator_win.h
@@ -183,6 +183,10 @@
 
   std::unique_ptr<MediaLog> media_log_;
 
+  // Attempts to set the current frame color space on `imf_input_media_type_`
+  // and `imf_output_media_type_` and update `encoder_`.
+  void SetEncoderColorSpace();
+
   // Bitstream buffers ready to be used to return encoded output as a FIFO.
   base::circular_deque<std::unique_ptr<BitstreamBufferRef>>
       bitstream_buffer_queue_;
@@ -281,6 +285,9 @@
   // Bitrate controller for CBR encoding.
   std::unique_ptr<VideoRateControlWrapper> rate_ctrl_;
 
+  // Color space of the first frame sent to Encode().
+  absl::optional<gfx::ColorSpace> encoder_color_space_;
+
   // Declared last to ensure that all weak pointers are invalidated before
   // other destructors run.
   base::WeakPtr<MediaFoundationVideoEncodeAccelerator> weak_ptr_;
diff --git a/net/cookies/canonical_cookie_test_helpers.h b/net/cookies/canonical_cookie_test_helpers.h
index ee21a12..b3236fc02 100644
--- a/net/cookies/canonical_cookie_test_helpers.h
+++ b/net/cookies/canonical_cookie_test_helpers.h
@@ -82,11 +82,11 @@
   return testing::ExplainMatchResult(true, status.IsInclude(), result_listener);
 }
 
-// Helper for checking that status.HasDowngradeWarning() == true.
-MATCHER(HasDowngradeWarning, "") {
+// Helper for checking that status.HasSchemefulDowngradeWarning() == true.
+MATCHER(HasSchemefulDowngradeWarning, "") {
   CookieInclusionStatus status = arg;
-  return testing::ExplainMatchResult(true, status.HasDowngradeWarning(),
-                                     result_listener);
+  return testing::ExplainMatchResult(
+      true, status.HasSchemefulDowngradeWarning(), result_listener);
 }
 
 // Helper for checking that status.HasWarningReason(reason) == true.
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc
index 49f7dc7..866e4ba 100644
--- a/net/cookies/canonical_cookie_unittest.cc
+++ b/net/cookies/canonical_cookie_unittest.cc
@@ -4563,72 +4563,72 @@
       base::test::ScopedFeatureList feature_list;
       feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
 
-      EXPECT_THAT(
-          cookie_same_site_unrestricted->IsSetPermittedInContext(
-              url, context_same_site_strict_to_lax,
-              CookieAccessParams(
-                  CookieAccessSemantics::UNKNOWN,
-                  false /* delegate_treats_url_as_trustworthy */,
-                  CookieSamePartyStatus::kNoSamePartyEnforcement),
-              kCookieableSchemes),
-          MatchesCookieAccessResult(
-              AllOf(IsInclude(), Not(HasDowngradeWarning())), _, _, true));
-      EXPECT_THAT(
-          cookie_same_site_unrestricted->IsSetPermittedInContext(
-              url, context_same_site_strict_to_cross,
-              CookieAccessParams(
-                  CookieAccessSemantics::UNKNOWN,
-                  false /* delegate_treats_url_as_trustworthy */,
-                  CookieSamePartyStatus::kNoSamePartyEnforcement),
-              kCookieableSchemes),
-          MatchesCookieAccessResult(
-              AllOf(IsInclude(), Not(HasDowngradeWarning())), _, _, true));
-      EXPECT_THAT(
-          cookie_same_site_unrestricted->IsSetPermittedInContext(
-              url, context_same_site_lax_to_cross,
-              CookieAccessParams(
-                  CookieAccessSemantics::UNKNOWN,
-                  false /* delegate_treats_url_as_trustworthy */,
-                  CookieSamePartyStatus::kNoSamePartyEnforcement),
-              kCookieableSchemes),
-          MatchesCookieAccessResult(
-              AllOf(IsInclude(), Not(HasDowngradeWarning())), _, _, true));
+      EXPECT_THAT(cookie_same_site_unrestricted->IsSetPermittedInContext(
+                      url, context_same_site_strict_to_lax,
+                      CookieAccessParams(
+                          CookieAccessSemantics::UNKNOWN,
+                          false /* delegate_treats_url_as_trustworthy */,
+                          CookieSamePartyStatus::kNoSamePartyEnforcement),
+                      kCookieableSchemes),
+                  MatchesCookieAccessResult(
+                      AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())),
+                      _, _, true));
+      EXPECT_THAT(cookie_same_site_unrestricted->IsSetPermittedInContext(
+                      url, context_same_site_strict_to_cross,
+                      CookieAccessParams(
+                          CookieAccessSemantics::UNKNOWN,
+                          false /* delegate_treats_url_as_trustworthy */,
+                          CookieSamePartyStatus::kNoSamePartyEnforcement),
+                      kCookieableSchemes),
+                  MatchesCookieAccessResult(
+                      AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())),
+                      _, _, true));
+      EXPECT_THAT(cookie_same_site_unrestricted->IsSetPermittedInContext(
+                      url, context_same_site_lax_to_cross,
+                      CookieAccessParams(
+                          CookieAccessSemantics::UNKNOWN,
+                          false /* delegate_treats_url_as_trustworthy */,
+                          CookieSamePartyStatus::kNoSamePartyEnforcement),
+                      kCookieableSchemes),
+                  MatchesCookieAccessResult(
+                      AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())),
+                      _, _, true));
     }
     {
       // Schemeful Same-Site enabled.
       base::test::ScopedFeatureList feature_list;
       feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
 
-      EXPECT_THAT(
-          cookie_same_site_unrestricted->IsSetPermittedInContext(
-              url, context_same_site_strict_to_lax,
-              CookieAccessParams(
-                  CookieAccessSemantics::UNKNOWN,
-                  false /* delegate_treats_url_as_trustworthy */,
-                  CookieSamePartyStatus::kNoSamePartyEnforcement),
-              kCookieableSchemes),
-          MatchesCookieAccessResult(
-              AllOf(IsInclude(), Not(HasDowngradeWarning())), _, _, true));
-      EXPECT_THAT(
-          cookie_same_site_unrestricted->IsSetPermittedInContext(
-              url, context_same_site_strict_to_cross,
-              CookieAccessParams(
-                  CookieAccessSemantics::UNKNOWN,
-                  false /* delegate_treats_url_as_trustworthy */,
-                  CookieSamePartyStatus::kNoSamePartyEnforcement),
-              kCookieableSchemes),
-          MatchesCookieAccessResult(
-              AllOf(IsInclude(), Not(HasDowngradeWarning())), _, _, true));
-      EXPECT_THAT(
-          cookie_same_site_unrestricted->IsSetPermittedInContext(
-              url, context_same_site_lax_to_cross,
-              CookieAccessParams(
-                  CookieAccessSemantics::UNKNOWN,
-                  false /* delegate_treats_url_as_trustworthy */,
-                  CookieSamePartyStatus::kNoSamePartyEnforcement),
-              kCookieableSchemes),
-          MatchesCookieAccessResult(
-              AllOf(IsInclude(), Not(HasDowngradeWarning())), _, _, true));
+      EXPECT_THAT(cookie_same_site_unrestricted->IsSetPermittedInContext(
+                      url, context_same_site_strict_to_lax,
+                      CookieAccessParams(
+                          CookieAccessSemantics::UNKNOWN,
+                          false /* delegate_treats_url_as_trustworthy */,
+                          CookieSamePartyStatus::kNoSamePartyEnforcement),
+                      kCookieableSchemes),
+                  MatchesCookieAccessResult(
+                      AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())),
+                      _, _, true));
+      EXPECT_THAT(cookie_same_site_unrestricted->IsSetPermittedInContext(
+                      url, context_same_site_strict_to_cross,
+                      CookieAccessParams(
+                          CookieAccessSemantics::UNKNOWN,
+                          false /* delegate_treats_url_as_trustworthy */,
+                          CookieSamePartyStatus::kNoSamePartyEnforcement),
+                      kCookieableSchemes),
+                  MatchesCookieAccessResult(
+                      AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())),
+                      _, _, true));
+      EXPECT_THAT(cookie_same_site_unrestricted->IsSetPermittedInContext(
+                      url, context_same_site_lax_to_cross,
+                      CookieAccessParams(
+                          CookieAccessSemantics::UNKNOWN,
+                          false /* delegate_treats_url_as_trustworthy */,
+                          CookieSamePartyStatus::kNoSamePartyEnforcement),
+                      kCookieableSchemes),
+                  MatchesCookieAccessResult(
+                      AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())),
+                      _, _, true));
     }
   }
 
@@ -4671,16 +4671,16 @@
       base::test::ScopedFeatureList feature_list;
       feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
 
-      EXPECT_THAT(
-          cookie_same_site_lax->IsSetPermittedInContext(
-              url, context_same_site_strict_to_lax,
-              CookieAccessParams(
-                  CookieAccessSemantics::UNKNOWN,
-                  false /* delegate_treats_url_as_trustworthy */,
-                  CookieSamePartyStatus::kNoSamePartyEnforcement),
-              kCookieableSchemes),
-          MatchesCookieAccessResult(
-              AllOf(IsInclude(), Not(HasDowngradeWarning())), _, _, true));
+      EXPECT_THAT(cookie_same_site_lax->IsSetPermittedInContext(
+                      url, context_same_site_strict_to_lax,
+                      CookieAccessParams(
+                          CookieAccessSemantics::UNKNOWN,
+                          false /* delegate_treats_url_as_trustworthy */,
+                          CookieSamePartyStatus::kNoSamePartyEnforcement),
+                      kCookieableSchemes),
+                  MatchesCookieAccessResult(
+                      AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())),
+                      _, _, true));
       EXPECT_THAT(cookie_same_site_lax->IsSetPermittedInContext(
                       url, context_same_site_strict_to_cross,
                       CookieAccessParams(
@@ -4713,16 +4713,16 @@
       base::test::ScopedFeatureList feature_list;
       feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
 
-      EXPECT_THAT(
-          cookie_same_site_lax->IsSetPermittedInContext(
-              url, context_same_site_strict_to_lax,
-              CookieAccessParams(
-                  CookieAccessSemantics::UNKNOWN,
-                  false /* delegate_treats_url_as_trustworthy */,
-                  CookieSamePartyStatus::kNoSamePartyEnforcement),
-              kCookieableSchemes),
-          MatchesCookieAccessResult(
-              AllOf(IsInclude(), Not(HasDowngradeWarning())), _, _, true));
+      EXPECT_THAT(cookie_same_site_lax->IsSetPermittedInContext(
+                      url, context_same_site_strict_to_lax,
+                      CookieAccessParams(
+                          CookieAccessSemantics::UNKNOWN,
+                          false /* delegate_treats_url_as_trustworthy */,
+                          CookieSamePartyStatus::kNoSamePartyEnforcement),
+                      kCookieableSchemes),
+                  MatchesCookieAccessResult(
+                      AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())),
+                      _, _, true));
       EXPECT_THAT(cookie_same_site_lax->IsSetPermittedInContext(
                       url, context_same_site_strict_to_cross,
                       CookieAccessParams(
@@ -4798,16 +4798,16 @@
       base::test::ScopedFeatureList feature_list;
       feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
 
-      EXPECT_THAT(
-          cookie_same_site_strict->IsSetPermittedInContext(
-              url, context_same_site_strict_to_lax,
-              CookieAccessParams(
-                  CookieAccessSemantics::UNKNOWN,
-                  false /* delegate_treats_url_as_trustworthy */,
-                  CookieSamePartyStatus::kNoSamePartyEnforcement),
-              kCookieableSchemes),
-          MatchesCookieAccessResult(
-              AllOf(IsInclude(), Not(HasDowngradeWarning())), _, _, true));
+      EXPECT_THAT(cookie_same_site_strict->IsSetPermittedInContext(
+                      url, context_same_site_strict_to_lax,
+                      CookieAccessParams(
+                          CookieAccessSemantics::UNKNOWN,
+                          false /* delegate_treats_url_as_trustworthy */,
+                          CookieSamePartyStatus::kNoSamePartyEnforcement),
+                      kCookieableSchemes),
+                  MatchesCookieAccessResult(
+                      AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())),
+                      _, _, true));
       EXPECT_THAT(
           cookie_same_site_strict->IsSetPermittedInContext(
               url, context_same_site_strict_to_cross,
@@ -4841,16 +4841,16 @@
       base::test::ScopedFeatureList feature_list;
       feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
 
-      EXPECT_THAT(
-          cookie_same_site_strict->IsSetPermittedInContext(
-              url, context_same_site_strict_to_lax,
-              CookieAccessParams(
-                  CookieAccessSemantics::UNKNOWN,
-                  false /* delegate_treats_url_as_trustworthy */,
-                  CookieSamePartyStatus::kNoSamePartyEnforcement),
-              kCookieableSchemes),
-          MatchesCookieAccessResult(
-              AllOf(IsInclude(), Not(HasDowngradeWarning())), _, _, true));
+      EXPECT_THAT(cookie_same_site_strict->IsSetPermittedInContext(
+                      url, context_same_site_strict_to_lax,
+                      CookieAccessParams(
+                          CookieAccessSemantics::UNKNOWN,
+                          false /* delegate_treats_url_as_trustworthy */,
+                          CookieSamePartyStatus::kNoSamePartyEnforcement),
+                      kCookieableSchemes),
+                  MatchesCookieAccessResult(
+                      AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())),
+                      _, _, true));
       EXPECT_THAT(
           cookie_same_site_strict->IsSetPermittedInContext(
               url, context_same_site_strict_to_cross,
diff --git a/net/cookies/cookie_inclusion_status.cc b/net/cookies/cookie_inclusion_status.cc
index 0a7633e1..0022857 100644
--- a/net/cookies/cookie_inclusion_status.cc
+++ b/net/cookies/cookie_inclusion_status.cc
@@ -121,7 +121,7 @@
   return warning_reasons_[reason];
 }
 
-bool CookieInclusionStatus::HasDowngradeWarning(
+bool CookieInclusionStatus::HasSchemefulDowngradeWarning(
     CookieInclusionStatus::WarningReason* reason) const {
   if (!ShouldWarn())
     return false;
@@ -165,7 +165,7 @@
 
   // Don't bother checking the return value because the default switch case
   // will handle if no reason was found.
-  HasDowngradeWarning(&reason);
+  HasSchemefulDowngradeWarning(&reason);
 
   switch (reason) {
     case WarningReason::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE:
diff --git a/net/cookies/cookie_inclusion_status.h b/net/cookies/cookie_inclusion_status.h
index 129b13a..32bae95 100644
--- a/net/cookies/cookie_inclusion_status.h
+++ b/net/cookies/cookie_inclusion_status.h
@@ -309,7 +309,7 @@
   // SameSiteCookieContext::|schemeful_context| downgrade that will prevent its
   // access schemefully. If the function returns true and |reason| is valid then
   // |reason| will contain which warning was found.
-  bool HasDowngradeWarning(
+  bool HasSchemefulDowngradeWarning(
       CookieInclusionStatus::WarningReason* reason = nullptr) const;
 
   // Add an warning reason.
diff --git a/net/cookies/cookie_inclusion_status_unittest.cc b/net/cookies/cookie_inclusion_status_unittest.cc
index 3873bc4..e896c26e9 100644
--- a/net/cookies/cookie_inclusion_status_unittest.cc
+++ b/net/cookies/cookie_inclusion_status_unittest.cc
@@ -145,7 +145,7 @@
       CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT));
 }
 
-TEST(CookieInclusionStatusTest, HasDowngradeWarning) {
+TEST(CookieInclusionStatusTest, HasSchemefulDowngradeWarning) {
   std::vector<CookieInclusionStatus::WarningReason> downgrade_warnings = {
       CookieInclusionStatus::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE,
       CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE,
@@ -155,19 +155,19 @@
   };
 
   CookieInclusionStatus empty_status;
-  EXPECT_FALSE(empty_status.HasDowngradeWarning());
+  EXPECT_FALSE(empty_status.HasSchemefulDowngradeWarning());
 
   CookieInclusionStatus not_downgrade;
   not_downgrade.AddWarningReason(
       CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT);
-  EXPECT_FALSE(not_downgrade.HasDowngradeWarning());
+  EXPECT_FALSE(not_downgrade.HasSchemefulDowngradeWarning());
 
   for (auto warning : downgrade_warnings) {
     CookieInclusionStatus status;
     status.AddWarningReason(warning);
     CookieInclusionStatus::WarningReason reason;
 
-    EXPECT_TRUE(status.HasDowngradeWarning(&reason));
+    EXPECT_TRUE(status.HasSchemefulDowngradeWarning(&reason));
     EXPECT_EQ(warning, reason);
   }
 }
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index e3f5577..ebe25df 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -9126,6 +9126,47 @@
   RemoveMockTransaction(&transaction);
 }
 
+// Similar to UnknownRangeGET_2, except that the resource size is empty.
+// Regression test for crbug.com/813061, and probably https://crbug.com/1375128
+TEST_F(HttpCacheTest, UnknownRangeGET_3) {
+  MockHttpCache cache;
+  std::string headers;
+
+  ScopedMockTransaction transaction(kSimpleGET_Transaction);
+  transaction.response_headers =
+      "Cache-Control: max-age=10000\n"
+      "Content-Length: 0\n",
+  transaction.data = "";
+  transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
+                          TEST_MODE_SYNC_CACHE_READ |
+                          TEST_MODE_SYNC_CACHE_WRITE;
+
+  // Write the empty resource to the cache.
+  RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
+
+  EXPECT_EQ(
+      "HTTP/1.1 200 OK\nCache-Control: max-age=10000\nContent-Length: 0\n",
+      headers);
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+  // Make sure we are done with the previous transaction.
+  base::RunLoop().RunUntilIdle();
+
+  // Write and read from the cache. This used to trigger a DCHECK
+  // (or loop infinitely with it off).
+  transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER;
+  RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
+
+  EXPECT_EQ(
+      "HTTP/1.1 200 OK\nCache-Control: max-age=10000\nContent-Length: 0\n",
+      headers);
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
+  EXPECT_EQ(1, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+}
+
 // Tests that receiving Not Modified when asking for an open range doesn't mess
 // up things.
 TEST_F(HttpCacheTest, UnknownRangeGET_304) {
diff --git a/net/http/partial_data.cc b/net/http/partial_data.cc
index 7b3bc39a..f58ef98 100644
--- a/net/http/partial_data.cc
+++ b/net/http/partial_data.cc
@@ -354,20 +354,21 @@
   if (truncated_)
     return;
 
-  if (byte_range_.IsValid() && success) {
-    headers->UpdateWithNewRange(byte_range_, resource_size_, !sparse_entry_);
-    return;
-  }
-
-  if (byte_range_.IsValid()) {
+  if (!success) {
     headers->ReplaceStatusLine("HTTP/1.1 416 Requested Range Not Satisfiable");
     headers->SetHeader(
         kRangeHeader, base::StringPrintf("bytes 0-0/%" PRId64, resource_size_));
     headers->SetHeader(kLengthHeader, "0");
+    return;
+  }
+
+  if (byte_range_.IsValid() && resource_size_) {
+    headers->UpdateWithNewRange(byte_range_, resource_size_, !sparse_entry_);
   } else {
-    // TODO(rvargas): Is it safe to change the protocol version?
-    headers->ReplaceStatusLine("HTTP/1.1 200 OK");
-    DCHECK_NE(resource_size_, 0);
+    if (headers->response_code() == net::HTTP_PARTIAL_CONTENT) {
+      // TODO(rvargas): Is it safe to change the protocol version?
+      headers->ReplaceStatusLine("HTTP/1.1 200 OK");
+    }
     headers->RemoveHeader(kRangeHeader);
     headers->SetHeader(kLengthHeader,
                        base::StringPrintf("%" PRId64, resource_size_));
@@ -433,6 +434,9 @@
 }
 
 int PartialData::GetNextRangeLen() {
+  if (!resource_size_) {
+    return 0;
+  }
   int64_t range_len =
       byte_range_.HasLastBytePosition()
           ? byte_range_.last_byte_position() - current_range_start_ + 1
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 480a0f12..32c2916 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -562,16 +562,9 @@
     { "name": "messenger.com", "policy": "custom", "mode": "force-https" },
     { "name": "www.messenger.com", "policy": "custom", "mode": "force-https", "include_subdomains": true },
 
-    // Enforce HSTS and public key pins for Twitter domains.
+    // Enforce HSTS for Twitter domains.
     { "name": "twitter.com", "policy": "custom", "mode": "force-https" },
     { "name": "www.twitter.com", "policy": "custom", "mode": "force-https", "include_subdomains": true },
-    { "name": "api.twitter.com", "policy": "custom", "include_subdomains": true },
-    { "name": "oauth.twitter.com", "policy": "custom", "include_subdomains": true },
-    { "name": "mobile.twitter.com", "policy": "custom", "include_subdomains": true },
-    { "name": "dev.twitter.com", "policy": "custom", "include_subdomains": true },
-    { "name": "business.twitter.com", "policy": "custom", "include_subdomains": true },
-    { "name": "platform.twitter.com", "policy": "custom", "include_subdomains": true },
-    { "name": "twimg.com", "policy": "custom", "include_subdomains": true },
 
     // START OF LEGACY MANUAL CUSTOM ENTRIES
     { "name": "www.paypal.com", "policy": "custom", "mode": "force-https" },
@@ -703,8 +696,6 @@
       "name": "www.dropbox.com", "policy": "custom",
       "mode": "force-https", "include_subdomains": true
     },
-    { "name": "dropboxstatic.com", "policy": "custom" },
-    { "name": "dropboxusercontent.com", "policy": "custom" },
     { "name": "jackyyf.com", "policy": "custom", "mode": "force-https" },
     { "name": "gamesdepartment.co.uk", "policy": "custom", "mode": "force-https" },
     { "name": "gparent.org", "policy": "custom", "mode": "force-https" },
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins
index 39d5f33..052fe46 100644
--- a/net/http/transport_security_state_static.pins
+++ b/net/http/transport_security_state_static.pins
@@ -43,39 +43,13 @@
 #   hash function for preloaded entries again (we have already done so once).
 #
 
-# Last updated: 2023-04-17 12:55 UTC
+# Last updated: 2023-04-25 12:56 UTC
 PinsListTimestamp
-1681736112
+1682427372
 
 TestSPKI
 sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
 
-VeriSignClass3_G3
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
-LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
-aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
-VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
-aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
-bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
-IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
-N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
-KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
-kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
-CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
-Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
-imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
-2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
-DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
-/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
-F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
-TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
------END CERTIFICATE-----
-
 GoogleBackup2048
 -----BEGIN PUBLIC KEY-----
 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuuYB7COWpsVCLYy0iOzd
@@ -233,29 +207,6 @@
 b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S
 -----END CERTIFICATE-----
 
-GeoTrustPrimary
------BEGIN CERTIFICATE-----
-MIIDizCCAvSgAwIBAgIDDW5iMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
-MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
-aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMTI3MDAwMDAwWhcNMTgwODIxMTYxNTAw
-WjBYMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UE
-AxMoR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIw
-DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL64FXv/1Hx9Z62DZHvIQlMt3/aE
-CCBh1gFZapxEEa/vdv2Vfs5hMLt6g18CvQFmyu4VjW+hMJy9oYWelDrzVogAMc/Y
-7mqWAtntA4z7dW3n6rhVFgUWmvTgXrGIwGSFXBVNiMe3uuB16a0FPZ3HiUjguyjI
-A+Ewk2ReUsBZcCI1V4iK8ZUKg9e8MXMBNO3vRnHgawKoNXJrl5tm4MsceV/YGgRo
-HkcC5p1g4jaXAd/ONZLfvmfHbXdZO4+d1pAVlLxCNBDBOfmxJz5+1op1xbKvltOi
-3pvkmL594emBrbZv/NcO2uA0sA0ad+fjCJjvWPqchLc2r8LfrNL0EAZwcTUCAwEA
-AaOB6DCB5TAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFCzVUEGXFYvwjzZhW0r7
-a9mZyTOSMB8GA1UdIwQYMBaAFEjmaPkr0rKV10fYIyAQTzOYkJ/UMA8GA1UdEwEB
-/wQFMAMBAf8wOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5j
-b20vY3Jscy9zZWN1cmVjYS5jcmwwRgYDVR0gBD8wPTA7BgRVHSAAMDMwMQYIKwYB
-BQUHAgEWJWh0dHA6Ly93d3cuZ2VvdHJ1c3QuY29tL3Jlc291cmNlcy9jcHMwDQYJ
-KoZIhvcNAQEFBQADgYEAr/MO1nKrx6mXyiprhDneeanwgeUIZ6vXLyACAXEMBCLJ
-HoiVA8lJOq9nCEmw1Qj1ID2AkaDFh6P7yaMXkfmoL67pD9+Wcg91F4BdeAFNnx9t
-e9j1QjgjGpmT9IO+OzV05zcTNXqstLaQgmwnpODsnjW9v+UpoUefWzL86Zl9Kzk=
------END CERTIFICATE-----
-
 RapidSSL
 -----BEGIN CERTIFICATE-----
 MIID1TCCAr2gAwIBAgIDAjbRMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
@@ -387,847 +338,6 @@
 1wIDAQAB
 -----END PUBLIC KEY-----
 
-VeriSignClass1
------BEGIN CERTIFICATE-----
-MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh
-c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05
-NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD
-VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp
-bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N
-H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR
-4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN
-BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo
-EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5
-FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx
-lA==
------END CERTIFICATE-----
-
-VeriSignClass3_G4
------BEGIN CERTIFICATE-----
-MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL
-MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
-ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln
-biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
-U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
-aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp
-U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg
-SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln
-biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
-IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm
-GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve
-fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw
-AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ
-aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj
-aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW
-kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC
-4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga
-FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
------END CERTIFICATE-----
-
-VeriSignClass4_G3
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
-LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
-aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
-VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
-aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
-bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
-IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1
-GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ
-+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd
-U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm
-NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY
-ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/
-ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1
-CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq
-g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm
-fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c
-2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/
-bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==
------END CERTIFICATE-----
-
-VeriSignClass1_G3
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
-LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
-aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
-VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
-aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
-bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
-IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4
-nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO
-8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV
-ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb
-PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2
-6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr
-n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a
-qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4
-wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3
-ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs
-pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4
-E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g==
------END CERTIFICATE-----
-
-VeriSignClass2_G3
------BEGIN CERTIFICATE-----
-MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy
-aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s
-IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp
-Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
-eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV
-BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp
-Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu
-Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g
-Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
-IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU
-J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO
-JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY
-wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o
-koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN
-qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E
-Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe
-xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u
-7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU
-sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI
-sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP
-cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q
------END CERTIFICATE-----
-
-VeriSignClass3_G2
------BEGIN CERTIFICATE-----
-MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
-c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
-MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
-emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
-DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
-YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
-MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4
-pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0
-13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID
-AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk
-U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
-F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY
-oJ2daZH9
------END CERTIFICATE-----
-
-VeriSignClass2_G2
------BEGIN CERTIFICATE-----
-MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns
-YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH
-MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y
-aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe
-Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX
-MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj
-IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx
-KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
-eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM
-HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw
-DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC
-AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji
-nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX
-rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn
-jBJ7xUS0rg==
------END CERTIFICATE-----
-
-VeriSignClass3_G5
------BEGIN CERTIFICATE-----
-MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
-yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
-ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
-U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
-ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
-MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
-ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
-biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
-U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
-aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
-nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
-t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
-SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
-BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
-rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
-NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
-BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
-BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
-aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
-MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
-p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
-5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
-WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
-4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
-hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
------END CERTIFICATE-----
-
-VeriSignUniversal
------BEGIN CERTIFICATE-----
-MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB
-vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
-ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp
-U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W
-ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
-Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX
-MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0
-IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y
-IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh
-bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
-AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF
-9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH
-H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H
-LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN
-/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT
-rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud
-EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw
-WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs
-exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
-DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4
-sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+
-seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz
-4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+
-BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR
-lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3
-7M2CYfE45k+XmCpajQ==
------END CERTIFICATE-----
-
-Twitter1
------BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApNG3ovIHXvy3YJ64Eq2O
-6J0gV0i1nbnWrPdNFHoR1y6rAKJzhCTq0XY69W+1GjHw5scQ/zhVxsYJku2BB+9i
-jvzk5Yl5j0EYqWyCmNGqTXwX7b4A9+pLFs95RjooxwVkhRA57tcEuWEXX1dJlca+
-qOmrs+jisCmu9Kvs4cichyuAoYwc3/pgevGErrXg7lMmJKASa5WGPV8/prS2KQmH
-wZMIAAWXUTmVRQRFshAET1rzBbcDfjf4lX5UVPzSYzUDbL4yNyHPIOWrewVfP7Mg
-WB6VB5x8aEgyePZF0dbNZN/mFJuXZU+NNzogP2z0dfmWoh1I2H5389yPBEU+9o4M
-nQIDAQAB
------END PUBLIC KEY-----
-
-GeoTrustGlobal2
------BEGIN CERTIFICATE-----
-MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW
-MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs
-IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG
-EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg
-R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A
-PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8
-Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL
-TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL
-5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7
-S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe
-2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
-FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap
-EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td
-EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv
-/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN
-A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0
-abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF
-I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz
-4iIprn2DQKi6bA==
------END CERTIFICATE-----
-
-GeoTrustUniversal
------BEGIN CERTIFICATE-----
-MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW
-MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy
-c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE
-BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0
-IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV
-VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8
-cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT
-QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh
-F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v
-c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w
-mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd
-VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX
-teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ
-f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe
-Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+
-nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB
-/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY
-MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG
-9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
-aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX
-IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn
-ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z
-uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN
-Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja
-QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW
-koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9
-ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt
-DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm
-bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw=
------END CERTIFICATE-----
-
-GeoTrustUniversal2
------BEGIN CERTIFICATE-----
-MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW
-MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy
-c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD
-VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1
-c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
-AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81
-WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG
-FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq
-XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL
-se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb
-KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd
-IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73
-y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt
-hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc
-QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4
-Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV
-HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV
-HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
-KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
-dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ
-L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr
-Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo
-ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY
-T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz
-GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m
-1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV
-OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH
-6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX
-QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
------END CERTIFICATE-----
-
-GeoTrustPrimary_G2
------BEGIN CERTIFICATE-----
-MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL
-MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj
-KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2
-MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
-eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV
-BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw
-NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV
-BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH
-MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL
-So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal
-tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
-BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG
-CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT
-qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz
-rD6ogRLQy7rQkgu2npaqBA+K
------END CERTIFICATE-----
-
-GeoTrustPrimary_G3
------BEGIN CERTIFICATE-----
-MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB
-mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT
-MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
-eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv
-cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ
-BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
-MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0
-BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz
-+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm
-hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn
-5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W
-JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL
-DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC
-huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
-HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB
-AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB
-zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN
-kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
-AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH
-SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G
-spki4cErx5z481+oghLrGREt
------END CERTIFICATE-----
-
-Entrust_2048
------BEGIN CERTIFICATE-----
-MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
-ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
-bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
-BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
-NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
-d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
-MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
-ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
-MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
-Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
-hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
-nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
-VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
-BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
-KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
-T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
-zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
-J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
-nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
------END CERTIFICATE-----
-
-Entrust_EV
------BEGIN CERTIFICATE-----
-MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
-VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
-Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
-KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
-cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
-NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
-NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
-ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
-BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
-Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
-4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
-KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
-rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
-94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
-sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
-gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
-kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
-vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
-A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
-O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
-AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
-9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
-eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
-0vdXcDazv/wor3ElhVsT/h5/WrQ8
------END CERTIFICATE-----
-
-Entrust_G2
------BEGIN CERTIFICATE-----
-MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC
-VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50
-cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs
-IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz
-dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy
-NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu
-dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt
-dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0
-aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj
-YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
-AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T
-RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN
-cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW
-wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1
-U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0
-jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP
-BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN
-BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/
-jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
-Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v
-1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R
-nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH
-VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g==
------END CERTIFICATE-----
-
-Entrust_SSL
------BEGIN CERTIFICATE-----
-MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
-VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
-ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
-KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
-ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1
-MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE
-ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j
-b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
-bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg
-U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA
-A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/
-I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3
-wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC
-AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb
-oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5
-BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p
-dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk
-MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp
-b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
-dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0
-MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi
-E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa
-MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI
-hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN
-95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd
-2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
------END CERTIFICATE-----
-
-AAACertificateServices
------BEGIN CERTIFICATE-----
-MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
-MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
-GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
-YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
-MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
-BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
-GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
-BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
-3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
-YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
-rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
-ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
-oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
-MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
-QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
-b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
-AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
-GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
-Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
-G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
-l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
-smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
------END CERTIFICATE-----
-
-AddTrustClass1CARoot
------BEGIN CERTIFICATE-----
-MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
-b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw
-MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
-QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD
-VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA
-A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul
-CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n
-tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl
-dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch
-PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC
-+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O
-BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E
-BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl
-MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk
-ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB
-IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X
-7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz
-43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
-eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl
-pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA
-WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
------END CERTIFICATE-----
-
-AddTrustExternalCARoot
------BEGIN CERTIFICATE-----
-MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
-IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
-MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
-FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
-bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
-dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
-H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
-uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
-mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
-a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
-E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
-WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
-VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
-Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
-cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
-IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
-AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
-YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
-6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
-Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
-c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
-mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
------END CERTIFICATE-----
-
-AddTrustPublicCARoot
------BEGIN CERTIFICATE-----
-MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
-b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx
-MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB
-ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV
-BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV
-6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX
-GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP
-dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH
-1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF
-62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW
-BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw
-AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL
-MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU
-cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv
-b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6
-IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/
-iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
-GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh
-4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm
-XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
------END CERTIFICATE-----
-
-AddTrustQualifiedCARoot
------BEGIN CERTIFICATE-----
-MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
-b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1
-MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK
-EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh
-BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B
-AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq
-xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G
-87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i
-2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U
-WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1
-0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G
-A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T
-AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr
-pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL
-ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm
-aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv
-hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm
-hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
-dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3
-P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y
-iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no
-xqE=
------END CERTIFICATE-----
-
-COMODOCertificationAuthority
------BEGIN CERTIFICATE-----
-MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
-gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
-A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
-BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
-MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
-YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
-RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
-UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
-2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
-Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
-+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
-DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
-nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
-/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
-PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
-QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
-SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
-IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
-RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
-zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
-BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
-ZQ==
------END CERTIFICATE-----
-
-SecureCertificateServices
------BEGIN CERTIFICATE-----
-MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb
-MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
-GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp
-ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow
-fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
-A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV
-BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB
-BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM
-cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S
-HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996
-CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk
-3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz
-6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV
-HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
-EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv
-Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw
-Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww
-DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0
-5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
-Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI
-gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ
-aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl
-izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk=
------END CERTIFICATE-----
-
-TrustedCertificateServices
------BEGIN CERTIFICATE-----
-MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb
-MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
-GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0
-aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla
-MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
-BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD
-VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B
-AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW
-fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt
-TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL
-fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW
-1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7
-kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G
-A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD
-VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v
-ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo
-dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu
-Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/
-HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
-pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS
-jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+
-xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn
-dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi
------END CERTIFICATE-----
-
-UTNDATACorpSGC
------BEGIN CERTIFICATE-----
-MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB
-kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
-Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
-dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw
-IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG
-EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD
-VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu
-dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN
-BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6
-E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ
-D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK
-4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq
-lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW
-bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB
-o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT
-MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js
-LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr
-BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB
-AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft
-Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj
-j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH
-KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv
-2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3
-mfnGV/TJVTl4uix5yaaIK/QI
------END CERTIFICATE-----
-
-UTNUSERFirstClientAuthenticationandEmail
------BEGIN CERTIFICATE-----
-MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB
-rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
-Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
-dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt
-Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa
-Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV
-BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l
-dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE
-AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B
-YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9
-hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l
-L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm
-SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM
-1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws
-6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
-DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw
-Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50
-aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
-AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u
-7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0
-xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ
-rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim
-eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk
-USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ=
------END CERTIFICATE-----
-
-UTNUSERFirstHardware
------BEGIN CERTIFICATE-----
-MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB
-lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
-Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
-dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
-SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG
-A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe
-MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v
-d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh
-cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn
-0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ
-M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a
-MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd
-oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI
-DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy
-oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
-VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0
-dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy
-bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF
-BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
-//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli
-CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE
-CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t
-3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS
-KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA==
------END CERTIFICATE-----
-
-UTNUSERFirstObject
------BEGIN CERTIFICATE-----
-MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCB
-lTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
-Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
-dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAbBgNVBAMTFFVUTi1VU0VSRmlyc3Qt
-T2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAzNlowgZUxCzAJBgNV
-BAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxHjAc
-BgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3
-dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCC
-ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicP
-HxzfOpuCaDDASmEd8S8O+r5596Uj71VRloTN2+O5bj4x2AogZ8f02b+U60cEPgLO
-KqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQw5ujm9M89RKZd7G3CeBo
-5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vulBe3/IW+
-pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehb
-kkj7RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUC
-AwEAAaOBrzCBrDALBgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
-FgQU2u1kdBScFDyr3ZmpvVsoTYs8ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov
-L2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0LmNybDApBgNV
-HSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQwDQYJKoZIhvcN
-AQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw
-NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXB
-mMiKVl0+7kNOPmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU
-4U3GDZlDAQ0Slox4nb9QorFEqmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK5
-81OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCGhU3IfdeLA/5u1fedFqySLKAj5ZyR
-Uh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g=
------END CERTIFICATE-----
-
-GTECyberTrustGlobalRoot
------BEGIN CERTIFICATE-----
-MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD
-VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv
-bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv
-b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV
-UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
-cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
-b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH
-iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS
-r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4
-04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r
-GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9
-3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P
-lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
------END CERTIFICATE-----
-
-BaltimoreCyberTrustRoot
------BEGIN CERTIFICATE-----
-MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
-RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
-VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
-DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
-ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
-VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
-mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
-IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
-mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
-XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
-dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
-jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
-BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
-DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
-9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
-jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
-Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
-ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
-R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
------END CERTIFICATE-----
-
 GlobalSignRootCA
 -----BEGIN CERTIFICATE-----
 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
@@ -1384,108 +494,6 @@
 WD9f
 -----END CERTIFICATE-----
 
-EntrustRootEC1
------BEGIN CERTIFICATE-----
-MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG
-A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3
-d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu
-dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq
-RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy
-MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD
-VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
-L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g
-Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD
-ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi
-A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt
-ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH
-Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
-BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC
-R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX
-hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
------END CERTIFICATE-----
-
-TheGoDaddyGroupClass2
------BEGIN CERTIFICATE-----
-MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
-MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
-YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
-MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
-ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
-MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
-ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
-PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
-wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
-EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
-avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
-YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
-sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
-/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
-IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
-YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
-OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
-TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
-HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
-dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
-ReYNnyicsbkqWletNw+vHX/bvZ8=
------END CERTIFICATE-----
-
-GoDaddyRoot_G2
------BEGIN CERTIFICATE-----
-MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
-EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
-EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
-ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
-NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
-EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
-AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
-DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
-E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
-/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
-DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
-GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
-tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
-AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
-FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
-WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
-9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
-gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
-2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
-LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
-4uJEvlz36hz1
------END CERTIFICATE-----
-
-GoDaddySecure
------BEGIN CERTIFICATE-----
-MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx
-ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
-RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw
-MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH
-QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j
-b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j
-b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj
-YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN
-AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H
-KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm
-VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR
-SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT
-cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ
-6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu
-MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS
-kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB
-BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f
-BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv
-c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH
-AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO
-BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG
-OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU
-A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o
-0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX
-RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH
-qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV
-U+4=
------END CERTIFICATE-----
-
 SymantecClass3EVG3
 -----BEGIN CERTIFICATE-----
 MIIFKzCCBBOgAwIBAgIQfuFKb2/v8tN/P61lTTratDANBgkqhkiG9w0BAQsFADCB
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json
index 3cfbb75..bf3b133 100644
--- a/net/http/transport_security_state_static_pins.json
+++ b/net/http/transport_security_state_static_pins.json
@@ -31,6 +31,8 @@
 // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets'
 // refer to, and the timestamp at which the pins list was last updated.
 //
+// Last updated: 2023-04-25 12:56 UTC
+//
 {
   "pinsets": [
     {
@@ -73,97 +75,6 @@
       ]
     },
     {
-      "name": "twitterCom",
-      "static_spki_hashes": [
-        "VeriSignClass1",
-        "VeriSignClass3_G4",
-        "VeriSignClass4_G3",
-        "VeriSignClass3_G3",
-        "VeriSignClass1_G3",
-        "VeriSignClass2_G3",
-        "VeriSignClass3_G2",
-        "VeriSignClass2_G2",
-        "VeriSignClass3_G5",
-        "VeriSignUniversal",
-        "GeoTrustGlobal",
-        "GeoTrustGlobal2",
-        "GeoTrustUniversal",
-        "GeoTrustUniversal2",
-        "GeoTrustPrimary",
-        "GeoTrustPrimary_G2",
-        "GeoTrustPrimary_G3",
-        "DigiCertGlobalRoot",
-        "DigiCertEVRoot",
-        "DigiCertAssuredIDRoot",
-        "Twitter1"
-      ],
-      "report_uri": "http://l.twimg.com/i/hpkp_report"
-    },
-    {
-      "name": "twitterCDN",
-      "static_spki_hashes": [
-        "VeriSignClass1",
-        "VeriSignClass3_G4",
-        "VeriSignClass4_G3",
-        "VeriSignClass3_G3",
-        "VeriSignClass1_G3",
-        "VeriSignClass2_G3",
-        "VeriSignClass3_G2",
-        "VeriSignClass2_G2",
-        "VeriSignClass3_G5",
-        "VeriSignUniversal",
-        "GeoTrustGlobal",
-        "GeoTrustGlobal2",
-        "GeoTrustUniversal",
-        "GeoTrustUniversal2",
-        "GeoTrustPrimary",
-        "GeoTrustPrimary_G2",
-        "GeoTrustPrimary_G3",
-        "DigiCertGlobalRoot",
-        "DigiCertEVRoot",
-        "DigiCertAssuredIDRoot",
-        "Twitter1",
-        "Entrust_2048",
-        "Entrust_EV",
-        "Entrust_G2",
-        "Entrust_SSL",
-        "AAACertificateServices",
-        "AddTrustClass1CARoot",
-        "AddTrustExternalCARoot",
-        "AddTrustPublicCARoot",
-        "AddTrustQualifiedCARoot",
-        "COMODOCertificationAuthority",
-        "SecureCertificateServices",
-        "TrustedCertificateServices",
-        "UTNDATACorpSGC",
-        "UTNUSERFirstClientAuthenticationandEmail",
-        "UTNUSERFirstHardware",
-        "UTNUSERFirstObject",
-        "GTECyberTrustGlobalRoot",
-        "BaltimoreCyberTrustRoot",
-        "GlobalSignRootCA",
-        "GlobalSignRootCA_R2",
-        "GlobalSignRootCA_R3"
-      ],
-      "report_uri": "http://l.twimg.com/i/hpkp_report"
-    },
-    {
-      "name": "dropbox",
-      "static_spki_hashes": [
-        "DigiCertAssuredIDRoot",
-        "DigiCertGlobalRoot",
-        "DigiCertEVRoot",
-        "EntrustRootEC1",
-        "Entrust_G2",
-        "Entrust_EV",
-        "Entrust_2048",
-        "TheGoDaddyGroupClass2",
-        "GoDaddyRoot_G2",
-        "GoDaddySecure"
-      ],
-      "report_uri": "https://log.getdropbox.com/hpkp"
-    },
-    {
       "name": "facebook",
       "static_spki_hashes": [
         "SymantecClass3EVG3",
@@ -2478,51 +2389,6 @@
       "pins": "facebook"
     },
     {
-      "name": "twitter.com",
-      "include_subdomains": false,
-      "pins": "twitterCom"
-    },
-    {
-      "name": "www.twitter.com",
-      "include_subdomains": true,
-      "pins": "twitterCom"
-    },
-    {
-      "name": "api.twitter.com",
-      "include_subdomains": true,
-      "pins": "twitterCDN"
-    },
-    {
-      "name": "oauth.twitter.com",
-      "include_subdomains": true,
-      "pins": "twitterCom"
-    },
-    {
-      "name": "mobile.twitter.com",
-      "include_subdomains": true,
-      "pins": "twitterCom"
-    },
-    {
-      "name": "dev.twitter.com",
-      "include_subdomains": true,
-      "pins": "twitterCom"
-    },
-    {
-      "name": "business.twitter.com",
-      "include_subdomains": true,
-      "pins": "twitterCom"
-    },
-    {
-      "name": "platform.twitter.com",
-      "include_subdomains": true,
-      "pins": "twitterCDN"
-    },
-    {
-      "name": "twimg.com",
-      "include_subdomains": true,
-      "pins": "twitterCDN"
-    },
-    {
       "name": "torproject.org",
       "include_subdomains": false,
       "pins": "tor"
@@ -2548,26 +2414,6 @@
       "pins": "tor"
     },
     {
-      "name": "dropbox.com",
-      "include_subdomains": true,
-      "pins": "dropbox"
-    },
-    {
-      "name": "www.dropbox.com",
-      "include_subdomains": true,
-      "pins": "dropbox"
-    },
-    {
-      "name": "dropboxstatic.com",
-      "include_subdomains": true,
-      "pins": "dropbox"
-    },
-    {
-      "name": "dropboxusercontent.com",
-      "include_subdomains": true,
-      "pins": "dropbox"
-    },
-    {
       "name": "spideroak.com",
       "include_subdomains": true,
       "pins": "spideroak"
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc
index a8f1ca5..925910fc 100644
--- a/net/http/transport_security_state_unittest.cc
+++ b/net/http/transport_security_state_unittest.cc
@@ -1888,8 +1888,6 @@
   EXPECT_TRUE(state.GetStaticPKPState("blog.torproject.org", &pkp_state));
   EXPECT_FALSE(pkp_state.spki_hashes.empty());
 
-  EXPECT_TRUE(HasStaticPublicKeyPins("www.twitter.com"));
-
   // Facebook has pinning and hsts on facebook.com, but only pinning on
   // subdomains.
   EXPECT_TRUE(state.GetStaticPKPState("facebook.com", &pkp_state));
@@ -1956,17 +1954,6 @@
   EXPECT_TRUE(HasStaticPublicKeyPins("www.gstatic.com"));
   EXPECT_TRUE(HasStaticPublicKeyPins("ssl.google-analytics.com"));
   EXPECT_TRUE(HasStaticPublicKeyPins("www.googleplex.com"));
-
-  EXPECT_TRUE(HasStaticPublicKeyPins("twitter.com"));
-  EXPECT_FALSE(HasStaticPublicKeyPins("foo.twitter.com"));
-  EXPECT_TRUE(HasStaticPublicKeyPins("www.twitter.com"));
-  EXPECT_TRUE(HasStaticPublicKeyPins("api.twitter.com"));
-  EXPECT_TRUE(HasStaticPublicKeyPins("oauth.twitter.com"));
-  EXPECT_TRUE(HasStaticPublicKeyPins("mobile.twitter.com"));
-  EXPECT_TRUE(HasStaticPublicKeyPins("dev.twitter.com"));
-  EXPECT_TRUE(HasStaticPublicKeyPins("business.twitter.com"));
-  EXPECT_TRUE(HasStaticPublicKeyPins("platform.twitter.com"));
-  EXPECT_TRUE(HasStaticPublicKeyPins("si0.twimg.com"));
 }
 
 TEST_F(TransportSecurityStateStaticTest, OptionalHSTSCertPins) {
diff --git a/printing/buildflags/buildflags.gni b/printing/buildflags/buildflags.gni
index 8a688b2..e617f46 100644
--- a/printing/buildflags/buildflags.gni
+++ b/printing/buildflags/buildflags.gni
@@ -32,8 +32,8 @@
     # For fuzzing, just restrict to chromeos and linux.
     use_cups = true
   } else {
-    use_cups = (is_chromeos_device || (is_linux && !is_castos) ||
-                is_chromeos_lacros || is_mac) && !is_fuchsia
+    use_cups = (is_chromeos_device || (is_linux && !is_castos) || is_mac) &&
+               !is_fuchsia
   }
 
   # Enables out-of-process printing. While this definition matches
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc
index 49f2265..163c3a3 100644
--- a/remoting/host/client_session.cc
+++ b/remoting/host/client_session.cc
@@ -181,6 +181,14 @@
     }
   }
 
+  if (video_control.has_target_framerate()) {
+    target_framerate_ = video_control.target_framerate();
+    LOG(INFO) << "Received target framerate: " << target_framerate_;
+    for (const auto& [_, video_stream] : video_streams_) {
+      video_stream->SetTargetFramerate(target_framerate_);
+    }
+  }
+
   if (video_control.has_framerate_boost()) {
     auto framerate_boost = video_control.framerate_boost();
     DCHECK(framerate_boost.has_enabled());
@@ -573,6 +581,9 @@
   // Pause capturing if necessary.
   video_stream->Pause(pause_video_);
 
+  // Set the current target framerate.
+  video_stream->SetTargetFramerate(target_framerate_);
+
   if (event_timestamp_source_for_tests_) {
     video_stream->SetEventTimestampsSource(event_timestamp_source_for_tests_);
   }
@@ -610,6 +621,9 @@
     // Pause capturing if necessary.
     video_stream->Pause(pause_video_);
 
+    // Set the current target framerate.
+    video_stream->SetTargetFramerate(target_framerate_);
+
     if (event_timestamp_source_for_tests_) {
       video_stream->SetEventTimestampsSource(event_timestamp_source_for_tests_);
     }
diff --git a/remoting/host/client_session.h b/remoting/host/client_session.h
index 92092ad4..45e88f9 100644
--- a/remoting/host/client_session.h
+++ b/remoting/host/client_session.h
@@ -386,9 +386,12 @@
   // Set to true after all data channels have been connected.
   bool channels_connected_ = false;
 
-  // Used to store video channel pause parameter.
+  // Used to store the video channel pause parameter.
   bool pause_video_ = false;
 
+  // Used to store the target framerate control parameter.
+  int target_framerate_ = kTargetFrameRate;
+
   // VideoLayout is sent only after the control channel is connected. Until
   // then it's stored in |pending_video_layout_message_|.
   std::unique_ptr<protocol::VideoLayout> pending_video_layout_message_;
diff --git a/remoting/proto/control.proto b/remoting/proto/control.proto
index 8d937c4..eeb5249f0 100644
--- a/remoting/proto/control.proto
+++ b/remoting/proto/control.proto
@@ -60,6 +60,12 @@
   }
   optional FramerateBoost framerate_boost = 4;
 
+  // Sets the target framerate for the host. Note that the actual framerate is
+  // variable so this value will update the rate at which frames are captured
+  // but the framerate will be lower if there aren't enough changes on the
+  // screen or the host is not capable of generating frames quickly enough.
+  optional uint32 target_framerate = 5;
+
   // Lossless encode and color settings are no longer set via this message.
   reserved 2, 3;
   reserved "lossless_encode", "lossless_color";
diff --git a/remoting/protocol/fake_connection_to_client.cc b/remoting/protocol/fake_connection_to_client.cc
index 31c6da9e..636e8273 100644
--- a/remoting/protocol/fake_connection_to_client.cc
+++ b/remoting/protocol/fake_connection_to_client.cc
@@ -39,6 +39,8 @@
 void FakeVideoStream::SetMouseCursorPosition(
     const webrtc::DesktopVector& position) {}
 
+void FakeVideoStream::SetTargetFramerate(int framerate) {}
+
 webrtc::ScreenId FakeVideoStream::selected_source() const {
   return selected_source_;
 }
diff --git a/remoting/protocol/fake_connection_to_client.h b/remoting/protocol/fake_connection_to_client.h
index f903b91..e0b5b91 100644
--- a/remoting/protocol/fake_connection_to_client.h
+++ b/remoting/protocol/fake_connection_to_client.h
@@ -39,6 +39,7 @@
   void SetMouseCursor(
       std::unique_ptr<webrtc::MouseCursor> mouse_cursor) override;
   void SetMouseCursorPosition(const webrtc::DesktopVector& position) override;
+  void SetTargetFramerate(int framerate) override;
 
   webrtc::ScreenId selected_source() const;
 
diff --git a/remoting/protocol/video_channel_state_observer.h b/remoting/protocol/video_channel_state_observer.h
index 21b17c4..9272df17 100644
--- a/remoting/protocol/video_channel_state_observer.h
+++ b/remoting/protocol/video_channel_state_observer.h
@@ -12,8 +12,6 @@
 
 class VideoChannelStateObserver {
  public:
-  virtual void OnTargetFramerateChanged(int framerate) = 0;
-
   // Called after the encoded frame is sent via the WebRTC registered callback.
   // The result contains the frame ID assigned by WebRTC if successfully sent.
   // This is only called if the encoder successfully returned a non-null
diff --git a/remoting/protocol/video_frame_pump.cc b/remoting/protocol/video_frame_pump.cc
index 8537990..2b01cfb 100644
--- a/remoting/protocol/video_frame_pump.cc
+++ b/remoting/protocol/video_frame_pump.cc
@@ -102,6 +102,8 @@
   capturer_->SetMouseCursorPosition(position);
 }
 
+void VideoFramePump::SetTargetFramerate(int framerate) {}
+
 void VideoFramePump::OnCaptureResult(
     webrtc::DesktopCapturer::Result result,
     std::unique_ptr<webrtc::DesktopFrame> frame) {
diff --git a/remoting/protocol/video_frame_pump.h b/remoting/protocol/video_frame_pump.h
index 56c4bfc..fd31baa 100644
--- a/remoting/protocol/video_frame_pump.h
+++ b/remoting/protocol/video_frame_pump.h
@@ -91,6 +91,7 @@
   void SetMouseCursor(
       std::unique_ptr<webrtc::MouseCursor> mouse_cursor) override;
   void SetMouseCursorPosition(const webrtc::DesktopVector& position) override;
+  void SetTargetFramerate(int framerate) override;
 
   protocol::VideoFeedbackStub* video_feedback_stub() {
     return &capture_scheduler_;
diff --git a/remoting/protocol/video_stream.h b/remoting/protocol/video_stream.h
index abe14a4..18562d2 100644
--- a/remoting/protocol/video_stream.h
+++ b/remoting/protocol/video_stream.h
@@ -51,6 +51,12 @@
   // Selects the current desktop display (if multiple displays).
   virtual void SelectSource(webrtc::ScreenId id) = 0;
 
+  // Sets the target/max video framerate for the host. The actual framerate is
+  // variable and determined by the number of changes on the screen and the rate
+  // at which the host is able to generate frames. Also WebRTC will adjust this
+  // value based on network conditions.
+  virtual void SetTargetFramerate(int framerate) = 0;
+
   // Allows the owner of the stream to request a different |capture_interval|
   // (usually a higher frequency) for the specified |boost_duration|. After
   // |boost_duration| has elapsed, the capture rate will return to normal.
diff --git a/remoting/protocol/video_stream_event_router.cc b/remoting/protocol/video_stream_event_router.cc
index 3ce2ea02..7eac5316 100644
--- a/remoting/protocol/video_stream_event_router.cc
+++ b/remoting/protocol/video_stream_event_router.cc
@@ -16,19 +16,6 @@
 VideoStreamEventRouter::VideoStreamEventRouter() = default;
 VideoStreamEventRouter::~VideoStreamEventRouter() = default;
 
-void VideoStreamEventRouter::OnTargetFramerateChanged(
-    webrtc::ScreenId screen_id,
-    int framerate) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-  auto observer = GetObserver(screen_id);
-  if (observer) {
-    observer->OnTargetFramerateChanged(framerate);
-  } else {
-    LOG(WARNING) << "No registered VideoChannelStateObserver for " << screen_id;
-  }
-}
-
 void VideoStreamEventRouter::OnEncodedFrameSent(
     webrtc::ScreenId screen_id,
     webrtc::EncodedImageCallback::Result result,
@@ -94,4 +81,4 @@
   return nullptr;
 }
 
-}  // namespace remoting::protocol
\ No newline at end of file
+}  // namespace remoting::protocol
diff --git a/remoting/protocol/video_stream_event_router.h b/remoting/protocol/video_stream_event_router.h
index 3735a8c..76925ac 100644
--- a/remoting/protocol/video_stream_event_router.h
+++ b/remoting/protocol/video_stream_event_router.h
@@ -24,7 +24,6 @@
 
   // Mirrors the VideoChannelStateObserver interface with an additional
   // |screen_id| param used to route the value to the appropriate video stream.
-  void OnTargetFramerateChanged(webrtc::ScreenId screen_id, int framerate);
   void OnEncodedFrameSent(webrtc::ScreenId screen_id,
                           webrtc::EncodedImageCallback::Result result,
                           const WebrtcVideoEncoder::EncodedFrame& frame);
@@ -52,4 +51,4 @@
 
 }  // namespace remoting::protocol
 
-#endif  // REMOTING_PROTOCOL_VIDEO_STREAM_EVENT_ROUTER_H_
\ No newline at end of file
+#endif  // REMOTING_PROTOCOL_VIDEO_STREAM_EVENT_ROUTER_H_
diff --git a/remoting/protocol/webrtc_video_encoder_wrapper.cc b/remoting/protocol/webrtc_video_encoder_wrapper.cc
index 040d457..9dfc3db5 100644
--- a/remoting/protocol/webrtc_video_encoder_wrapper.cc
+++ b/remoting/protocol/webrtc_video_encoder_wrapper.cc
@@ -74,8 +74,9 @@
 // processing and rendering lots of identical frames.
 constexpr base::TimeDelta kKeepAliveInterval = base::Seconds(2);
 
-// SDP format parameter name used to set the maximum framerate for an encoder.
-constexpr char kMaxFramerateKey[] = "max-fr";
+// Used to clamp the calculated frame durations to a set of reasonable values.
+constexpr auto kMinFrameDuration = base::Hertz(120);
+constexpr auto kMaxFrameDuration = base::Hertz(15);
 
 std::string EncodeResultToString(WebrtcVideoEncoder::EncodeResult result) {
   using EncodeResult = WebrtcVideoEncoder::EncodeResult;
@@ -92,25 +93,6 @@
   return "";
 }
 
-int GetFrameRateFromSdpFormatParam(const std::string& param_value) {
-  int conversion_result;
-  if (!base::StringToInt(param_value, &conversion_result)) {
-    LOG(ERROR) << "Failed to convert max-fr value to an int: " << param_value;
-    return kTargetFrameRate;
-  }
-
-  // Clamp the range to prevent a bad experience in case of a client bug.
-  // 1000 is the maximum allowable frame rate as capturing at a higher rate will
-  // cause problems in several components which expect at least 1 millisecond
-  // between frames. In reality, very few applications update their window
-  // faster than the current monitor refresh rate which is likely 60Hz - 144Hz
-  // so value > ~150 won't provide much value.
-  // A lower bound of 1 millisecond is needed because the framerate is used as
-  // the denominator when determining the period between frames so 0 will lead
-  // to divide by 0 bugs.
-  return std::clamp<int>(conversion_result, 1, 1000);
-}
-
 }  // namespace
 
 WebrtcVideoEncoderWrapper::WebrtcVideoEncoderWrapper(
@@ -173,12 +155,6 @@
     default:
       LOG(FATAL) << "Unknown codec type: " << codec_type_;
   }
-
-  auto iter = format.parameters.find(kMaxFramerateKey);
-  if (iter != format.parameters.end()) {
-    target_frame_rate_ = GetFrameRateFromSdpFormatParam(iter->second);
-  }
-  target_frame_interval_ = base::Hertz(target_frame_rate_);
 }
 
 WebrtcVideoEncoderWrapper::~WebrtcVideoEncoderWrapper() {
@@ -235,7 +211,18 @@
     const std::vector<webrtc::VideoFrameType>* frame_types) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  auto now = base::TimeTicks::Now();
+  // Include all of the pre-processing steps in the total encode time.
+  auto encode_start = base::TimeTicks::Now();
+
+  // Calculate the frame interval before dropping or queueing frames.
+  auto frame_timestamp =
+      base::Time::NowFromSystemTime().ToDeltaSinceWindowsEpoch();
+  if (!last_frame_received_timestamp_.is_zero()) {
+    current_frame_interval_ =
+        std::clamp(frame_timestamp - last_frame_received_timestamp_,
+                   kMinFrameDuration, kMaxFrameDuration);
+  }
+  last_frame_received_timestamp_ = frame_timestamp;
 
   // Simulcast is unsupported, so only the first vector element is needed.
   bool key_frame_requested =
@@ -296,20 +283,13 @@
   }
 
   if (!screen_id_.has_value()) {
+    // Save the screen_id from the first encoded frame, otherwise we won't know
+    // which screen_id this encoder is associated with due to the current WebRTC
+    // architecture.
     screen_id_ = frame_stats_->screen_id;
-
-    // Now that we know which screen id this encoder is associated with, we can
-    // let that video stream know if a non-default framerate has been requested.
-    if (target_frame_rate_ != kTargetFrameRate) {
-      main_task_runner_->PostTask(
-          FROM_HERE,
-          base::BindOnce(&VideoStreamEventRouter::OnTargetFramerateChanged,
-                         video_stream_event_router_, *screen_id_,
-                         target_frame_rate_));
-    }
   }
 
-  frame_stats_->encode_started_time = now;
+  frame_stats_->encode_started_time = encode_start;
 
   auto desktop_frame = video_frame_adapter->TakeDesktopFrame();
 
@@ -352,7 +332,7 @@
   // This is done to save on network bandwidth and CPU usage.
   if (desktop_frame->updated_region().is_empty() && !top_off_active_ &&
       !pending_key_frame_request_ &&
-      (now - latest_frame_encode_start_time_ < kKeepAliveInterval)) {
+      (encode_start - latest_frame_encode_start_time_ < kKeepAliveInterval)) {
     // Drop the frame. There is no need to track the update-rect as the
     // frame being dropped is empty.
     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
@@ -361,18 +341,15 @@
                        weak_factory_.GetWeakPtr()));
     return WEBRTC_VIDEO_CODEC_OK;
   }
-  latest_frame_encode_start_time_ = now;
+  latest_frame_encode_start_time_ = encode_start;
 
   WebrtcVideoEncoder::FrameParams frame_params;
 
   // SetRates() must be called prior to Encode(), with a non-zero bitrate.
   DCHECK_NE(0, bitrate_kbps_);
   frame_params.bitrate_kbps = bitrate_kbps_;
-  frame_params.duration = target_frame_interval_;
-
-  // TODO(crbug.com/1192865): Copy the FPS estimator from the scheduler,
-  // instead of hard-coding this value here.
-  frame_params.fps = target_frame_rate_;
+  frame_params.duration = current_frame_interval_;
+  frame_params.fps = current_frame_interval_.ToHz();
 
   frame_params.vpx_min_quantizer =
       ShouldDropQualityForLargeFrame(*desktop_frame) ? kMaxQuantizer
@@ -579,7 +556,7 @@
         updated_area * kEstimatedBytesPerMegapixel / kPixelsPerMegapixel;
     base::TimeDelta expected_send_delay =
         base::Seconds(expected_frame_size * 8 / (bitrate_kbps_ * 1000.0));
-    if (expected_send_delay > target_frame_interval_) {
+    if (expected_send_delay > current_frame_interval_) {
       should_drop_quality = true;
     }
   }
diff --git a/remoting/protocol/webrtc_video_encoder_wrapper.h b/remoting/protocol/webrtc_video_encoder_wrapper.h
index 4144970..211f43bb 100644
--- a/remoting/protocol/webrtc_video_encoder_wrapper.h
+++ b/remoting/protocol/webrtc_video_encoder_wrapper.h
@@ -164,10 +164,11 @@
   // TaskRunner used for scheduling encoding tasks.
   scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner_;
 
-  // Stores the target frame rate used for capture and encode scheduling. May be
-  // changed by the client using SDP format parameters for the selected codec.
-  int target_frame_rate_ = kTargetFrameRate;
-  base::TimeDelta target_frame_interval_;
+  // Stores the current frame interval, updated for each frame received.
+  base::TimeDelta current_frame_interval_ = base::Hertz(kTargetFrameRate);
+
+  // Stores the timestamp of the last frame that was sent for encoding.
+  base::TimeDelta last_frame_received_timestamp_;
 
   // Represents the screen which is being encoded by this instance. Initialized
   // after the first captured frame has been received.
diff --git a/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc b/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc
index 390078fa..7609e89e 100644
--- a/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc
+++ b/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc
@@ -46,6 +46,9 @@
 constexpr int kBitrateBps = 8000000;
 constexpr int kTestScreenId = 16;
 
+// Used for a +/- 5ms fudge factor when checking frame durations.
+constexpr int kDurationMsFudgeFactor = 5;
+
 const VideoEncoder::Capabilities kVideoEncoderCapabilities(
     /*loss_notification*/ false);
 const VideoEncoder::Settings kVideoEncoderSettings(kVideoEncoderCapabilities,
@@ -119,7 +122,6 @@
   MockVideoChannelStateObserver() = default;
   ~MockVideoChannelStateObserver() override = default;
 
-  MOCK_METHOD(void, OnTargetFramerateChanged, (int framerate), (override));
   MOCK_METHOD(void,
               OnEncodedFrameSent,
               (EncodedImageCallback::Result result,
@@ -155,7 +157,7 @@
   MOCK_METHOD(void,
               Encode,
               (std::unique_ptr<webrtc::DesktopFrame> frame,
-               const FrameParams& param,
+               const FrameParams& frame_params,
                EncodeCallback done),
               (override));
 };
@@ -168,17 +170,25 @@
     // Configure the mock encoder's default behavior to mimic a real encoder.
     mock_video_encoder_ = std::make_unique<NiceMock<MockVideoEncoder>>();
     ON_CALL(*mock_video_encoder_, Encode)
-        .WillByDefault([](std::unique_ptr<webrtc::DesktopFrame> frame,
-                          const WebrtcVideoEncoder::FrameParams& param,
-                          WebrtcVideoEncoder::EncodeCallback done) {
+        .WillByDefault([&](std::unique_ptr<webrtc::DesktopFrame> frame,
+                           const WebrtcVideoEncoder::FrameParams& frame_params,
+                           WebrtcVideoEncoder::EncodeCallback done) {
           auto encoded_frame =
               std::make_unique<WebrtcVideoEncoder::EncodedFrame>();
           encoded_frame->dimensions = frame->size();
           encoded_frame->data = webrtc::EncodedImageBuffer::Create(
               frame->size().width() * frame->size().height());
-          encoded_frame->key_frame = param.key_frame;
-          encoded_frame->quantizer = param.vpx_min_quantizer;
+          encoded_frame->key_frame = frame_params.key_frame;
+          encoded_frame->quantizer = frame_params.vpx_min_quantizer;
           encoded_frame->codec = kVideoCodecVP9;
+
+          auto expected_framerate = get_expected_framerate();
+          if (expected_framerate.has_value()) {
+            EXPECT_EQ(frame_params.fps, *expected_framerate);
+            EXPECT_NEAR(frame_params.duration.InMilliseconds(),
+                        base::Hertz(*expected_framerate).InMilliseconds(),
+                        kDurationMsFudgeFactor);
+          }
           std::move(done).Run(WebrtcVideoEncoder::EncodeResult::SUCCEEDED,
                               std::move(encoded_frame));
         });
@@ -206,11 +216,21 @@
   }
 
  protected:
+  void set_expected_framerate(int framerate) {
+    expected_framerate_ = framerate;
+  }
+
+  const absl::optional<int>& get_expected_framerate() const {
+    return expected_framerate_;
+  }
+
   base::test::SingleThreadTaskEnvironment task_environment_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
 
   base::RunLoop run_loop_;
 
+  absl::optional<int> expected_framerate_;
+
   VideoStreamEventRouter video_stream_event_router_;
   NiceMock<MockVideoChannelStateObserver> observer_;
   MockEncodedImageCallback callback_;
@@ -241,77 +261,6 @@
   PostQuitAndRun();
 }
 
-TEST_F(WebrtcVideoEncoderWrapperTest, NotifiesOnFramerateChanged) {
-  EXPECT_CALL(observer_, OnTargetFramerateChanged(42));
-  EXPECT_CALL(callback_, OnEncodedImage(_, Field(&CodecSpecificInfo::codecType,
-                                                 kVideoCodecVP9)))
-      .WillOnce(Return(kResultOk));
-
-  auto sdp_format = GetVp9Format();
-  sdp_format.parameters.emplace("max-fr", "42");
-  auto encoder = InitEncoder(std::move(sdp_format), GetVp9Codec());
-  std::vector<VideoFrameType> frame_types{VideoFrameType::kVideoFrameKey};
-  encoder->Encode(MakeVideoFrame(), &frame_types);
-
-  PostQuitAndRun();
-}
-
-TEST_F(WebrtcVideoEncoderWrapperTest,
-       NotifiesOnFramerateChangedInMultiStreamMode) {
-  EXPECT_CALL(observer_, OnTargetFramerateChanged(42));
-  EXPECT_CALL(callback_, OnEncodedImage(_, Field(&CodecSpecificInfo::codecType,
-                                                 kVideoCodecVP9)))
-      .WillOnce(Return(kResultOk));
-
-  // Register a multi-stream observer for |kTestScreenId|.
-  video_stream_event_router_.SetVideoChannelStateObserver(
-      "screen_stream_16", observer_.GetWeakPtr());
-
-  // Also set up a strict mock observer for another screen id to ensure the
-  // proper observer is called.
-  StrictMock<MockVideoChannelStateObserver> observer;
-  video_stream_event_router_.SetVideoChannelStateObserver(
-      "screen_stream_17", observer.GetWeakPtr());
-
-  auto sdp_format = GetVp9Format();
-  sdp_format.parameters.emplace("max-fr", "42");
-  auto encoder = InitEncoder(std::move(sdp_format), GetVp9Codec());
-  std::vector<VideoFrameType> frame_types{VideoFrameType::kVideoFrameKey};
-  encoder->Encode(MakeVideoFrame(), &frame_types);
-
-  PostQuitAndRun();
-}
-
-TEST_F(WebrtcVideoEncoderWrapperTest, FramerateClampedToLowerBound) {
-  EXPECT_CALL(observer_, OnTargetFramerateChanged(1));
-  EXPECT_CALL(callback_, OnEncodedImage(_, Field(&CodecSpecificInfo::codecType,
-                                                 kVideoCodecVP9)))
-      .WillOnce(Return(kResultOk));
-
-  auto sdp_format = GetVp9Format();
-  sdp_format.parameters.emplace("max-fr", "0");
-  auto encoder = InitEncoder(std::move(sdp_format), GetVp9Codec());
-  std::vector<VideoFrameType> frame_types{VideoFrameType::kVideoFrameKey};
-  encoder->Encode(MakeVideoFrame(), &frame_types);
-
-  PostQuitAndRun();
-}
-
-TEST_F(WebrtcVideoEncoderWrapperTest, FramerateClampedToUpperBound) {
-  EXPECT_CALL(observer_, OnTargetFramerateChanged(1000));
-  EXPECT_CALL(callback_, OnEncodedImage(_, Field(&CodecSpecificInfo::codecType,
-                                                 kVideoCodecVP9)))
-      .WillOnce(Return(kResultOk));
-
-  auto sdp_format = GetVp9Format();
-  sdp_format.parameters.emplace("max-fr", "1001");
-  auto encoder = InitEncoder(std::move(sdp_format), GetVp9Codec());
-  std::vector<VideoFrameType> frame_types{VideoFrameType::kVideoFrameKey};
-  encoder->Encode(MakeVideoFrame(), &frame_types);
-
-  PostQuitAndRun();
-}
-
 TEST_F(WebrtcVideoEncoderWrapperTest, NotifiesFrameEncodedAndReturned) {
   EXPECT_CALL(callback_, OnEncodedImage(_, Field(&CodecSpecificInfo::codecType,
                                                  kVideoCodecVP9)))
@@ -539,4 +488,24 @@
   PostQuitAndRun();
 }
 
+TEST_F(WebrtcVideoEncoderWrapperTest, FrameDurationAndFpsCalculated) {
+  EXPECT_CALL(callback_, OnEncodedImage(_, _))
+      .Times(3)
+      .WillRepeatedly(Return(kResultOk));
+
+  set_expected_framerate(kTargetFrameRate);
+
+  auto encoder = InitEncoder(GetVp9Format(), GetVp9Codec());
+  encoder->SetEncoderForTest(std::move(mock_video_encoder_));
+
+  std::vector<VideoFrameType> frame_types{VideoFrameType::kVideoFrameKey};
+  encoder->Encode(MakeVideoFrame(), &frame_types);
+  task_environment_.FastForwardBy(base::Hertz(kTargetFrameRate));
+  encoder->Encode(MakeVideoFrame(), &frame_types);
+  task_environment_.FastForwardBy(base::Hertz(kTargetFrameRate));
+  encoder->Encode(MakeVideoFrame(), &frame_types);
+
+  PostQuitAndRun();
+}
+
 }  // namespace remoting::protocol
diff --git a/remoting/protocol/webrtc_video_stream.cc b/remoting/protocol/webrtc_video_stream.cc
index e84ad7c..5a7c68d 100644
--- a/remoting/protocol/webrtc_video_stream.cc
+++ b/remoting/protocol/webrtc_video_stream.cc
@@ -408,10 +408,11 @@
                                 boost_duration));
 }
 
-void WebrtcVideoStream::OnTargetFramerateChanged(int framerate) {
+void WebrtcVideoStream::SetTargetFramerate(int framerate) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK_GT(framerate, 0);
   DCHECK_LE(framerate, 1000);
+  target_framerate_ = framerate;
 
   if (!transceiver_) {
     LOG(WARNING) << "No transceiver, can't set updated framerate.";
@@ -504,15 +505,35 @@
 void WebrtcVideoStream::OnSinkAddedOrUpdated(const rtc::VideoSinkWants& wants) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
-  VLOG(0) << "WebRTC requested max framerate: " << wants.max_framerate_fps
-          << " FPS";
+  auto framerate = wants.max_framerate_fps;
+  VLOG(0) << "WebRTC requested max framerate: " << framerate << " FPS";
+
+  // OnSinkAddedOrUpdated() is called when:
+  //   - A new stream is added
+  //   - An SDP renegotiation is requested
+  //   - A new max framerate is requested
+  //   - WebRTC artificially lowers the framerate due to network conditions
+  //
+  // We need to update the max_framerate for the stream in some of the scenarios
+  // but not for the others. In order to determine whether to update the
+  // RTPSender, we check the current max_framerate rather than the framerate in
+  // |wants|.
+  auto sender = transceiver_->sender();
+  if (sender) {
+    for (auto& encoding : sender->GetParameters().encodings) {
+      if (encoding.max_framerate != target_framerate_) {
+        VLOG(0) << "Setting target framerate for new sink: "
+                << target_framerate_;
+        SetTargetFramerate(target_framerate_);
+      }
+    }
+  }
 
   // Unretained is sound as |core_| is owned by |this| and destroyed on
   // |core_task_runner_|.
   core_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&WebrtcVideoStream::Core::SetMaxFramerateFps,
-                     base::Unretained(core_.get()), wants.max_framerate_fps));
+      FROM_HERE, base::BindOnce(&WebrtcVideoStream::Core::SetMaxFramerateFps,
+                                base::Unretained(core_.get()), framerate));
 }
 
 void WebrtcVideoStream::OnVideoSizeChanged(webrtc::DesktopSize frame_size,
diff --git a/remoting/protocol/webrtc_video_stream.h b/remoting/protocol/webrtc_video_stream.h
index f363dd8..1e69f98 100644
--- a/remoting/protocol/webrtc_video_stream.h
+++ b/remoting/protocol/webrtc_video_stream.h
@@ -14,6 +14,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
+#include "remoting/base/constants.h"
 #include "remoting/base/session_options.h"
 #include "remoting/protocol/desktop_capturer.h"
 #include "remoting/protocol/video_channel_state_observer.h"
@@ -67,11 +68,11 @@
   void SetMouseCursor(
       std::unique_ptr<webrtc::MouseCursor> mouse_cursor) override;
   void SetMouseCursorPosition(const webrtc::DesktopVector& position) override;
+  void SetTargetFramerate(int framerate) override;
   void BoostFramerate(base::TimeDelta capture_interval,
                       base::TimeDelta boost_duration) override;
 
   // VideoChannelStateObserver interface.
-  void OnTargetFramerateChanged(int framerate) override;
   void OnEncodedFrameSent(
       webrtc::EncodedImageCallback::Result result,
       const WebrtcVideoEncoder::EncodedFrame& frame) override;
@@ -93,6 +94,10 @@
   // Label of the associated WebRTC video-stream.
   std::string stream_name_;
 
+  // Store the target framerate so we can set it on the RTP Sender when the SDP
+  // is renegotiated (such as when the codec or codec profile is changed).
+  int target_framerate_ = kTargetFrameRate;
+
   // Used to send captured frames to the encoder.
   rtc::scoped_refptr<WebrtcVideoTrackSource> video_track_source_;
 
diff --git a/services/network/public/cpp/trigger_attestation.cc b/services/network/public/cpp/trigger_attestation.cc
index fe81d83..f724207 100644
--- a/services/network/public/cpp/trigger_attestation.cc
+++ b/services/network/public/cpp/trigger_attestation.cc
@@ -8,7 +8,7 @@
 #include <utility>
 
 #include "base/check.h"
-#include "base/guid.h"
+#include "base/uuid.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace network {
@@ -28,7 +28,7 @@
 absl::optional<TriggerAttestation> TriggerAttestation::Create(
     std::string token,
     const std::string& aggregatable_report_id) {
-  base::GUID id = base::GUID::ParseLowercase(aggregatable_report_id);
+  base::Uuid id = base::Uuid::ParseLowercase(aggregatable_report_id);
   if (!id.is_valid() || token.empty()) {
     return absl::nullopt;
   }
@@ -37,7 +37,7 @@
 }
 
 TriggerAttestation::TriggerAttestation(std::string token,
-                                       base::GUID aggregatable_report_id)
+                                       base::Uuid aggregatable_report_id)
     : token_(std::move(token)),
       aggregatable_report_id_(std::move(aggregatable_report_id)) {
   DCHECK(aggregatable_report_id_.is_valid());
diff --git a/services/network/public/cpp/trigger_attestation.h b/services/network/public/cpp/trigger_attestation.h
index f1d543b1..20204834 100644
--- a/services/network/public/cpp/trigger_attestation.h
+++ b/services/network/public/cpp/trigger_attestation.h
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "base/component_export.h"
-#include "base/guid.h"
+#include "base/uuid.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace network {
@@ -35,15 +35,15 @@
   TriggerAttestation& operator=(TriggerAttestation&&);
 
   const std::string& token() const { return token_; }
-  const base::GUID& aggregatable_report_id() const {
+  const base::Uuid& aggregatable_report_id() const {
     return aggregatable_report_id_;
   }
 
  private:
-  TriggerAttestation(std::string token, base::GUID aggregatable_report_id);
+  TriggerAttestation(std::string token, base::Uuid aggregatable_report_id);
 
   std::string token_;
-  base::GUID aggregatable_report_id_;
+  base::Uuid aggregatable_report_id_;
 };
 
 }  // namespace network
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 4d13b30..ea7cfd9 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -463,7 +463,6 @@
     deps += [
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.fonts:fuchsia.fonts_hlcpp",
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.io:fuchsia.io_hlcpp",
-      "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.sys:fuchsia.sys_hlcpp",
       "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
       "//third_party/fuchsia-sdk/sdk/pkg/zx",
       "//third_party/icu:icuuc",
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index b91eea2a..508b6f8 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -28230,7 +28230,8 @@
               "os": "Windows-10-19045"
             }
           ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 4
         },
         "test": "blink_unittests",
         "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/"
@@ -29517,7 +29518,8 @@
               "os": "Windows-10-19045"
             }
           ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 6
         },
         "test": "unit_tests",
         "test_id_prefix": "ninja://chrome/test:unit_tests/"
diff --git a/testing/buildbot/filters/linux-lacros.browser_tests.filter b/testing/buildbot/filters/linux-lacros.browser_tests.filter
index 36d61f1..2082e03 100644
--- a/testing/buildbot/filters/linux-lacros.browser_tests.filter
+++ b/testing/buildbot/filters/linux-lacros.browser_tests.filter
@@ -15,7 +15,6 @@
 -KeepAliveDevToolsTest.KeepsAliveUntilBrowserClose
 -OmniboxPopupViewViewsTest.ClickOmnibox
 -OmniboxPopupViewViewsTest.PopupMatchesLocationBarBackground
--OutOfProcessPPAPITest.Printing
 -ProfileListDesktopBrowserTest.SwitchToProfile
 -SSLUITest.TestCloseTabWithUnsafePopup
 # crbug.com/1121486
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 5b7bf0db..2befea9 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -3953,6 +3953,11 @@
           '--top-chrome-touch-ui=disabled',
         ],
       },
+      'win10-code-coverage': {
+        'swarming': {
+          'shards': 6,
+        },
+      },
     },
   },
   'vaapi_unittest eve': {
@@ -4527,6 +4532,11 @@
           'inverse_quickrun_shards': 12,
         },
       },
+      'win10-code-coverage': {
+        'swarming': {
+          'shards': 4,
+        },
+      },
     },
   },
   'weblayer_browsertests': {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 6124eae7..3a50fa8 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -4042,6 +4042,14 @@
                         "CustomizeChromeColorExtraction",
                         "CustomizeChromeSidePanel"
                     ]
+                },
+                {
+                    "name": "Panorama_In_Product_Help",
+                    "enable_features": [
+                        "CustomizeChromeColorExtraction",
+                        "CustomizeChromeSidePanel",
+                        "IPH_DesktopCustomizeChrome"
+                    ]
                 }
             ]
         }
@@ -6706,22 +6714,6 @@
             ]
         }
     ],
-    "IOSExpKitMaps": [
-        {
-            "platforms": [
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "LongPressSurroundingText",
-                        "MapsExperienceKit"
-                    ]
-                }
-            ]
-        }
-    ],
     "IOSFastApplicationWillTerminate": [
         {
             "platforms": [
@@ -10131,21 +10123,6 @@
             ]
         }
     ],
-    "PolicyLogsPageAndroid": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "PolicyLogsPageAndroid"
-                    ]
-                }
-            ]
-        }
-    ],
     "PolicyLogsPageIOS": [
         {
             "platforms": [
@@ -11221,9 +11198,9 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled_33_0_20230323",
+                    "name": "Enabled_30_0_20230127",
                     "params": {
-                        "reporter_omaha_tag": "33.0"
+                        "reporter_omaha_tag": "30.0"
                     },
                     "enable_features": [
                         "ClientSideDetectionTag"
diff --git a/testing/variations/smoke/conftest.py b/testing/variations/smoke/conftest.py
new file mode 100644
index 0000000..a926a4d3
--- /dev/null
+++ b/testing/variations/smoke/conftest.py
@@ -0,0 +1,96 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import pytest
+
+import logging
+import os
+import test_utils
+import shutil
+
+from contextlib import contextmanager
+from selenium import webdriver
+from selenium.common.exceptions import WebDriverException
+from selenium.webdriver import ChromeOptions
+
+def pytest_addoption(parser: pytest.Parser):
+  # By default, running on the hosted platform.
+  parser.addoption('--target-platform',
+                   default=test_utils.get_hosted_platform(),
+                   dest='target_platform',
+                   choices=['linux', 'win', 'mac', 'android', 'cros',
+                            'lacros'],
+                   help='If present, run for the target platform, '
+                   'defaults to the host platform.')
+
+  parser.addoption('--channel',
+                   default='dev',
+                   choices=['dev', 'canary', 'beta', 'stable', 'extended'],
+                   help='The channel of Chrome to download.')
+
+  parser.addoption('--chromedriver',
+                   help='The path to the existing chromedriver. '
+                   'This will ignore --channel and skip downloading.')
+
+# pylint: disable=redefined-outer-name
+@pytest.fixture(scope="session")
+def chromedriver_path(pytestconfig: pytest.Config) -> str:
+  """Returns a path to the chromedriver."""
+  if cd_path := pytestconfig.getoption('chromedriver'):
+    cd_path = os.path.abspath(cd_path)
+    if not os.path.isfile(cd_path):
+      raise RuntimeError(f'Given chromedriver doesn\'t exist. ({cd_path})')
+    return cd_path
+
+  platform = pytestconfig.getoption('target_platform')
+  channel = pytestconfig.getoption('channel')
+
+  # https://developer.chrome.com/docs/versionhistory/reference/#platform-identifiers
+  downloaded_dir = None
+  if platform == "linux":
+    ver = test_utils.find_version('linux', channel)
+    downloaded_dir = test_utils.download_chrome_linux(version=str(ver))
+  elif platform == "mac":
+    ver = test_utils.find_version('mac_arm64', channel)
+    downloaded_dir = test_utils.download_chrome_mac(version=str(ver))
+  elif platform == "win":
+    ver = test_utils.find_version('win64', channel)
+    downloaded_dir = test_utils.download_chrome_win(version=str(ver))
+  else:
+    raise RuntimeError(f'Given platform ({platform}) is not supported.')
+
+  return os.path.join(downloaded_dir, 'chromedriver')
+
+@pytest.fixture
+def driver_factory(chromedriver_path: str,
+                   tmp_path_factory: pytest.TempPathFactory):
+  """Returns a factory that creates a webdriver."""
+  @contextmanager
+  def factory(chrome_options = None):
+    # Crashpad is a separate process and its dump locations is set via env
+    # variable.
+    crash_dump_dir = tmp_path_factory.mktemp('crash', True)
+    os.environ['BREAKPAD_DUMP_LOCATION'] = str(crash_dump_dir)
+
+    chrome_options = chrome_options or ChromeOptions()
+    chrome_options.add_argument("--headless")
+    chrome_options.add_experimental_option('excludeSwitches',
+                                          ['disable-background-networking'])
+    driver = None
+    try:
+      driver = webdriver.Chrome(chromedriver_path, options=chrome_options)
+      yield driver
+    except WebDriverException as e:
+      # Report this to be part of test result.
+      if os.listdir(crash_dump_dir):
+        logging.error('Chrome crashed and exited abnormally.\n%s', e)
+      else:
+        logging.error('Uncaught WebDriver exception thrown.\n%s', e)
+      raise
+    finally:
+      if driver:
+        driver.quit()
+      shutil.rmtree(crash_dump_dir, ignore_errors=True)
+
+  return factory
diff --git a/third_party/blink/common/interest_group/auction_config_mojom_traits.cc b/third_party/blink/common/interest_group/auction_config_mojom_traits.cc
index ea6a0ae..a297054 100644
--- a/third_party/blink/common/interest_group/auction_config_mojom_traits.cc
+++ b/third_party/blink/common/interest_group/auction_config_mojom_traits.cc
@@ -170,6 +170,7 @@
       !data.ReadAuctionReportBuyers(&out->auction_report_buyers) ||
       !data.ReadRequiredSellerCapabilities(
           &out->required_seller_capabilities) ||
+      !data.ReadRequestedSize(&out->requested_size) ||
       !data.ReadComponentAuctions(&out->component_auctions)) {
     return false;
   }
diff --git a/third_party/blink/public/common/interest_group/auction_config.h b/third_party/blink/public/common/interest_group/auction_config.h
index a456c67..f3082eb5 100644
--- a/third_party/blink/public/common/interest_group/auction_config.h
+++ b/third_party/blink/public/common/interest_group/auction_config.h
@@ -19,6 +19,7 @@
 #include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/blink/public/common/common_export.h"
 #include "third_party/blink/public/common/interest_group/ad_auction_currencies.h"
+#include "third_party/blink/public/common/interest_group/ad_display_size.h"
 #include "third_party/blink/public/common/interest_group/seller_capabilities.h"
 #include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-shared.h"
 #include "url/gurl.h"
@@ -262,6 +263,12 @@
     // all required seller capabilities will not participate in the auction.
     SellerCapabilitiesType required_seller_capabilities;
 
+    // The requested ad creative size for the auction (strictly optional).
+    // If specified by the caller, it is surfaced during the auction through
+    // browser signals and stored after the auction in the winning fenced frame
+    // config as its container size.
+    absl::optional<blink::AdSize> requested_size;
+
     // Nested auctions whose results will also be fed to `seller`. Only the top
     // level auction config can have component auctions.
     std::vector<AuctionConfig> component_auctions;
diff --git a/third_party/blink/public/common/interest_group/auction_config_mojom_traits.h b/third_party/blink/public/common/interest_group/auction_config_mojom_traits.h
index 4ce7bb8..03b542a 100644
--- a/third_party/blink/public/common/interest_group/auction_config_mojom_traits.h
+++ b/third_party/blink/public/common/interest_group/auction_config_mojom_traits.h
@@ -306,6 +306,11 @@
     return params.required_seller_capabilities;
   }
 
+  static const absl::optional<blink::AdSize> requested_size(
+      const blink::AuctionConfig::NonSharedParams& params) {
+    return params.requested_size;
+  }
+
   static const std::vector<blink::AuctionConfig>& component_auctions(
       const blink::AuctionConfig::NonSharedParams& params) {
     return params.component_auctions;
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index c753ca3e..c22fc45 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -9384,6 +9384,11 @@
       string storageKey
       string bucketName
 
+  # Deletes state for sites identified as potential bounce trackers, immediately.
+  experimental command runBounceTrackingMitigations
+    returns
+      array of string deletedSites
+
   # A cache's contents have been modified.
   event cacheStorageContentUpdated
     parameters
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom
index 0181b4b9..3f09115c 100644
--- a/third_party/blink/public/mojom/frame/frame.mojom
+++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -597,20 +597,27 @@
   //
   // A document in a fenced frame can invoke the reportEvent API to request the
   // browser to send `eventData` in a beacon toward the URL registered against
-  // `eventType` by the worklet in registerAdBeacon. Please see enum
-  // `ReportingDestination` for egilible reporting entities.
+  // `eventType` by the worklet in registerAdBeacon. Depending on the declared
+  // `destination`, the beacon is sent to the reporting destination's
+  // registered URL.
+  // Note the `destination` above is a WebIDL sequence, which means it may
+  // contain multiple destinations. It is forwarded as a collection in a single
+  // IPC call, instead of making an IPC call for each destination.
+  // For the list of available reporting destinations, see enum
+  // ReportingDestination defined in:
+  // third_party/blink/public/mojom/fenced_frame/fenced_frame_config.mojom
   SendFencedFrameReportingBeacon(string event_data,
                                  string event_type,
-                                 ReportingDestination destination);
+                                 array<ReportingDestination> destinations);
 
   // Fenced frames can send beacons automatically when an event happens.
   //
   // For now, only "reserved.top_navigation" is supported. The `event_data` is
-  // installed in the RenderFrameHost and will be sent toward `destination` on
+  // installed in the RenderFrameHost and will be sent toward `destinations` on
   // the next cross-document top-frame navigation.
   SetFencedFrameAutomaticBeaconReportEventData(
       string event_data,
-      array<ReportingDestination> destination);
+      array<ReportingDestination> destinations);
 
   // See:
   // https://github.com/WICG/turtledove/blob/main/FLEDGE_extended_PA_reporting.md
diff --git a/third_party/blink/public/mojom/interest_group/interest_group_types.mojom b/third_party/blink/public/mojom/interest_group/interest_group_types.mojom
index 0132932..7a5c34fd 100644
--- a/third_party/blink/public/mojom/interest_group/interest_group_types.mojom
+++ b/third_party/blink/public/mojom/interest_group/interest_group_types.mojom
@@ -372,6 +372,12 @@
   // capabilities will not participate in the auction.
   SellerCapabilities required_seller_capabilities;
 
+  // The requested ad creative size for the auction (strictly optional).
+  // If specified in the auction config, it is surfaced during the auction
+  // through browser signals and stored after the auction in the winning
+  // fenced frame config as its container size.
+  AdSize? requested_size;
+
   // Nested auctions whose results will also be fed to `seller`. Only the top
   // level auction config can have component auctions.
   array<AuctionAdConfig> component_auctions;
diff --git a/third_party/blink/public/mojom/loader/code_cache.mojom b/third_party/blink/public/mojom/loader/code_cache.mojom
index e90f476..1dc462c 100644
--- a/third_party/blink/public/mojom/loader/code_cache.mojom
+++ b/third_party/blink/public/mojom/loader/code_cache.mojom
@@ -32,11 +32,9 @@
   ClearCodeCacheEntry(CodeCacheType cache_type, url.mojom.Url url);
 
   // Requests that the browser cache |data| for the specified CacheStorage entry.
-  // TODO(https://crbug.com/779444): Verify or remove |cache_storage_origin|.
   // TODO(kinuko): Consider making the renderer-side code directly call into the
   // origin's CacheStoragePtr.
   DidGenerateCacheableMetadataInCacheStorage(
       url.mojom.Url url, mojo_base.mojom.Time expected_response_time,
-      mojo_base.mojom.BigBuffer data, url.mojom.Origin cache_storage_origin,
-      string cache_storage_cache_name);
+      mojo_base.mojom.BigBuffer data, string cache_storage_cache_name);
 };
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
index 8b41bc7..3a78ce4 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3406,7 +3406,7 @@
   kCrossOriginOpenerPolicySameOriginAllowPopupsReportOnly = 4089,
   kCrossOriginOpenerPolicySameOriginReportOnly = 4090,
   kImageLoadAtDismissalEvent = 4091,
-  kPrivateNetworkAccessIgnoredPreflightError = 4092,
+  kOBSOLETE_PrivateNetworkAccessIgnoredPreflightError = 4092,
   kAbortPaymentRespondWithTrue = 4093,
   // The items above roughly this point are available in the M98 branch.
 
diff --git a/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h b/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h
index 106356d8..14764f42 100644
--- a/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h
+++ b/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h
@@ -33,9 +33,6 @@
 std::unique_ptr<WebMockThreadScheduler>
 CreateMockWebMainThreadSchedulerForTests();
 
-void RunIdleTasksForTesting(WebThreadScheduler& scheduler,
-                            base::OnceClosure callback);
-
 // Returns a SequencedTaskRunner. This implementation is same as
 // base::SequencedTaskRunner::GetCurrentDefault(), but this is intended to be
 // used for testing. See crbug.com/794123.
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
index aeb6e0c5..cf6f78c 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
@@ -68,8 +68,8 @@
   base::span<const uint8_t> serialized_data = cached_metadata->SerializedData();
   CachedMetadataSender::SendToCodeCacheHost(
       code_cache_host, mojom::blink::CodeCacheType::kWebAssembly, response_url,
-      response_time, execution_context->GetSecurityOrigin(),
-      cache_storage_cache_name, serialized_data.data(), serialized_data.size());
+      response_time, cache_storage_cache_name, serialized_data.data(),
+      serialized_data.size());
 }
 
 class WasmCodeCachingCallback {
diff --git a/third_party/blink/renderer/controller/user_level_memory_pressure_signal_generator_test.cc b/third_party/blink/renderer/controller/user_level_memory_pressure_signal_generator_test.cc
index 3c968b7b..6f08b9c 100644
--- a/third_party/blink/renderer/controller/user_level_memory_pressure_signal_generator_test.cc
+++ b/third_party/blink/renderer/controller/user_level_memory_pressure_signal_generator_test.cc
@@ -91,6 +91,7 @@
   void AddTaskObserver(base::TaskObserver*) override {}
   void RemoveTaskObserver(base::TaskObserver*) override {}
   void SetV8Isolate(v8::Isolate*) override {}
+  void StartIdlePeriodForTesting() override {}
 };
 
 class UserLevelMemoryPressureSignalGeneratorTest : public testing::Test {
diff --git a/third_party/blink/renderer/core/animation/animatable.cc b/third_party/blink/renderer/core/animation/animatable.cc
index 5ed350b..c686adc 100644
--- a/third_party/blink/renderer/core/animation/animatable.cc
+++ b/third_party/blink/renderer/core/animation/animatable.cc
@@ -118,12 +118,12 @@
 
   // ViewTimeline options.
   if (options_dict->hasRangeStart() &&
-      RuntimeEnabledFeatures::CSSScrollTimelineEnabled()) {
+      RuntimeEnabledFeatures::ScrollTimelineEnabled()) {
     animation->SetRangeStartInternal(TimelineOffset::Create(
         element, options_dict->rangeStart(), 0, exception_state));
   }
   if (options_dict->hasRangeEnd() &&
-      RuntimeEnabledFeatures::CSSScrollTimelineEnabled()) {
+      RuntimeEnabledFeatures::ScrollTimelineEnabled()) {
     animation->SetRangeEndInternal(TimelineOffset::Create(
         element, options_dict->rangeEnd(), 100, exception_state));
   }
diff --git a/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc b/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc
index e05f48cb..e72418b 100644
--- a/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc
+++ b/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc
@@ -24,9 +24,9 @@
 namespace blink {
 
 class CSSScrollTimelineTest : public PageTestBase,
-                              private ScopedCSSScrollTimelineForTest {
+                              private ScopedScrollTimelineForTest {
  public:
-  CSSScrollTimelineTest() : ScopedCSSScrollTimelineForTest(true) {}
+  CSSScrollTimelineTest() : ScopedScrollTimelineForTest(true) {}
 
   DocumentAnimations& GetDocumentAnimations() const {
     return GetDocument().GetDocumentAnimations();
diff --git a/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc b/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc
index 5c118bce..1719623e 100644
--- a/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc
+++ b/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc
@@ -161,7 +161,7 @@
 }
 
 TEST_F(CSSComputedStyleDeclarationTest, UseCountDurationZero) {
-  ScopedCSSScrollTimelineForTest scroll_timeline_feature(false);
+  ScopedScrollTimelineForTest scroll_timeline_feature(false);
   GetDocument().body()->setInnerHTML(R"HTML(
     <style>
       div {
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index b4d1ee9..f9d9420 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -900,7 +900,7 @@
       valid_for_marker: true,
       is_animation_property: true,
       valid_for_keyframe: false,
-      runtime_flag: "CSSScrollTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "animation-range-end",
@@ -913,7 +913,7 @@
       valid_for_marker: true,
       is_animation_property: true,
       valid_for_keyframe: false,
-      runtime_flag: "CSSScrollTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "animation-timeline",
@@ -926,7 +926,7 @@
       typedom_types: ["Keyword"],
       separator: ",",
       valid_for_marker: true,
-      runtime_flag: "CSSScrollTimeline",
+      runtime_flag: "ScrollTimeline",
       is_animation_property: true,
     },
     {
@@ -4415,7 +4415,7 @@
       type_name: "Vector<TimelineAttachment>",
       converter: "ConvertViewTimelineAttachment",
       separator: ",",
-      runtime_flag: "CSSScrollTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "scroll-timeline-axis",
@@ -4426,7 +4426,7 @@
       type_name: "Vector<TimelineAxis>",
       converter: "ConvertViewTimelineAxis",
       separator: ",",
-      runtime_flag: "CSSScrollTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "scroll-timeline-name",
@@ -4438,7 +4438,7 @@
       wrapper_pointer_name: "Persistent",
       converter: "ConvertViewTimelineName",
       separator: ",",
-      runtime_flag: "CSSScrollTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "shape-image-threshold",
@@ -5186,7 +5186,7 @@
       type_name: "Vector<TimelineAttachment>",
       converter: "ConvertViewTimelineAttachment",
       separator: ",",
-      runtime_flag: "CSSViewTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "view-timeline-axis",
@@ -5197,7 +5197,7 @@
       type_name: "Vector<TimelineAxis>",
       converter: "ConvertViewTimelineAxis",
       separator: ",",
-      runtime_flag: "CSSViewTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "view-timeline-inset",
@@ -5209,7 +5209,7 @@
       type_name: "Vector<TimelineInset>",
       converter: "ConvertViewTimelineInset",
       separator: ",",
-      runtime_flag: "CSSViewTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "view-timeline-name",
@@ -5221,7 +5221,7 @@
       wrapper_pointer_name: "Persistent",
       converter: "ConvertViewTimelineName",
       separator: ",",
-      runtime_flag: "CSSViewTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "view-transition-name",
@@ -6664,7 +6664,7 @@
       ],
       property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
       valid_for_keyframe: false,
-      runtime_flag: 'CSSScrollTimeline',
+      runtime_flag: 'ScrollTimeline',
     },
     {
       // Variant of the "animation" shorthand which includes the
@@ -6689,7 +6689,7 @@
       ],
       property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
       valid_for_keyframe: false,
-      runtime_flag: 'CSSScrollTimeline',
+      runtime_flag: 'ScrollTimeline',
     },
     {
       name: "background",
@@ -7189,7 +7189,7 @@
       name: "scroll-timeline",
       longhands: ["scroll-timeline-name", "scroll-timeline-axis", "scroll-timeline-attachment"],
       property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
-      runtime_flag: "CSSScrollTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "text-decoration",
@@ -7215,7 +7215,7 @@
       name: "view-timeline",
       longhands: ["view-timeline-name", "view-timeline-axis", "view-timeline-attachment"],
       property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
-      runtime_flag: "CSSViewTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "-webkit-border-after",
@@ -7803,7 +7803,7 @@
       name: "-webkit-alternative-animation-with-timeline",
       alias_for: "-alternative-animation-with-timeline",
       alternative_of: "-webkit-animation",
-      runtime_flag: "CSSScrollTimeline",
+      runtime_flag: "ScrollTimeline",
     },
     {
       name: "-webkit-alternative-animation-with-delay-start-end",
diff --git a/third_party/blink/renderer/core/css/css_property_names_test.cc b/third_party/blink/renderer/core/css/css_property_names_test.cc
index acc92d5..435ddeb 100644
--- a/third_party/blink/renderer/core/css/css_property_names_test.cc
+++ b/third_party/blink/renderer/core/css/css_property_names_test.cc
@@ -13,14 +13,14 @@
   ScopedCSSAnimationDelayStartEndForTest start_end_enabled(false);
 
   {
-    ScopedCSSScrollTimelineForTest scroll_timeline_enabled(false);
+    ScopedScrollTimelineForTest scroll_timeline_enabled(false);
     EXPECT_EQ(
         CSSPropertyID::kAnimation,
         UnresolvedCSSPropertyID(/* execution_context */ nullptr, "animation"));
   }
 
   {
-    ScopedCSSScrollTimelineForTest scroll_timeline_enabled(true);
+    ScopedScrollTimelineForTest scroll_timeline_enabled(true);
     EXPECT_EQ(
         CSSPropertyID::kAlternativeAnimationWithTimeline,
         UnresolvedCSSPropertyID(/* execution_context */ nullptr, "animation"));
@@ -29,7 +29,7 @@
 
 TEST(CSSPropertyNamesTest, AlternativeAnimationWithDelayStartEnd) {
   // CSSAnimationDelayStartEnd depends on CSSScrollTimeline.
-  ScopedCSSScrollTimelineForTest scroll_timeline_enabled(true);
+  ScopedScrollTimelineForTest scroll_timeline_enabled(true);
 
   {
     ScopedCSSAnimationDelayStartEndForTest start_end_enabled(false);
diff --git a/third_party/blink/renderer/core/css/element_rule_collector.cc b/third_party/blink/renderer/core/css/element_rule_collector.cc
index 7acded0..2220ab2 100644
--- a/third_party/blink/renderer/core/css/element_rule_collector.cc
+++ b/third_party/blink/renderer/core/css/element_rule_collector.cc
@@ -519,9 +519,15 @@
       if (pseudo_style_request_.pseudo_id != kPseudoIdNone ||
           result.dynamic_pseudo == kPseudoIdNone) {
         Element* style_container_candidate =
-            pseudo_style_request_.pseudo_id == kPseudoIdNone
-                ? context_.GetElement().ParentOrShadowHostElement()
-                : &context_.GetElement();
+            style_recalc_context_.style_container;
+        if (!style_container_candidate) {
+          if (pseudo_style_request_.pseudo_id == kPseudoIdNone) {
+            style_container_candidate =
+                context_.GetElement().ParentOrShadowHostElement();
+          } else {
+            style_container_candidate = &context_.GetElement();
+          }
+        }
         if (!EvaluateAndAddContainerQueries(
                 style_container_candidate, *container_query,
                 style_recalc_context_, container_selector_cache_, result_)) {
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
index 892db43..e319704 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
@@ -2329,7 +2329,7 @@
         auto percent =
             To<CSSPrimitiveValue>(range_name_percent->Item(1)).GetFloatValue();
 
-        if (!RuntimeEnabledFeatures::CSSViewTimelineEnabled() &&
+        if (!RuntimeEnabledFeatures::ScrollTimelineEnabled() &&
             range_name != TimelineOffset::NamedRange::kNone) {
           return nullptr;
         }
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
index ff3e277..b355e89 100644
--- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -4307,7 +4307,7 @@
 
 CSSValue* ConsumeAnimationDuration(CSSParserTokenRange& range,
                                    const CSSParserContext& context) {
-  if (RuntimeEnabledFeatures::CSSScrollTimelineEnabled()) {
+  if (RuntimeEnabledFeatures::ScrollTimelineEnabled()) {
     if (CSSValue* ident = ConsumeIdent<CSSValueID::kAuto>(range)) {
       return ident;
     }
@@ -4348,7 +4348,7 @@
 CSSValue* ConsumeAnimationRange(CSSParserTokenRange& range,
                                 const CSSParserContext& context,
                                 double default_offset_percent) {
-  DCHECK(RuntimeEnabledFeatures::CSSScrollTimelineEnabled());
+  DCHECK(RuntimeEnabledFeatures::ScrollTimelineEnabled());
   if (CSSValue* ident = ConsumeIdent<CSSValueID::kNormal>(range)) {
     return ident;
   }
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index a5745abd..6a7f15e 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -467,7 +467,7 @@
     CSSParserTokenRange& range,
     const CSSParserContext& context,
     const CSSParserLocalContext&) const {
-  DCHECK(RuntimeEnabledFeatures::CSSScrollTimelineEnabled());
+  DCHECK(RuntimeEnabledFeatures::ScrollTimelineEnabled());
   return css_parsing_utils::ConsumeCommaSeparatedList(
       css_parsing_utils::ConsumeAnimationRange, range, context,
       /* default_offset_percent */ 0.0);
@@ -489,7 +489,7 @@
     CSSParserTokenRange& range,
     const CSSParserContext& context,
     const CSSParserLocalContext&) const {
-  DCHECK(RuntimeEnabledFeatures::CSSScrollTimelineEnabled());
+  DCHECK(RuntimeEnabledFeatures::ScrollTimelineEnabled());
   return css_parsing_utils::ConsumeCommaSeparatedList(
       css_parsing_utils::ConsumeAnimationRange, range, context,
       /* default_offset_percent */ 100.0);
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
index e2133ea..11ffe6e 100644
--- a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
@@ -84,7 +84,7 @@
     case CSSPropertyID::kAnimationRangeStart:
     case CSSPropertyID::kAnimationRangeEnd:
       // New animation-* properties are  "reset only", see kAnimationDelayEnd.
-      DCHECK(RuntimeEnabledFeatures::CSSScrollTimelineEnabled());
+      DCHECK(RuntimeEnabledFeatures::ScrollTimelineEnabled());
       return nullptr;
     default:
       NOTREACHED();
@@ -405,7 +405,7 @@
     const CSSParserContext& context,
     const CSSParserLocalContext& local_context,
     HeapVector<CSSPropertyValue, 64>& properties) const {
-  DCHECK(RuntimeEnabledFeatures::CSSScrollTimelineEnabled());
+  DCHECK(RuntimeEnabledFeatures::ScrollTimelineEnabled());
 
   using css_parsing_utils::AddProperty;
   using css_parsing_utils::ConsumeCommaIncludingWhitespace;
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc
index fbc50f2..7fd57095 100644
--- a/third_party/blink/renderer/core/css/style_engine_test.cc
+++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -5952,7 +5952,7 @@
 TEST_F(StyleEngineTest, AnimationShorthandFlags) {
   String css = "animation: foo 1s";
   {
-    ScopedCSSScrollTimelineForTest scroll_timeline_enabled(false);
+    ScopedScrollTimelineForTest scroll_timeline_enabled(false);
     ScopedCSSAnimationDelayStartEndForTest start_end_enabled(false);
     const CSSPropertyValueSet* set =
         css_test_helpers::ParseDeclarationBlock(css);
@@ -5968,7 +5968,7 @@
     EXPECT_TRUE(set->HasProperty(CSSPropertyID::kAnimationName));
   }
   {
-    ScopedCSSScrollTimelineForTest scroll_timeline_enabled(true);
+    ScopedScrollTimelineForTest scroll_timeline_enabled(true);
     ScopedCSSAnimationDelayStartEndForTest start_end_enabled(false);
     const CSSPropertyValueSet* set =
         css_test_helpers::ParseDeclarationBlock(css);
@@ -5987,7 +5987,7 @@
     EXPECT_TRUE(set->HasProperty(CSSPropertyID::kAnimationRangeEnd));
   }
   {
-    ScopedCSSScrollTimelineForTest scroll_timeline_enabled(true);
+    ScopedScrollTimelineForTest scroll_timeline_enabled(true);
     ScopedCSSAnimationDelayStartEndForTest start_end_enabled(true);
     const CSSPropertyValueSet* set =
         css_test_helpers::ParseDeclarationBlock(css);
@@ -6006,10 +6006,10 @@
     EXPECT_TRUE(set->HasProperty(CSSPropertyID::kAnimationRangeStart));
     EXPECT_TRUE(set->HasProperty(CSSPropertyID::kAnimationRangeEnd));
   }
-  // Note that the combination CSSScrollTimeline=false and
+  // Note that the combination ScrollTimeline=false and
   // CSSAnimationDelayStartEnd=true is not supported, via 'depends_on'
   // in runtime_enabled_features.json5.
-  EXPECT_FALSE(!RuntimeEnabledFeatures::CSSScrollTimelineEnabled() &&
+  EXPECT_FALSE(!RuntimeEnabledFeatures::ScrollTimelineEnabled() &&
                RuntimeEnabledFeatures::CSSAnimationDelayStartEndEnabled());
 }
 
diff --git a/third_party/blink/renderer/core/css/style_property_serializer.cc b/third_party/blink/renderer/core/css/style_property_serializer.cc
index 8786609b..4d843c4 100644
--- a/third_party/blink/renderer/core/css/style_property_serializer.cc
+++ b/third_party/blink/renderer/core/css/style_property_serializer.cc
@@ -1594,7 +1594,7 @@
         auto* ident = DynamicTo<CSSIdentifierValue>(value);
         if (!ident || (ident->GetValueID() !=
                        CSSAnimationData::InitialTimeline().GetKeyword())) {
-          DCHECK(RuntimeEnabledFeatures::CSSScrollTimelineEnabled());
+          DCHECK(RuntimeEnabledFeatures::ScrollTimelineEnabled());
           return g_empty_string;
         }
         is_initial_value = true;
@@ -1609,7 +1609,7 @@
       if (property->IDEquals(CSSPropertyID::kAnimationRangeStart)) {
         auto* ident = DynamicTo<CSSIdentifierValue>(value);
         if (!ident || (ident->GetValueID() != CSSValueID::kNormal)) {
-          DCHECK(RuntimeEnabledFeatures::CSSScrollTimelineEnabled());
+          DCHECK(RuntimeEnabledFeatures::ScrollTimelineEnabled());
           return g_empty_string;
         }
         is_initial_value = true;
@@ -1617,7 +1617,7 @@
       if (property->IDEquals(CSSPropertyID::kAnimationRangeEnd)) {
         auto* ident = DynamicTo<CSSIdentifierValue>(value);
         if (!ident || (ident->GetValueID() != CSSValueID::kNormal)) {
-          DCHECK(RuntimeEnabledFeatures::CSSScrollTimelineEnabled());
+          DCHECK(RuntimeEnabledFeatures::ScrollTimelineEnabled());
           return g_empty_string;
         }
         is_initial_value = true;
diff --git a/third_party/blink/renderer/core/css/style_recalc_context.cc b/third_party/blink/renderer/core/css/style_recalc_context.cc
index 9f5a0a3a..db91d52 100644
--- a/third_party/blink/renderer/core/css/style_recalc_context.cc
+++ b/third_party/blink/renderer/core/css/style_recalc_context.cc
@@ -71,7 +71,11 @@
   DCHECK(slot.IsInShadowTree());
   Element* host = slot.OwnerShadowHost();
   DCHECK(host);
-  return StyleRecalcContext{FromInclusiveAncestors(*host)};
+  StyleRecalcContext slot_child_context(*this);
+  if (container) {
+    slot_child_context.container = ClosestInclusiveAncestorContainer(*host);
+  }
+  return slot_child_context;
 }
 
 StyleRecalcContext StyleRecalcContext::ForSlottedRules(
@@ -80,22 +84,26 @@
   // host. When matching ::slotted rules, the closest container may be found in
   // the shadow-including inclusive ancestry of the slot. If we reach the host,
   // the current container is still the closest one.
+
+  StyleRecalcContext slotted_context(*this);
   if (Element* shadow_container =
           ClosestInclusiveAncestorContainer(slot, slot.OwnerShadowHost())) {
-    return StyleRecalcContext{shadow_container};
+    slotted_context.container = shadow_container;
   }
-  return *this;
+  slotted_context.style_container = &slot;
+  return slotted_context;
 }
 
 StyleRecalcContext StyleRecalcContext::ForPartRules(Element& host) const {
   DCHECK(IsShadowHost(host));
 
-  if (!container) {
-    return *this;
+  StyleRecalcContext part_context(*this);
+  if (container) {
+    // The closest container for matching ::part rules is the originating host.
+    part_context.container = ClosestInclusiveAncestorContainer(host);
   }
-
-  // The closest container for matching ::part rules is the originating host.
-  return StyleRecalcContext{ClosestInclusiveAncestorContainer(host)};
+  part_context.style_container = &host;
+  return part_context;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/style_recalc_context.h b/third_party/blink/renderer/core/css/style_recalc_context.h
index 59133b6..4413f700 100644
--- a/third_party/blink/renderer/core/css/style_recalc_context.h
+++ b/third_party/blink/renderer/core/css/style_recalc_context.h
@@ -54,10 +54,14 @@
   // Called to update the context when matching ::part rules for shadow hosts.
   StyleRecalcContext ForPartRules(Element& host) const;
 
-  // Set to the nearest container (for container queries), if any.
+  // Set to the nearest container (for size container queries), if any.
   // This is used to evaluate container queries in ElementRuleCollector.
   Element* container = nullptr;
 
+  // Used to decide which is the the closest style() @container candidate for
+  // ::slotted() and ::part() rule matching. Otherwise nullptr.
+  Element* style_container = nullptr;
+
   StyleScopeFrame* style_scope_frame = nullptr;
 
   // The style for the element at the start of the lifecycle update, or the
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index a8ae825b..3085364 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -866,7 +866,7 @@
   // parsing a special case in this respect should be avoided if possible.
   virtual void FinishParsingChildren();
 
-  virtual void BeginParsingChildren() { SetIsFinishedParsingChildren(false); }
+  void BeginParsingChildren() { SetIsFinishedParsingChildren(false); }
 
   // Returns the pseudo element for the given PseudoId type.
   // |view_transition_name| is used to uniquely identify a pseudo element
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_metrics_test.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_metrics_test.cc
index 29af561..7b098f54 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_metrics_test.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_metrics_test.cc
@@ -9,8 +9,6 @@
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/scroll/scroll_enums.mojom-blink.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.h"
@@ -20,6 +18,8 @@
 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+#include "third_party/blink/renderer/platform/scheduler/public/main_thread_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/testing/histogram_tester.h"
 #include "third_party/blink/renderer/platform/testing/scoped_fake_ukm_recorder.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -39,9 +39,9 @@
   }
 
   void RunAsyncMatchingTasks() {
-    auto& scheduler =
-        blink::scheduler::WebThreadScheduler::MainThreadScheduler();
-    blink::scheduler::RunIdleTasksForTesting(scheduler, WTF::BindOnce([]() {}));
+    ThreadScheduler::Current()
+        ->ToMainThreadScheduler()
+        ->StartIdlePeriodForTesting();
     RunPendingTasks();
   }
 
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_test.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_test.cc
index c7e68ab..fc3da60 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_test.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_test.cc
@@ -8,8 +8,6 @@
 #include "components/shared_highlighting/core/common/shared_highlighting_features.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/input/web_menu_source_type.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/public_buildflags.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_font_face_descriptors.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_mouse_event_init.h"
@@ -40,6 +38,8 @@
 #include "third_party/blink/renderer/core/scroll/scrollable_area.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+#include "third_party/blink/renderer/platform/scheduler/public/main_thread_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 
 #if BUILDFLAG(ENABLE_UNHANDLED_TAP)
@@ -61,9 +61,9 @@
   }
 
   void RunAsyncMatchingTasks() {
-    auto& scheduler =
-        blink::scheduler::WebThreadScheduler::MainThreadScheduler();
-    blink::scheduler::RunIdleTasksForTesting(scheduler, WTF::BindOnce([]() {}));
+    ThreadScheduler::Current()
+        ->ToMainThreadScheduler()
+        ->StartIdlePeriodForTesting();
     RunPendingTasks();
   }
 
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_generation_navigation_test.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_generation_navigation_test.cc
index 8917bc5..eaf5cf9 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_generation_navigation_test.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_generation_navigation_test.cc
@@ -8,8 +8,6 @@
 #include "components/shared_highlighting/core/common/shared_highlighting_data_driven_test.h"
 #include "components/shared_highlighting/core/common/shared_highlighting_data_driven_test_results.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/renderer/core/annotation/annotation_agent_container_impl.h"
 #include "third_party/blink/renderer/core/annotation/annotation_agent_impl.h"
 #include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
@@ -21,6 +19,8 @@
 #include "third_party/blink/renderer/core/html/html_element.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+#include "third_party/blink/renderer/platform/scheduler/public/main_thread_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
@@ -75,8 +75,9 @@
 }
 
 void TextFragmentGenerationNavigationTest::RunAsyncMatchingTasks() {
-  auto& scheduler = blink::scheduler::WebThreadScheduler::MainThreadScheduler();
-  blink::scheduler::RunIdleTasksForTesting(scheduler, WTF::BindOnce([]() {}));
+  ThreadScheduler::Current()
+      ->ToMainThreadScheduler()
+      ->StartIdlePeriodForTesting();
   RunPendingTasks();
 }
 
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler_test.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler_test.cc
index 9520c5d..efbd1c9 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler_test.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler_test.cc
@@ -12,8 +12,6 @@
 #include "base/test/scoped_feature_list.h"
 #include "components/shared_highlighting/core/common/shared_highlighting_features.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_font_face_descriptors.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_mouse_event_init.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.h"
@@ -29,6 +27,8 @@
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+#include "third_party/blink/renderer/platform/scheduler/public/main_thread_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 
 namespace blink {
@@ -54,9 +54,9 @@
   }
 
   void RunAsyncMatchingTasks() {
-    auto& scheduler =
-        blink::scheduler::WebThreadScheduler::MainThreadScheduler();
-    blink::scheduler::RunIdleTasksForTesting(scheduler, WTF::BindOnce([]() {}));
+    ThreadScheduler::Current()
+        ->ToMainThreadScheduler()
+        ->StartIdlePeriodForTesting();
     RunPendingTasks();
   }
 
diff --git a/third_party/blink/renderer/core/html/fenced_frame/fence.cc b/third_party/blink/renderer/core/html/fenced_frame/fence.cc
index 34dd5f0..c3cbf77 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/fence.cc
+++ b/third_party/blink/renderer/core/html/fenced_frame/fence.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/html/fenced_frame/fence.h"
 
 #include "base/feature_list.h"
+#include "base/ranges/algorithm.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/fenced_frame/fenced_frame_utils.h"
@@ -98,12 +99,14 @@
     return;
   }
 
-  for (const V8FenceReportingDestination& web_destination :
-       event->destination()) {
-    frame->GetLocalFrameHostRemote().SendFencedFrameReportingBeacon(
-        event->getEventDataOr(String{""}), event->eventType(),
-        ToPublicDestination(web_destination));
-  }
+  WTF::Vector<blink::FencedFrame::ReportingDestination> destinations;
+  destinations.reserve(event->destination().size());
+  base::ranges::transform(event->destination(),
+                          std::back_inserter(destinations),
+                          ToPublicDestination);
+
+  frame->GetLocalFrameHostRemote().SendFencedFrameReportingBeacon(
+      event->getEventDataOr(String{""}), event->eventType(), destinations);
 }
 
 void Fence::setReportEventDataForAutomaticBeacons(
@@ -140,13 +143,15 @@
     AddConsoleMessage("This frame did not register reporting metadata.");
     return;
   }
-  WTF::Vector<blink::FencedFrame::ReportingDestination> destination_vector;
-  for (const V8FenceReportingDestination& web_destination :
-       event->destination()) {
-    destination_vector.push_back(ToPublicDestination(web_destination));
-  }
+
+  WTF::Vector<blink::FencedFrame::ReportingDestination> destinations;
+  destinations.reserve(event->destination().size());
+  base::ranges::transform(event->destination(),
+                          std::back_inserter(destinations),
+                          ToPublicDestination);
+
   frame->GetLocalFrameHostRemote().SetFencedFrameAutomaticBeaconReportEventData(
-      event->getEventDataOr(String{""}), destination_vector);
+      event->getEventDataOr(String{""}), destinations);
 }
 
 HeapVector<Member<FencedFrameConfig>> Fence::getNestedConfigs(
diff --git a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_config.cc b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_config.cc
index 8dac8bc..ad7fe3d 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_config.cc
+++ b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_config.cc
@@ -39,6 +39,13 @@
   KURL urn_uuid = KURL(*urn);
   urn_uuid_.emplace(std::move(urn_uuid));
 
+  const absl::optional<FencedFrame::RedactedFencedFrameProperty<gfx::Size>>&
+      container_size = config.container_size();
+  if (container_size.has_value() &&
+      container_size->potentially_opaque_value.has_value()) {
+    container_size_.emplace(*container_size->potentially_opaque_value);
+  }
+
   // `content_size` and `deprecated_should_freeze_initial_size` temporarily need
   // to be treated differently than other fields, because for implementation
   // convenience the fenced frame size is frozen by the embedder. In the long
diff --git a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_config.h b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_config.h
index 3ec7f2e6..19be9fab 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_config.h
+++ b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_config.h
@@ -99,6 +99,11 @@
     return urn_uuid_;
   }
 
+  absl::optional<gfx::Size> container_size(
+      base::PassKey<HTMLFencedFrameElement>) {
+    return container_size_;
+  }
+
   absl::optional<gfx::Size> content_size(
       base::PassKey<HTMLFencedFrameElement>) {
     return content_size_;
@@ -177,6 +182,11 @@
   // URL. This value is never exposed to the web platform.
   absl::optional<KURL> urn_uuid_;
 
+  // The intended size for the fenced frame. If <fencedframe> doesn't have a
+  // specified size, this will override the default size. If it does have a
+  // specified size, this will do nothing.
+  absl::optional<gfx::Size> container_size_;
+
   // `content_size` and `deprecated_should_freeze_initial_size` temporarily need
   // to be treated differently than other fields, because for implementation
   // convenience the fenced frame size is frozen by the embedder. In the long
diff --git a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc
index 1baad09..f65e783 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc
+++ b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc
@@ -72,7 +72,14 @@
   }
   if (auto* layout_object = GetElement().GetLayoutObject()) {
     layout_object->SetNeedsLayoutAndFullPaintInvalidation(
-        "Froze MPArch fenced frame");
+        "Froze fenced frame content size");
+  }
+}
+
+void FencedFrameMPArchDelegate::MarkContainerSizeStale() {
+  if (auto* layout_object = GetElement().GetLayoutObject()) {
+    layout_object->SetNeedsLayoutAndFullPaintInvalidation(
+        "Stored fenced frame container size");
   }
 }
 
diff --git a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.h b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.h
index d98567a..62f73606 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.h
+++ b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.h
@@ -28,6 +28,7 @@
   void AttachLayoutTree() override;
   bool SupportsFocus() override;
   void MarkFrozenFrameSizeStale() override;
+  void MarkContainerSizeStale() override;
   void DidChangeFramePolicy(const FramePolicy&) override;
 
   void Trace(Visitor* visitor) const override;
diff --git a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc
index 59a1654..18799f5 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc
+++ b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc
@@ -478,6 +478,7 @@
 void HTMLFencedFrameElement::Navigate(
     const KURL& url,
     absl::optional<bool> deprecated_should_freeze_initial_size,
+    absl::optional<gfx::Size> container_size,
     absl::optional<gfx::Size> content_size,
     String embedder_shared_storage_context) {
   TRACE_EVENT0("navigation", "HTMLFencedFrameElement::Navigate");
@@ -566,6 +567,11 @@
           ? FencedFrameCreationOutcome::kSuccessDefault
           : FencedFrameCreationOutcome::kSuccessOpaque);
 
+  // Inherit the container size from the FencedFrameConfig, if one is present.
+  if (container_size.has_value()) {
+    SetContainerSize(*container_size);
+  }
+
   // Handle size freezing.
   // This isn't strictly correct, because the size is frozen on navigation
   // start rather than navigation commit (i.e. if the navigation fails, the
@@ -618,7 +624,7 @@
             ->GetValueIgnoringVisibility<FencedFrameConfig::Attribute::kURL>();
   }
   Navigate(url, config_->deprecated_should_freeze_initial_size(PassKey()),
-           config_->content_size(PassKey()),
+           config_->container_size(PassKey()), config_->content_size(PassKey()),
            config_->GetSharedStorageContext());
 }
 
@@ -832,6 +838,15 @@
   should_freeze_frame_size_on_next_layout_ = true;
 }
 
+void HTMLFencedFrameElement::SetContainerSize(const gfx::Size& size) {
+  setAttribute(html_names::kWidthAttr, String::Format("%dpx", size.width()),
+               ASSERT_NO_EXCEPTION);
+  setAttribute(html_names::kHeightAttr, String::Format("%dpx", size.height()),
+               ASSERT_NO_EXCEPTION);
+
+  frame_delegate_->MarkContainerSizeStale();
+}
+
 void HTMLFencedFrameElement::FreezeFrameSize(const PhysicalSize& size,
                                              bool should_coerce_size) {
   frozen_frame_size_ = size;
diff --git a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h
index 2873889..1865dba 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h
+++ b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h
@@ -60,6 +60,7 @@
     virtual void AttachLayoutTree() {}
     virtual bool SupportsFocus() { return false; }
     virtual void MarkFrozenFrameSizeStale() {}
+    virtual void MarkContainerSizeStale() {}
     virtual void DidChangeFramePolicy(const FramePolicy& frame_policy) {}
 
    protected:
@@ -124,6 +125,7 @@
   void Navigate(const KURL& url,
                 absl::optional<bool> deprecated_should_freeze_initial_size =
                     absl::nullopt,
+                absl::optional<gfx::Size> container_size = absl::nullopt,
                 absl::optional<gfx::Size> content_size = absl::nullopt,
                 String embedder_shared_storage_context = String());
 
@@ -154,6 +156,10 @@
   void AttachLayoutTree(AttachContext& context) override;
   bool SupportsFocus() const override;
 
+  // Set the size of the fenced frame outer container. Used for container size
+  // specified by FencedFrameConfig.
+  void SetContainerSize(const gfx::Size& container_size);
+
   // Make sure that the fenced frame size is not frozen. (If it is already
   // unfrozen, this is a no-op.)
   void UnfreezeFrameSize();
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc
index 2f70301..9752425 100644
--- a/third_party/blink/renderer/core/html/html_element.cc
+++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -1231,12 +1231,11 @@
           HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions,
           /*exception_state=*/nullptr);
       // Event handlers could have changed the popover, including by removing
-      // the popover attribute, or changing its value. If that happened, defer
-      // to the change that already happened, and don't reset it again here.
-      if (!isConnected() || !HasPopoverAttribute() ||
-          original_type != FastGetAttribute(html_names::kPopoverAttr)) {
-        return;
-      }
+      // the popover attribute, or changing its value. If that happened, we need
+      // to make sure that PopoverData's copy of the popover attribute stays in
+      // sync.
+      type = GetPopoverTypeFromAttributeValue(
+          FastGetAttribute(html_names::kPopoverAttr));
     }
   }
   if (type == PopoverValueType::kNone) {
@@ -1695,10 +1694,15 @@
   if (PopoverType() == PopoverValueType::kAuto ||
       PopoverType() == PopoverValueType::kHint) {
     auto& stack = document.PopoverStack();
+    bool repeating_hide = false;
     do {
-      // Hide any popovers above us in the stack.
-      HideAllPopoversUntil(this, document, focus_behavior, transition_behavior,
-                           HidePopoverIndependence::kLeaveUnrelated);
+      // Hide any popovers above us in the stack. Fire events only the first
+      // time through the while loop.
+      HideAllPopoversUntil(
+          this, document, focus_behavior,
+          repeating_hide ? HidePopoverTransitionBehavior::kNoEventsNoWaiting
+                         : transition_behavior,
+          HidePopoverIndependence::kLeaveUnrelated);
       // The 'beforetoggle' event handlers could have changed this popover, e.g.
       // by changing its type, removing it from the document, or calling
       // hidePopover().
@@ -1706,9 +1710,17 @@
                           /*include_event_handler_text=*/true, &document)) {
         return;
       }
-    } while (PopoverType() == PopoverValueType::kAuto
-                 ? (!stack.empty() && stack.back() != this)
-                 : (document.TopmostPopoverOrHint() != this));
+      repeating_hide = PopoverType() == PopoverValueType::kAuto
+                           ? (!stack.empty() && stack.back() != this)
+                           : (document.TopmostPopoverOrHint() != this);
+      if (repeating_hide) {
+        document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+            mojom::blink::ConsoleMessageSource::kOther,
+            mojom::blink::ConsoleMessageLevel::kWarning,
+            "The `beforetoggle` event handler for a popover triggered another "
+            "popover to be shown. This is not recommended."));
+      }
+    } while (repeating_hide);
   }
 
   MarkPopoverInvokersDirty(*this);
@@ -3109,8 +3121,8 @@
     EnsureElementInternals().TakeStateAndRestore();
 }
 
-void HTMLElement::BeginParsingChildren() {
-  Element::BeginParsingChildren();
+void HTMLElement::ParserDidSetAttributes() {
+  Element::ParserDidSetAttributes();
 
   if (GetDocument().IsDirAttributeDirty() && !HasDirectionAuto() &&
       !ElementAffectsDirectionality(this)) {
diff --git a/third_party/blink/renderer/core/html/html_element.h b/third_party/blink/renderer/core/html/html_element.h
index 9b1ceda..78c2455 100644
--- a/third_party/blink/renderer/core/html/html_element.h
+++ b/third_party/blink/renderer/core/html/html_element.h
@@ -208,7 +208,7 @@
   void UpdateDirectionalityAndDescendant(TextDirection direction);
   void UpdateDescendantDirectionality(TextDirection direction);
   void AdjustDirectionalityIfNeededAfterShadowRootChanged();
-  void BeginParsingChildren() override;
+  void ParserDidSetAttributes() override;
 
   V8UnionBooleanOrStringOrUnrestrictedDouble* hidden() const;
   void setHidden(const V8UnionBooleanOrStringOrUnrestrictedDouble*);
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index 0444fd0..23e64b5 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1316,6 +1316,9 @@
       // when `contain: strict` is explicitly set.
       if (fragment.HasAnchorQuery())
         return false;
+    } else if (RuntimeEnabledFeatures::LayoutNewSubtreeRootEnabled()) {
+      // We need a previous layout result to begin layout at a subtree root.
+      return false;
     }
 
     // A box which doesn't establish a new formating context can pass a whole
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
index 8cf82c6..a1a0f536 100644
--- a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
@@ -35,8 +35,6 @@
 #include "cc/trees/sticky_position_constraint.h"
 #include "content/test/test_blink_web_unit_test_support.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/platform/web_cache.h"
 #include "third_party/blink/public/web/web_settings.h"
 #include "third_party/blink/public/web/web_view_client.h"
@@ -64,6 +62,8 @@
 #include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
 #include "third_party/blink/renderer/platform/graphics/touch_action.h"
 #include "third_party/blink/renderer/platform/region_capture_crop_id.h"
+#include "third_party/blink/renderer/platform/scheduler/public/main_thread_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/testing/find_cc_layer.h"
 #include "third_party/blink/renderer/platform/testing/histogram_tester.h"
 #include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
@@ -2090,10 +2090,9 @@
   }
 
   void RunIdleTasks() {
-    auto& scheduler =
-        blink::scheduler::WebThreadScheduler::MainThreadScheduler();
-    blink::scheduler::RunIdleTasksForTesting(scheduler,
-                                             base::BindOnce([]() {}));
+    ThreadScheduler::Current()
+        ->ToMainThreadScheduler()
+        ->StartIdlePeriodForTesting();
     test::RunPendingTasks();
   }
 
@@ -2656,7 +2655,7 @@
 }
 
 TEST_P(ScrollingSimTest, CompositedScrollDeferredWithLinkedAnimation) {
-  ScopedCSSScrollTimelineForTest scroll_timeline_enabled(true);
+  ScopedScrollTimelineForTest scroll_timeline_enabled(true);
 
   String kUrl = "https://example.com/test.html";
   SimRequest request(kUrl, "text/html");
diff --git a/third_party/blink/renderer/core/page/slot_scoped_traversal.cc b/third_party/blink/renderer/core/page/slot_scoped_traversal.cc
index cc20340..17a9ece 100644
--- a/third_party/blink/renderer/core/page/slot_scoped_traversal.cc
+++ b/third_party/blink/renderer/core/page/slot_scoped_traversal.cc
@@ -10,44 +10,6 @@
 
 namespace blink {
 
-namespace {
-Element* NextSkippingChildrenOfShadowHost(const Element& start,
-                                          const Element& scope) {
-  DCHECK(scope.AssignedSlot());
-  if (!start.AuthorShadowRoot()) {
-    if (Element* first = ElementTraversal::FirstChild(start))
-      return first;
-  }
-
-  for (const Element* current = &start; current != scope;
-       current = current->parentElement()) {
-    if (Element* next_sibling = ElementTraversal::NextSibling(*current))
-      return next_sibling;
-  }
-  return nullptr;
-}
-
-Element* LastWithinOrSelfSkippingChildrenOfShadowHost(const Element& scope) {
-  Element* current = const_cast<Element*>(&scope);
-  while (!current->AuthorShadowRoot()) {
-    Element* last_child = ElementTraversal::LastChild(*current);
-    if (!last_child)
-      break;
-    current = last_child;
-  }
-  return current;
-}
-
-Element* PreviousSkippingChildrenOfShadowHost(const Element& start,
-                                              const Element& scope) {
-  DCHECK(scope.AssignedSlot());
-  DCHECK_NE(start, &scope);
-  if (Element* previous_sibling = ElementTraversal::PreviousSibling(start))
-    return LastWithinOrSelfSkippingChildrenOfShadowHost(*previous_sibling);
-  return start.parentElement();
-}
-}  // namespace
-
 HTMLSlotElement* SlotScopedTraversal::FindScopeOwnerSlot(
     const Element& current) {
   if (Element* nearest_inclusive_ancestor_assigned_to_slot =
@@ -66,84 +28,4 @@
   return element;
 }
 
-Element* SlotScopedTraversal::Next(const Element& current) {
-  Element* nearest_inclusive_ancestor_assigned_to_slot =
-      SlotScopedTraversal::NearestInclusiveAncestorAssignedToSlot(current);
-  DCHECK(nearest_inclusive_ancestor_assigned_to_slot);
-  // Search within children of an element which is assigned to a slot.
-  if (Element* next = NextSkippingChildrenOfShadowHost(
-          current, *nearest_inclusive_ancestor_assigned_to_slot))
-    return next;
-
-  // Seek to the next element assigned to the same slot.
-  HTMLSlotElement* slot =
-      nearest_inclusive_ancestor_assigned_to_slot->AssignedSlot();
-  DCHECK(slot);
-  const HeapVector<Member<Node>>& assigned_nodes = slot->AssignedNodes();
-  wtf_size_t current_index =
-      assigned_nodes.Find(*nearest_inclusive_ancestor_assigned_to_slot);
-  DCHECK_NE(current_index, kNotFound);
-  for (++current_index; current_index < assigned_nodes.size();
-       ++current_index) {
-    if (auto* element = DynamicTo<Element>(assigned_nodes[current_index].Get()))
-      return element;
-  }
-  return nullptr;
-}
-
-Element* SlotScopedTraversal::Previous(const Element& current) {
-  Element* nearest_inclusive_ancestor_assigned_to_slot =
-      SlotScopedTraversal::NearestInclusiveAncestorAssignedToSlot(current);
-  DCHECK(nearest_inclusive_ancestor_assigned_to_slot);
-
-  if (current != nearest_inclusive_ancestor_assigned_to_slot) {
-    // Search within children of an element which is assigned to a slot.
-    Element* previous = PreviousSkippingChildrenOfShadowHost(
-        current, *nearest_inclusive_ancestor_assigned_to_slot);
-    DCHECK(previous);
-    return previous;
-  }
-
-  // Seek to the previous element assigned to the same slot.
-  const HeapVector<Member<Node>>& assigned_nodes =
-      nearest_inclusive_ancestor_assigned_to_slot->AssignedSlot()
-          ->AssignedNodes();
-  wtf_size_t current_index =
-      assigned_nodes.ReverseFind(*nearest_inclusive_ancestor_assigned_to_slot);
-  DCHECK_NE(current_index, kNotFound);
-  for (; current_index > 0; --current_index) {
-    const Member<Node> assigned_node = assigned_nodes[current_index - 1];
-    auto* element = DynamicTo<Element>(assigned_node.Get());
-    if (!element)
-      continue;
-    return LastWithinOrSelfSkippingChildrenOfShadowHost(*element);
-  }
-  return nullptr;
-}
-
-Element* SlotScopedTraversal::FirstAssignedToSlot(HTMLSlotElement& slot) {
-  const HeapVector<Member<Node>>& assigned_nodes = slot.AssignedNodes();
-  for (auto assigned_node : assigned_nodes) {
-    if (auto* element = DynamicTo<Element>(assigned_node.Get()))
-      return element;
-  }
-  return nullptr;
-}
-
-Element* SlotScopedTraversal::LastAssignedToSlot(HTMLSlotElement& slot) {
-  const HeapVector<Member<Node>>& assigned_nodes = slot.AssignedNodes();
-  for (auto assigned_node = assigned_nodes.rbegin();
-       assigned_node != assigned_nodes.rend(); ++assigned_node) {
-    auto* element = DynamicTo<Element>(assigned_node->Get());
-    if (!element)
-      continue;
-    return LastWithinOrSelfSkippingChildrenOfShadowHost(*element);
-  }
-  return nullptr;
-}
-
-bool SlotScopedTraversal::IsSlotScoped(const Element& current) {
-  return SlotScopedTraversal::NearestInclusiveAncestorAssignedToSlot(current);
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/page/slot_scoped_traversal.h b/third_party/blink/renderer/core/page/slot_scoped_traversal.h
index 34a55eb..bc9997f 100644
--- a/third_party/blink/renderer/core/page/slot_scoped_traversal.h
+++ b/third_party/blink/renderer/core/page/slot_scoped_traversal.h
@@ -13,18 +13,14 @@
 class Element;
 class HTMLSlotElement;
 
+// TODO(http://crbug.com/1439837): Rename this class as it no longer provides
+// traversal functionality.
 class CORE_EXPORT SlotScopedTraversal {
   STATIC_ONLY(SlotScopedTraversal);
 
  public:
   static HTMLSlotElement* FindScopeOwnerSlot(const Element&);
   static Element* NearestInclusiveAncestorAssignedToSlot(const Element&);
-  static Element* Next(const Element&);
-  static Element* Previous(const Element&);
-  static Element* FirstAssignedToSlot(HTMLSlotElement&);
-  static Element* LastAssignedToSlot(HTMLSlotElement&);
-
-  static bool IsSlotScoped(const Element&);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc b/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc
index f39cd92..6c7d5c6 100644
--- a/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc
+++ b/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc
@@ -67,32 +67,6 @@
   shadow_root.setInnerHTML(String::FromUTF8(shadow_inner_html));
 }
 
-TEST_F(SlotScopedTraversalTest, emptySlot) {
-  const char* main_html = "<div id='host'></div>";
-  const char* shadow_html = "<slot></slot>";
-  SetupSampleHTML(main_html, shadow_html, 0);
-
-  Element* host = GetDocument().QuerySelector("#host");
-  ShadowRoot* shadow_root = host->OpenShadowRoot();
-  auto* slot = To<HTMLSlotElement>(shadow_root->QuerySelector("slot"));
-
-  EXPECT_EQ(nullptr, SlotScopedTraversal::FirstAssignedToSlot(*slot));
-  EXPECT_EQ(nullptr, SlotScopedTraversal::LastAssignedToSlot(*slot));
-}
-
-void SlotScopedTraversalTest::TestExpectedSequence(
-    const Vector<Element*>& list) {
-  for (wtf_size_t i = 0; i < list.size(); ++i) {
-    const Element* expected = i == list.size() - 1 ? nullptr : list[i + 1];
-    EXPECT_EQ(expected, SlotScopedTraversal::Next(*list[i]));
-  }
-
-  for (wtf_size_t i = list.size(); i > 0; --i) {
-    const Element* expected = i == 1 ? nullptr : list[i - 2];
-    EXPECT_EQ(expected, SlotScopedTraversal::Previous(*list[i - 1]));
-  }
-}
-
 TEST_F(SlotScopedTraversalTest, simpleSlot) {
   const char* main_html =
       "<div id='host'>"
@@ -110,295 +84,16 @@
   ShadowRoot* shadow_root = host->OpenShadowRoot();
   auto* slot = To<HTMLSlotElement>(shadow_root->QuerySelector("slot"));
 
-  EXPECT_EQ(inner1, SlotScopedTraversal::FirstAssignedToSlot(*slot));
-  EXPECT_EQ(inner2, SlotScopedTraversal::LastAssignedToSlot(*slot));
-  EXPECT_FALSE(SlotScopedTraversal::IsSlotScoped(*host));
-  EXPECT_FALSE(SlotScopedTraversal::IsSlotScoped(*slot));
-  EXPECT_TRUE(SlotScopedTraversal::IsSlotScoped(*inner1));
-  EXPECT_TRUE(SlotScopedTraversal::IsSlotScoped(*inner2));
+  EXPECT_EQ(nullptr,
+            SlotScopedTraversal::NearestInclusiveAncestorAssignedToSlot(*host));
+  EXPECT_EQ(nullptr,
+            SlotScopedTraversal::NearestInclusiveAncestorAssignedToSlot(*slot));
   EXPECT_EQ(inner1, SlotScopedTraversal::NearestInclusiveAncestorAssignedToSlot(
                         *inner1));
   EXPECT_EQ(inner2, SlotScopedTraversal::NearestInclusiveAncestorAssignedToSlot(
                         *inner2));
   EXPECT_EQ(slot, SlotScopedTraversal::FindScopeOwnerSlot(*inner1));
   EXPECT_EQ(slot, SlotScopedTraversal::FindScopeOwnerSlot(*inner2));
-
-  Vector<Element*> expected_sequence({inner1, inner2});
-  TestExpectedSequence(expected_sequence);
-}
-
-TEST_F(SlotScopedTraversalTest, multipleSlots) {
-  const char* main_html =
-      "<div id='host'>"
-      "<div id='inner0' slot='slot0'></div>"
-      "<div id='inner1' slot='slot1'></div>"
-      "<div id='inner2'></div>"
-      "<div id='inner3' slot='slot1'></div>"
-      "<div id='inner4' slot='slot0'></div>"
-      "<div id='inner5'></div>"
-      "</div>";
-
-  const char* shadow_html =
-      "<slot id='unnamedslot'></slot>"
-      "<slot id='slot0' name='slot0'></slot>"
-      "<slot id='slot1' name='slot1'></slot>";
-
-  SetupSampleHTML(main_html, shadow_html, 0);
-
-  Element* host = GetDocument().QuerySelector("#host");
-  Element* inner[6];
-  inner[0] = GetDocument().QuerySelector("#inner0");
-  inner[1] = GetDocument().QuerySelector("#inner1");
-  inner[2] = GetDocument().QuerySelector("#inner2");
-  inner[3] = GetDocument().QuerySelector("#inner3");
-  inner[4] = GetDocument().QuerySelector("#inner4");
-  inner[5] = GetDocument().QuerySelector("#inner5");
-
-  ShadowRoot* shadow_root = host->OpenShadowRoot();
-  Element* slot_element[3];
-  slot_element[0] = shadow_root->QuerySelector("#slot0");
-  slot_element[1] = shadow_root->QuerySelector("#slot1");
-  slot_element[2] = shadow_root->QuerySelector("#unnamedslot");
-
-  HTMLSlotElement* slot[3];
-  slot[0] = To<HTMLSlotElement>(slot_element[0]);
-  slot[1] = To<HTMLSlotElement>(slot_element[1]);
-  slot[2] = To<HTMLSlotElement>(slot_element[2]);
-
-  {
-    // <slot id='slot0'> : Expected assigned nodes: inner0, inner4
-    EXPECT_EQ(inner[0], SlotScopedTraversal::FirstAssignedToSlot(*slot[0]));
-    EXPECT_EQ(inner[4], SlotScopedTraversal::LastAssignedToSlot(*slot[0]));
-    Vector<Element*> expected_sequence({inner[0], inner[4]});
-    TestExpectedSequence(expected_sequence);
-  }
-
-  {
-    // <slot name='slot1'> : Expected assigned nodes: inner1, inner3
-    EXPECT_EQ(inner[1], SlotScopedTraversal::FirstAssignedToSlot(*slot[1]));
-    EXPECT_EQ(inner[3], SlotScopedTraversal::LastAssignedToSlot(*slot[1]));
-    Vector<Element*> expected_sequence({inner[1], inner[3]});
-    TestExpectedSequence(expected_sequence);
-  }
-
-  {
-    // <slot id='unnamedslot'> : Expected assigned nodes: inner2, inner5
-    EXPECT_EQ(inner[2], SlotScopedTraversal::FirstAssignedToSlot(*slot[2]));
-    EXPECT_EQ(inner[5], SlotScopedTraversal::LastAssignedToSlot(*slot[2]));
-    Vector<Element*> expected_sequence({inner[2], inner[5]});
-    TestExpectedSequence(expected_sequence);
-  }
-}
-
-TEST_F(SlotScopedTraversalTest, shadowHostAtTopLevel) {
-  // This covers a shadow host is directly assigned to a slot.
-  //
-  // We build the following tree:
-  //         host
-  //           |
-  //       ShadowRoot
-  //           |
-  //     ____<slot>____
-  //     |      |      |
-  //   inner0 inner1 inner2
-  //     |      |      |
-  //   child0 child1 child2
-  //
-  // And iterate on inner0, inner1, and inner2 to attach shadow on each of
-  // them, and check if elements that are slotted to another slot are skipped
-  // in traversal.
-
-  const char* main_html =
-      "<div id='host'>"
-      "<div id='inner0'><div id='child0'></div></div>"
-      "<div id='inner1'><div id='child1'></div></div>"
-      "<div id='inner2'><div id='child2'></div></div>"
-      "</div>";
-
-  const char* shadow_html = "<slot></slot>";
-
-  for (int i = 0; i < 3; ++i) {
-    SetupSampleHTML(main_html, shadow_html, 0);
-
-    Element* host = GetDocument().QuerySelector("#host");
-    Element* inner[3];
-    inner[0] = GetDocument().QuerySelector("#inner0");
-    inner[1] = GetDocument().QuerySelector("#inner1");
-    inner[2] = GetDocument().QuerySelector("#inner2");
-    Element* child[3];
-    child[0] = GetDocument().QuerySelector("#child0");
-    child[1] = GetDocument().QuerySelector("#child1");
-    child[2] = GetDocument().QuerySelector("#child2");
-
-    AttachOpenShadowRoot(*inner[i], shadow_html);
-
-    ShadowRoot* shadow_root = host->OpenShadowRoot();
-    auto* slot = To<HTMLSlotElement>(shadow_root->QuerySelector("slot"));
-
-    switch (i) {
-      case 0: {
-        // inner0 is a shadow host.
-        EXPECT_EQ(inner[0], SlotScopedTraversal::FirstAssignedToSlot(*slot));
-        EXPECT_EQ(child[2], SlotScopedTraversal::LastAssignedToSlot(*slot));
-
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Next(*child[0]));
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Previous(*child[0]));
-
-        Vector<Element*> expected_sequence(
-            {inner[0], inner[1], child[1], inner[2], child[2]});
-        TestExpectedSequence(expected_sequence);
-      } break;
-
-      case 1: {
-        // inner1 is a shadow host.
-        EXPECT_EQ(inner[0], SlotScopedTraversal::FirstAssignedToSlot(*slot));
-        EXPECT_EQ(child[2], SlotScopedTraversal::LastAssignedToSlot(*slot));
-
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Next(*child[1]));
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Previous(*child[1]));
-
-        Vector<Element*> expected_sequence(
-            {inner[0], child[0], inner[1], inner[2], child[2]});
-        TestExpectedSequence(expected_sequence);
-      } break;
-
-      case 2: {
-        // inner2 is a shadow host.
-        EXPECT_EQ(inner[0], SlotScopedTraversal::FirstAssignedToSlot(*slot));
-        EXPECT_EQ(inner[2], SlotScopedTraversal::LastAssignedToSlot(*slot));
-
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Next(*child[2]));
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Previous(*child[2]));
-
-        Vector<Element*> expected_sequence(
-            {inner[0], child[0], inner[1], child[1], inner[2]});
-        TestExpectedSequence(expected_sequence);
-      } break;
-    }
-  }
-}
-
-TEST_F(SlotScopedTraversalTest, shadowHostAtSecondLevel) {
-  // This covers cases where a shadow host exists in a child of a slotted
-  // element.
-  //
-  // We build the following tree:
-  //            host
-  //              |
-  //          ShadowRoot
-  //              |
-  //        ____<slot>____
-  //        |             |
-  //     _inner0_      _inner1_
-  //     |      |      |      |
-  //   child0 child1 child2 child3
-  //     |      |      |      |
-  //    span0  span1  span2  span3
-  //
-  // And iterate on child0, child1, child2, and child3 to attach shadow on each
-  // of them, and check if elements that are slotted to another slot are skipped
-  // in traversal.
-
-  const char* main_html =
-      "<div id='host'>"
-      "<div id='inner0'>"
-      "<div id='child0'><span id='span0'></span></div>"
-      "<div id='child1'><span id='span1'></span></div>"
-      "</div>"
-      "<div id='inner1'>"
-      "<div id='child2'><span id='span2'></span></div>"
-      "<div id='child3'><span id='span3'></span></div>"
-      "</div>"
-      "</div>";
-
-  const char* shadow_html = "<slot></slot>";
-
-  for (int i = 0; i < 4; ++i) {
-    SetupSampleHTML(main_html, shadow_html, 0);
-
-    Element* host = GetDocument().QuerySelector("#host");
-    Element* inner[2];
-    inner[0] = GetDocument().QuerySelector("#inner0");
-    inner[1] = GetDocument().QuerySelector("#inner1");
-    Element* child[4];
-    child[0] = GetDocument().QuerySelector("#child0");
-    child[1] = GetDocument().QuerySelector("#child1");
-    child[2] = GetDocument().QuerySelector("#child2");
-    child[3] = GetDocument().QuerySelector("#child3");
-    Element* span[4];
-    span[0] = GetDocument().QuerySelector("#span0");
-    span[1] = GetDocument().QuerySelector("#span1");
-    span[2] = GetDocument().QuerySelector("#span2");
-    span[3] = GetDocument().QuerySelector("#span3");
-
-    AttachOpenShadowRoot(*child[i], shadow_html);
-
-    for (int j = 0; j < 4; ++j) {
-      DCHECK(child[i]);
-      DCHECK(span[i]);
-    }
-
-    ShadowRoot* shadow_root = host->OpenShadowRoot();
-    auto* slot = To<HTMLSlotElement>(shadow_root->QuerySelector("slot"));
-
-    switch (i) {
-      case 0: {
-        // child0 is a shadow host.
-        EXPECT_EQ(inner[0], SlotScopedTraversal::FirstAssignedToSlot(*slot));
-        EXPECT_EQ(span[3], SlotScopedTraversal::LastAssignedToSlot(*slot));
-
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Next(*span[0]));
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Previous(*span[0]));
-
-        const Vector<Element*> expected_sequence({inner[0], child[0], child[1],
-                                                  span[1], inner[1], child[2],
-                                                  span[2], child[3], span[3]});
-        TestExpectedSequence(expected_sequence);
-      } break;
-
-      case 1: {
-        // child1 is a shadow host.
-        EXPECT_EQ(inner[0], SlotScopedTraversal::FirstAssignedToSlot(*slot));
-        EXPECT_EQ(span[3], SlotScopedTraversal::LastAssignedToSlot(*slot));
-
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Next(*span[1]));
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Previous(*span[1]));
-
-        const Vector<Element*> expected_sequence({inner[0], child[0], span[0],
-                                                  child[1], inner[1], child[2],
-                                                  span[2], child[3], span[3]});
-        TestExpectedSequence(expected_sequence);
-      } break;
-
-      case 2: {
-        // child2 is a shadow host.
-        EXPECT_EQ(inner[0], SlotScopedTraversal::FirstAssignedToSlot(*slot));
-        EXPECT_EQ(span[3], SlotScopedTraversal::LastAssignedToSlot(*slot));
-
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Next(*span[2]));
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Previous(*span[2]));
-
-        const Vector<Element*> expected_sequence({inner[0], child[0], span[0],
-                                                  child[1], span[1], inner[1],
-                                                  child[2], child[3], span[3]});
-        TestExpectedSequence(expected_sequence);
-      } break;
-
-      case 3: {
-        // child3 is a shadow host.
-        EXPECT_EQ(inner[0], SlotScopedTraversal::FirstAssignedToSlot(*slot));
-        EXPECT_EQ(child[3], SlotScopedTraversal::LastAssignedToSlot(*slot));
-
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Next(*span[3]));
-        EXPECT_EQ(nullptr, SlotScopedTraversal::Previous(*span[3]));
-
-        const Vector<Element*> expected_sequence({inner[0], child[0], span[0],
-                                                  child[1], span[1], inner[1],
-                                                  child[2], span[2], child[3]});
-        TestExpectedSequence(expected_sequence);
-      } break;
-    }
-  }
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
index 7e638f3b..a431e19e 100644
--- a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
+++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
@@ -253,11 +253,13 @@
 void FakeLocalFrameHost::SendFencedFrameReportingBeacon(
     const WTF::String& event_data,
     const WTF::String& event_type,
-    blink::FencedFrame::ReportingDestination destination) {}
+    const WTF::Vector<blink::FencedFrame::ReportingDestination>& destinations) {
+}
 
 void FakeLocalFrameHost::SetFencedFrameAutomaticBeaconReportEventData(
     const WTF::String& event_data,
-    const WTF::Vector<blink::FencedFrame::ReportingDestination>& destination) {}
+    const WTF::Vector<blink::FencedFrame::ReportingDestination>& destinations) {
+}
 
 void FakeLocalFrameHost::SendPrivateAggregationRequestsForFencedFrameEvent(
     const WTF::String& event_type) {}
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.h b/third_party/blink/renderer/core/testing/fake_local_frame_host.h
index 2bd4768..88337c3 100644
--- a/third_party/blink/renderer/core/testing/fake_local_frame_host.h
+++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.h
@@ -175,10 +175,11 @@
   void SendFencedFrameReportingBeacon(
       const WTF::String& event_data,
       const WTF::String& event_type,
-      blink::FencedFrame::ReportingDestination destination) override;
+      const WTF::Vector<blink::FencedFrame::ReportingDestination>& destinations)
+      override;
   void SetFencedFrameAutomaticBeaconReportEventData(
       const WTF::String& event_data,
-      const WTF::Vector<blink::FencedFrame::ReportingDestination>& destination)
+      const WTF::Vector<blink::FencedFrame::ReportingDestination>& destinations)
       override;
   void SendPrivateAggregationRequestsForFencedFrameEvent(
       const WTF::String& event_type) override;
diff --git a/third_party/blink/renderer/modules/ad_auction/auction_ad_config.idl b/third_party/blink/renderer/modules/ad_auction/auction_ad_config.idl
index 036b03e..29e8c458 100644
--- a/third_party/blink/renderer/modules/ad_auction/auction_ad_config.idl
+++ b/third_party/blink/renderer/modules/ad_auction/auction_ad_config.idl
@@ -53,6 +53,8 @@
   record<DOMString, AuctionReportBuyersConfig> auctionReportBuyers;
   sequence<DOMString> requiredSellerCapabilities;
 
+  AuctionAdInterestGroupSize requestedSize;
+
   sequence<AuctionAdConfig> componentAuctions;
   AbortSignal? signal;
   boolean resolveToConfig;
diff --git a/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc b/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
index 091bb41..5a38044 100644
--- a/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
+++ b/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
@@ -1776,6 +1776,47 @@
   return true;
 }
 
+bool CopyRequestedSizeFromIdlToMojo(const ExecutionContext& execution_context,
+                                    ExceptionState& exception_state,
+                                    const AuctionAdConfig& input,
+                                    mojom::blink::AuctionAdConfig& output) {
+  if (!input.hasRequestedSize()) {
+    return true;
+  }
+  auto [width_val, width_units] =
+      blink::ParseAdSizeString(input.requestedSize()->width().Ascii());
+  auto [height_val, height_units] =
+      blink::ParseAdSizeString(input.requestedSize()->height().Ascii());
+  if (width_units == blink::AdSize::LengthUnit::kInvalid) {
+    exception_state.ThrowTypeError(ErrorInvalidAuctionConfig(
+        input, "requestedSize width", input.requestedSize()->width(),
+        "must use units '', 'px', 'sw', or 'sh'."));
+    return false;
+  }
+  if (height_units == blink::AdSize::LengthUnit::kInvalid) {
+    exception_state.ThrowTypeError(ErrorInvalidAuctionConfig(
+        input, "requestedSize height", input.requestedSize()->height(),
+        "must use units '', 'px', 'sw', or 'sh'."));
+    return false;
+  }
+  if (width_val <= 0 || !std::isfinite(width_val)) {
+    exception_state.ThrowTypeError(ErrorInvalidAuctionConfig(
+        input, "requestedSize width", input.requestedSize()->width(),
+        "must be finite and positive."));
+    return false;
+  }
+  if (height_val <= 0 || !std::isfinite(height_val)) {
+    exception_state.ThrowTypeError(ErrorInvalidAuctionConfig(
+        input, "requestedSize height", input.requestedSize()->height(),
+        "must be finite and positive."));
+    return false;
+  }
+  output.auction_ad_config_non_shared_params->requested_size =
+      mojom::blink::AdSize::New(width_val, width_units, height_val,
+                                height_units);
+  return true;
+}
+
 // Attempts to convert the AuctionAdConfig `config`, passed in via Javascript,
 // to a `mojom::blink::AuctionAdConfig`. Throws a Javascript exception and
 // return null on failure. `auction_handle` is used for promise handling;
@@ -1839,7 +1880,9 @@
       !CopyAuctionReportBuyersFromIdlToMojo(exception_state, config,
                                             *mojo_config) ||
       !CopyRequiredSellerSignalsFromIdlToMojo(context, exception_state, config,
-                                              *mojo_config)) {
+                                              *mojo_config) ||
+      !CopyRequestedSizeFromIdlToMojo(context, exception_state, config,
+                                      *mojo_config)) {
     return mojom::blink::AuctionAdConfigPtr();
   }
 
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
index e394aab9..96ed5e259 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -2059,9 +2059,7 @@
   if (num_readbacks_performed_ == 2 && GetCanvasRenderingContextHost() &&
       GetCanvasRenderingContextHost()->RenderingContext()) {
     if (will_read_frequently_value == CanvasContextCreationAttributesCore::
-                                          WillReadFrequently::kUndefined ||
-        will_read_frequently_value ==
-            CanvasContextCreationAttributesCore::WillReadFrequently::kFalse) {
+                                          WillReadFrequently::kUndefined) {
       const String& message =
           "Canvas2D: Multiple readback operations using getImageData are "
           "faster with the willReadFrequently attribute set to true. See: "
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
index 9761daaa..3f792f2 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
@@ -16,7 +16,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
@@ -55,6 +54,8 @@
 #include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
+#include "third_party/blink/renderer/platform/scheduler/public/main_thread_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
@@ -1484,9 +1485,9 @@
       mojom::blink::PageVisibilityState::kHidden,
       /*is_initial_state=*/false);
   // Run hibernation task.
-  scheduler::RunIdleTasksForTesting(
-      scheduler::WebThreadScheduler::MainThreadScheduler(),
-      WTF::BindOnce([]() {}));
+  ThreadScheduler::Current()
+      ->ToMainThreadScheduler()
+      ->StartIdlePeriodForTesting();
   blink::test::RunPendingTasks();
   // If enabled, hibernation should cause repaint of the painting layer.
   EXPECT_FALSE(box->NeedsPaintPropertyUpdate());
@@ -1536,9 +1537,9 @@
       mojom::blink::PageVisibilityState::kHidden,
       /*is_initial_state=*/false);
   // Run hibernation task.
-  scheduler::RunIdleTasksForTesting(
-      scheduler::WebThreadScheduler::MainThreadScheduler(),
-      WTF::BindOnce([]() {}));
+  ThreadScheduler::Current()
+      ->ToMainThreadScheduler()
+      ->StartIdlePeriodForTesting();
   blink::test::RunPendingTasks();
 
   // Never hibernate a canvas with no resource provider.
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc b/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc
index f565fa3..947f8ad3 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc
@@ -144,6 +144,8 @@
       ExecutionContextLifecycleObserver(execution_context),
       registration_id_(info.registration_id),
       scope_(std::move(info.scope)),
+      host_(execution_context),
+      receiver_(this, execution_context),
       stopped_(false) {
   DCHECK_NE(mojom::blink::kInvalidServiceWorkerRegistrationId,
             registration_id_);
@@ -157,6 +159,8 @@
       ExecutionContextLifecycleObserver(execution_context),
       registration_id_(info->registration_id),
       scope_(std::move(info->scope)),
+      host_(execution_context),
+      receiver_(this, execution_context),
       stopped_(false) {
   DCHECK_NE(mojom::blink::kInvalidServiceWorkerRegistrationId,
             registration_id_);
@@ -184,7 +188,7 @@
 
   // If |host_| is bound, it already points to the same object host as
   // |info.host_remote|, so there is no need to bind again.
-  if (!host_) {
+  if (!host_.is_bound()) {
     host_.Bind(std::move(info.host_remote),
                GetExecutionContext()->GetTaskRunner(
                    blink::TaskType::kInternalDefault));
@@ -239,6 +243,9 @@
 void ServiceWorkerRegistration::EnableNavigationPreload(
     bool enable,
     ScriptPromiseResolver* resolver) {
+  if (!host_.is_bound()) {
+    return;
+  }
   host_->EnableNavigationPreload(
       enable,
       WTF::BindOnce(&DidEnableNavigationPreload, WrapPersistent(resolver)));
@@ -246,6 +253,9 @@
 
 void ServiceWorkerRegistration::GetNavigationPreloadState(
     ScriptPromiseResolver* resolver) {
+  if (!host_.is_bound()) {
+    return;
+  }
   host_->GetNavigationPreloadState(
       WTF::BindOnce(&DidGetNavigationPreloadState, WrapPersistent(resolver)));
 }
@@ -253,6 +263,9 @@
 void ServiceWorkerRegistration::SetNavigationPreloadHeader(
     const String& value,
     ScriptPromiseResolver* resolver) {
+  if (!host_.is_bound()) {
+    return;
+  }
   host_->SetNavigationPreloadHeader(
       value,
       WTF::BindOnce(&DidSetNavigationPreloadHeader, WrapPersistent(resolver)));
@@ -343,6 +356,8 @@
   visitor->Trace(waiting_);
   visitor->Trace(active_);
   visitor->Trace(navigation_preload_);
+  visitor->Trace(host_);
+  visitor->Trace(receiver_);
   EventTargetWithInlineData::Trace(visitor);
   ExecutionContextLifecycleObserver::Trace(visitor);
   Supplementable<ServiceWorkerRegistration>::Trace(visitor);
@@ -389,8 +404,9 @@
 void ServiceWorkerRegistration::UpdateInternal(
     mojom::blink::FetchClientSettingsObjectPtr mojom_settings_object,
     ScriptPromiseResolver* resolver) {
-  if (!host_)
+  if (!host_.is_bound()) {
     return;
+  }
   host_->Update(std::move(mojom_settings_object),
                 WTF::BindOnce(&DidUpdate, WrapPersistent(resolver),
                               WrapPersistent(this)));
@@ -398,8 +414,9 @@
 
 void ServiceWorkerRegistration::UnregisterInternal(
     ScriptPromiseResolver* resolver) {
-  if (!host_)
+  if (!host_.is_bound()) {
     return;
+  }
   host_->Unregister(WTF::BindOnce(&DidUnregister, WrapPersistent(resolver)));
 }
 
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_registration.h b/third_party/blink/renderer/modules/service_worker/service_worker_registration.h
index 5d6f355e..5cb38a7 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_registration.h
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_registration.h
@@ -6,8 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_H_
 
 #include <memory>
-#include "mojo/public/cpp/bindings/associated_receiver.h"
-#include "mojo/public/cpp/bindings/associated_remote.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-blink.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration_object_info.h"
 #include "third_party/blink/public/platform/web_vector.h"
@@ -18,6 +16,8 @@
 #include "third_party/blink/renderer/modules/service_worker/navigation_preload_manager.h"
 #include "third_party/blink/renderer/modules/service_worker/service_worker.h"
 #include "third_party/blink/renderer/platform/heap/prefinalizer.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/gc_plugin.h"
@@ -131,16 +131,15 @@
   // to the Mojo connection. It is bound on the
   // main thread for service worker clients (document), and is bound on the
   // service worker thread for service worker execution contexts.
-  GC_PLUGIN_IGNORE("https://crbug.com/1381979")
-  mojo::AssociatedRemote<mojom::blink::ServiceWorkerRegistrationObjectHost>
+  HeapMojoAssociatedRemote<mojom::blink::ServiceWorkerRegistrationObjectHost>
       host_;
   // |receiver_| receives messages from the ServiceWorkerRegistrationObjectHost
   // in the browser process. It is bound on the main thread for service worker
   // clients (document), and is bound on the service worker thread for service
   // worker execution contexts.
-  GC_PLUGIN_IGNORE("https://crbug.com/1381979")
-  mojo::AssociatedReceiver<mojom::blink::ServiceWorkerRegistrationObject>
-      receiver_{this};
+  HeapMojoAssociatedReceiver<mojom::blink::ServiceWorkerRegistrationObject,
+                             ServiceWorkerRegistration>
+      receiver_;
 
   bool stopped_;
 };
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
index a5dfb2d..36054ac4 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -60,8 +60,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/renderer/platform/graphics/canvas_resource_host.h"
 #include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
 #include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
@@ -70,6 +68,7 @@
 #include "third_party/blink/renderer/platform/graphics/test/gpu_memory_buffer_test_platform.h"
 #include "third_party/blink/renderer/platform/graphics/test/gpu_test_utils.h"
 #include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
+#include "third_party/blink/renderer/platform/scheduler/public/main_thread_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -494,9 +493,9 @@
   EXPECT_CALL(*mock_logger_ptr, DidStartHibernating()).Times(1);
 
   bridge->SetIsInHiddenPage(true);
-  scheduler::RunIdleTasksForTesting(
-      scheduler::WebThreadScheduler::MainThreadScheduler(),
-      base::BindOnce([]() {}));
+  ThreadScheduler::Current()
+      ->ToMainThreadScheduler()
+      ->StartIdlePeriodForTesting();
   platform->RunUntilIdle();
 
   testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
@@ -541,9 +540,9 @@
   // chance to run.
   bridge->SetIsInHiddenPage(false);
   bridge->SetIsInHiddenPage(true);
-  scheduler::RunIdleTasksForTesting(
-      scheduler::WebThreadScheduler::MainThreadScheduler(),
-      base::BindOnce([]() {}));
+  ThreadScheduler::Current()
+      ->ToMainThreadScheduler()
+      ->StartIdlePeriodForTesting();
   platform->RunUntilIdle();
 
   testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
@@ -584,9 +583,9 @@
       ReportHibernationEvent(Canvas2DLayerBridge::kHibernationScheduled));
   EXPECT_CALL(*mock_logger_ptr, DidStartHibernating()).Times(1);
   bridge->SetIsInHiddenPage(true);
-  scheduler::RunIdleTasksForTesting(
-      scheduler::WebThreadScheduler::MainThreadScheduler(),
-      base::BindOnce([]() {}));
+  ThreadScheduler::Current()
+      ->ToMainThreadScheduler()
+      ->StartIdlePeriodForTesting();
   platform->RunUntilIdle();
   testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
   EXPECT_FALSE(bridge->IsAccelerated());
@@ -621,9 +620,9 @@
       ReportHibernationEvent(Canvas2DLayerBridge::kHibernationScheduled));
   EXPECT_CALL(*mock_logger_ptr, DidStartHibernating()).Times(1);
   bridge->SetIsInHiddenPage(true);
-  scheduler::RunIdleTasksForTesting(
-      scheduler::WebThreadScheduler::MainThreadScheduler(),
-      base::BindOnce([]() {}));
+  ThreadScheduler::Current()
+      ->ToMainThreadScheduler()
+      ->StartIdlePeriodForTesting();
   platform->RunUntilIdle();
   testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
   EXPECT_FALSE(bridge->IsAccelerated());
@@ -673,9 +672,9 @@
   // HibernationAbortedDueToDestructionWhileHibernatePending event to be
   // fired, but that signal is lost in the unit test due to no longer having
   // a bridge to hold the mockLogger.
-  scheduler::RunIdleTasksForTesting(
-      scheduler::WebThreadScheduler::MainThreadScheduler(),
-      base::BindOnce([]() {}));
+  ThreadScheduler::Current()
+      ->ToMainThreadScheduler()
+      ->StartIdlePeriodForTesting();
   platform->RunUntilIdle();
   // This test passes by not crashing, which proves that the WeakPtr logic
   // is sound.
@@ -706,9 +705,9 @@
       .Times(1);
   bridge->SetIsInHiddenPage(true);
   bridge->SetIsInHiddenPage(false);
-  scheduler::RunIdleTasksForTesting(
-      scheduler::WebThreadScheduler::MainThreadScheduler(),
-      base::BindOnce([]() {}));
+  ThreadScheduler::Current()
+      ->ToMainThreadScheduler()
+      ->StartIdlePeriodForTesting();
   platform->RunUntilIdle();
   testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
   EXPECT_TRUE(bridge->IsAccelerated());
@@ -742,9 +741,9 @@
       .Times(1);
 
   bridge->SetIsInHiddenPage(true);
-  scheduler::RunIdleTasksForTesting(
-      scheduler::WebThreadScheduler::MainThreadScheduler(),
-      base::BindOnce([]() {}));
+  ThreadScheduler::Current()
+      ->ToMainThreadScheduler()
+      ->StartIdlePeriodForTesting();
   platform->RunUntilIdle();
   testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
   EXPECT_FALSE(bridge->IsHibernating());
@@ -770,9 +769,9 @@
       ReportHibernationEvent(Canvas2DLayerBridge::kHibernationScheduled));
   EXPECT_CALL(*mock_logger_ptr, DidStartHibernating()).Times(1);
   bridge->SetIsInHiddenPage(true);
-  scheduler::RunIdleTasksForTesting(
-      scheduler::WebThreadScheduler::MainThreadScheduler(),
-      base::BindOnce([]() {}));
+  ThreadScheduler::Current()
+      ->ToMainThreadScheduler()
+      ->StartIdlePeriodForTesting();
   platform->RunUntilIdle();
   testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
 
@@ -1107,9 +1106,9 @@
   bridge->SetIsInHiddenPage(hidden);
   // Make sure that idle tasks run when hidden.
   if (hidden) {
-    scheduler::RunIdleTasksForTesting(
-        scheduler::WebThreadScheduler::MainThreadScheduler(),
-        base::DoNothing());
+    ThreadScheduler::Current()
+        ->ToMainThreadScheduler()
+        ->StartIdlePeriodForTesting();
     platform->RunUntilIdle();
     EXPECT_TRUE(bridge->IsHibernating());
   }
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.cc
index 1ce7df0..db165ee4 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.cc
@@ -104,7 +104,7 @@
   code_cache_host->get()->DidGenerateCacheableMetadataInCacheStorage(
       response_url_, response_time_,
       mojo_base::BigBuffer(base::make_span(data, size)),
-      WebSecurityOrigin(security_origin_), cache_storage_cache_name_);
+      cache_storage_cache_name_);
 }
 
 // static
@@ -113,7 +113,6 @@
     mojom::blink::CodeCacheType code_cache_type,
     WTF::String url,
     base::Time response_time,
-    scoped_refptr<const SecurityOrigin> origin,
     const String& cache_storage_name,
     const uint8_t* data,
     size_t size) {
@@ -126,8 +125,7 @@
   } else {
     code_cache_host->get()->DidGenerateCacheableMetadataInCacheStorage(
         KURL(url), response_time,
-        mojo_base::BigBuffer(base::make_span(data, size)),
-        WebSecurityOrigin(origin), cache_storage_name);
+        mojo_base::BigBuffer(base::make_span(data, size)), cache_storage_name);
   }
 }
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h
index fe4c531..32754f9 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h
@@ -43,7 +43,6 @@
                                   mojom::blink::CodeCacheType,
                                   WTF::String,
                                   base::Time,
-                                  scoped_refptr<const SecurityOrigin>,
                                   const String&,
                                   const uint8_t*,
                                   size_t);
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
index 7d7aee6..9523830 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
@@ -68,7 +68,6 @@
       const KURL& url,
       base::Time expected_response_time,
       mojo_base::BigBuffer data,
-      const scoped_refptr<const SecurityOrigin>& cache_storage_origin,
       const String& cache_storage_cache_name) override {
     sim_->CacheMetadataInCacheStorage(url);
   }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 95731b68..a1df8b75 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -721,7 +721,7 @@
       // Additionally, animation-delay becomes a shorthand which expands
       // to those properties.
       name: "CSSAnimationDelayStartEnd",
-      depends_on: ["CSSScrollTimeline"],
+      depends_on: ["ScrollTimeline"],
       status: "test",
     },
     {
@@ -1046,14 +1046,6 @@
       status: "test",
       base_feature: "none",
     },
-    // Support for scroll-timeline.
-    //
-    // https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-shorthand
-    {
-      name: "CSSScrollTimeline",
-      status: "experimental",
-      base_feature: "none",
-    },
     {
       name: "CSSSelectorFragmentAnchor",
       status: "experimental",
@@ -1183,14 +1175,6 @@
       status: "stable",
       base_feature: "none",
     },
-    // Support for view-timeline.
-    //
-    // https://drafts.csswg.org/scroll-animations-1/#view-timeline-shorthand
-    {
-      name: "CSSViewTimeline",
-      status: "experimental",
-      base_feature: "none",
-    },
     // `white-space` as a shorthand. crbug.com/1417543
     {
       name: "CSSWhiteSpaceShorthand",
@@ -3014,7 +2998,7 @@
     {
       name: "ScrollTimeline",
       status: "experimental",
-      implied_by: ["AnimationWorklet", "CSSScrollTimeline", "CSSViewTimeline"],
+      implied_by: ["AnimationWorklet"],
       base_feature: "none",
     },
     // Implements documentElement.scrollTop/Left and bodyElement.scrollTop/Left
diff --git a/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc b/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
index 7154cdc..55aa661 100644
--- a/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
@@ -295,6 +295,8 @@
     return isolate_;
   }
 
+  void StartIdlePeriodForTesting() override {}
+
  private:
   v8::Isolate* isolate_ = nullptr;
 };
diff --git a/third_party/blink/renderer/platform/scheduler/common/simple_main_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/common/simple_main_thread_scheduler.cc
index 0d368fd..1821c6d 100644
--- a/third_party/blink/renderer/platform/scheduler/common/simple_main_thread_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/simple_main_thread_scheduler.cc
@@ -90,4 +90,6 @@
   return isolate_;
 }
 
+void SimpleMainThreadScheduler::StartIdlePeriodForTesting() {}
+
 }  // namespace blink::scheduler
diff --git a/third_party/blink/renderer/platform/scheduler/common/simple_main_thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/common/simple_main_thread_scheduler.h
index 9a52b120..f88e43d4 100644
--- a/third_party/blink/renderer/platform/scheduler/common/simple_main_thread_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/common/simple_main_thread_scheduler.h
@@ -78,6 +78,9 @@
   v8::Isolate* Isolate() override;
   std::unique_ptr<RendererPauseHandle> PauseScheduler() override;
 
+  // Idle tasks are dropped in `PostIdleTask()` and friends, so this is a no-op.
+  void StartIdlePeriodForTesting() override;
+
  private:
   v8::Isolate* isolate_ = nullptr;
 };
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index 4f9bb64..5a41f4a 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -1082,11 +1082,9 @@
 }
 
 void MainThreadSchedulerImpl::EndIdlePeriodForTesting(
-    base::OnceClosure callback,
     base::TimeTicks time_remaining) {
   main_thread_only().in_idle_period_for_testing = false;
   EndIdlePeriod();
-  std::move(callback).Run();
 }
 
 bool MainThreadSchedulerImpl::PolicyNeedsUpdateForTesting() {
@@ -1401,13 +1399,12 @@
   return idle_helper_.CurrentIdleTaskDeadline();
 }
 
-void MainThreadSchedulerImpl::RunIdleTasksForTesting(
-    base::OnceClosure callback) {
+void MainThreadSchedulerImpl::StartIdlePeriodForTesting() {
   main_thread_only().in_idle_period_for_testing = true;
   IdleTaskRunner()->PostIdleTask(
       FROM_HERE,
       base::BindOnce(&MainThreadSchedulerImpl::EndIdlePeriodForTesting,
-                     weak_factory_.GetWeakPtr(), std::move(callback)));
+                     weak_factory_.GetWeakPtr()));
   idle_helper_.EnableLongIdlePeriod();
 }
 
@@ -2709,6 +2706,16 @@
   return true;
 }
 
+TaskAttributionTracker* MainThreadSchedulerImpl::GetTaskAttributionTracker() {
+  return main_thread_only().task_attribution_tracker.get();
+}
+
+void MainThreadSchedulerImpl::InitializeTaskAttributionTracker(
+    std::unique_ptr<TaskAttributionTracker> tracker) {
+  DCHECK(!main_thread_only().task_attribution_tracker);
+  main_thread_only().task_attribution_tracker = std::move(tracker);
+}
+
 // static
 const char* MainThreadSchedulerImpl::UseCaseToString(UseCase use_case) {
   switch (use_case) {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
index 8c77ac66..dfb1107f4 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -138,36 +138,38 @@
   ~MainThreadSchedulerImpl() override;
 
   // WebThreadScheduler implementation:
+  scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
+  scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner()
+      override;
   std::unique_ptr<MainThread> CreateMainThread() override;
   std::unique_ptr<WebAgentGroupScheduler> CreateWebAgentGroupScheduler()
       override;
-  // Note: this is also shared by the ThreadScheduler interface.
-  scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override;
-  scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner()
-      override;
   void SetRendererHidden(bool hidden) override;
   void SetRendererBackgrounded(bool backgrounded) override;
 #if BUILDFLAG(IS_ANDROID)
   void PauseTimersForAndroidWebView() override;
   void ResumeTimersForAndroidWebView() override;
 #endif
-  bool ShouldYieldForHighPriorityWork() override;
-  void AddTaskObserver(base::TaskObserver* task_observer) override;
-  void RemoveTaskObserver(base::TaskObserver* task_observer) override;
-  void Shutdown() override;
-  void AddRAILModeObserver(RAILModeObserver* observer) override;
-  void RemoveRAILModeObserver(RAILModeObserver const* observer) override;
   void SetRendererProcessType(WebRendererProcessType type) override;
-  Vector<WebInputEventAttribution> GetPendingUserInputInfo(
-      bool include_continuous) const override;
-  blink::MainThreadScheduler* ToMainThreadScheduler() override;
+
+  // WebThreadScheduler and ThreadScheduler implementation:
+  void Shutdown() override;
 
   // MainThreadScheduler implementation:
+  scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override;
   [[nodiscard]] std::unique_ptr<MainThreadScheduler::RendererPauseHandle>
   PauseScheduler() override;
   v8::Isolate* Isolate() override;
+  AgentGroupScheduler* CreateAgentGroupScheduler() override;
+  AgentGroupScheduler* GetCurrentAgentGroupScheduler() override;
+  void AddRAILModeObserver(RAILModeObserver* observer) override;
+  void RemoveRAILModeObserver(RAILModeObserver const* observer) override;
+  Vector<WebInputEventAttribution> GetPendingUserInputInfo(
+      bool include_continuous) const override;
+  void StartIdlePeriodForTesting() override;
 
   // ThreadScheduler implementation:
+  bool ShouldYieldForHighPriorityWork() override;
   void PostIdleTask(const base::Location&, Thread::IdleTask) override;
   void PostNonNestableIdleTask(const base::Location&,
                                Thread::IdleTask) override;
@@ -176,11 +178,24 @@
                            Thread::IdleTask) override;
   scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override;
   scoped_refptr<base::SingleThreadTaskRunner> CleanupTaskRunner() override;
-  scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
-  AgentGroupScheduler* CreateAgentGroupScheduler() override;
-  AgentGroupScheduler* GetCurrentAgentGroupScheduler() override;
-  void SetV8Isolate(v8::Isolate* isolate) override;
   base::TimeTicks MonotonicallyIncreasingVirtualTime() override;
+  void AddTaskObserver(base::TaskObserver* task_observer) override;
+  void RemoveTaskObserver(base::TaskObserver* task_observer) override;
+  void SetV8Isolate(v8::Isolate* isolate) override;
+  TaskAttributionTracker* GetTaskAttributionTracker() override;
+  void InitializeTaskAttributionTracker(
+      std::unique_ptr<TaskAttributionTracker> tracker) override;
+  blink::MainThreadScheduler* ToMainThreadScheduler() override;
+
+  // ThreadSchedulerBase implementation:
+  scoped_refptr<base::SingleThreadTaskRunner> ControlTaskRunner() override;
+  const base::TickClock* GetTickClock() const override;
+  MainThreadSchedulerHelper& GetHelper() override { return helper_; }
+
+  // RenderWidgetSignals::Observer implementation:
+  void SetAllRenderWidgetsHidden(bool hidden) override;
+  void SetHasVisibleRenderWidgetWithTouchHandler(
+      bool has_visible_render_widget_with_touch_handler) override;
 
   scoped_refptr<WidgetScheduler> CreateWidgetScheduler();
   void WillBeginFrame(const viz::BeginFrameArgs& args);
@@ -216,37 +231,9 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner();
 
-  // The following functions are defined in both WebThreadScheduler and
-  // ThreadScheduler, and have the same function signatures -- see above.
-  // This class implements those functions for both base classes.
-  //
-  // void Shutdown() override;
-  //
-  // TODO(yutak): Reduce the overlaps and simplify.
-
-  // RenderWidgetSignals::Observer implementation:
-  void SetAllRenderWidgetsHidden(bool hidden) override;
-  void SetHasVisibleRenderWidgetWithTouchHandler(
-      bool has_visible_render_widget_with_touch_handler) override;
-
-  // ThreadSchedulerImpl implementation:
-  scoped_refptr<base::SingleThreadTaskRunner> ControlTaskRunner() override;
-  const base::TickClock* GetTickClock() const override;
-  MainThreadSchedulerHelper& GetHelper() override { return helper_; }
-
   scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner();
   base::TimeTicks NowTicks() const;
 
-  TaskAttributionTracker* GetTaskAttributionTracker() override {
-    return main_thread_only().task_attribution_tracker.get();
-  }
-
-  void InitializeTaskAttributionTracker(
-      std::unique_ptr<TaskAttributionTracker> tracker) override {
-    DCHECK(!main_thread_only().task_attribution_tracker);
-    main_thread_only().task_attribution_tracker = std::move(tracker);
-  }
-
   // Returns a new task queue created with given params.
   scoped_refptr<MainThreadTaskQueue> NewTaskQueue(
       const MainThreadTaskQueue::QueueCreationParams& params);
@@ -300,9 +287,7 @@
   MainThreadSchedulerHelper* GetSchedulerHelperForTesting();
   IdleTimeEstimator* GetIdleTimeEstimatorForTesting();
   base::TimeTicks CurrentIdleTaskDeadlineForTesting() const;
-  void RunIdleTasksForTesting(base::OnceClosure callback);
-  void EndIdlePeriodForTesting(base::OnceClosure callback,
-                               base::TimeTicks time_remaining);
+  void EndIdlePeriodForTesting(base::TimeTicks time_remaining);
   bool PolicyNeedsUpdateForTesting();
 
   std::unique_ptr<CPUTimeBudgetPool> CreateCPUTimeBudgetPoolForTesting(
@@ -356,7 +341,7 @@
   }
 
  protected:
-  // ThreadSchedulerImpl implementation:
+  // ThreadSchedulerBase implementation:
   WTF::Vector<base::OnceClosure>& GetOnTaskCompletionCallbacks() override;
 
   scoped_refptr<MainThreadTaskQueue> ControlTaskQueue();
diff --git a/third_party/blink/renderer/platform/scheduler/public/main_thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/main_thread_scheduler.h
index aeccd281..643f430 100644
--- a/third_party/blink/renderer/platform/scheduler/public/main_thread_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/public/main_thread_scheduler.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/functional/callback_forward.h"
 #include "base/task/single_thread_task_runner.h"
 #include "third_party/blink/public/common/input/web_input_event_attribution.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
@@ -70,6 +71,15 @@
     return {};
   }
 
+  // Test helpers
+
+  // Starts an idle period, allowing pending idle tasks to run. Idle tasks can
+  // only run within an idle period, which is determined based on compositor
+  // signals. This method enables idle tasks to run in tests outside of a
+  // detected idle period. The idle period ends once all idle tasks scheduled
+  // before this method was called have run.
+  virtual void StartIdlePeriodForTesting() = 0;
+
  private:
   // For `ToWebMainThreadScheduler`.
   friend class scheduler::WebThreadScheduler;
diff --git a/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc b/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc
index 319d186..5672b36 100644
--- a/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc
+++ b/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc
@@ -46,13 +46,6 @@
   return std::make_unique<SimpleMockMainThreadScheduler>();
 }
 
-void RunIdleTasksForTesting(WebThreadScheduler& scheduler,
-                            base::OnceClosure callback) {
-  MainThreadSchedulerImpl* scheduler_impl =
-      static_cast<MainThreadSchedulerImpl*>(&scheduler);
-  scheduler_impl->RunIdleTasksForTesting(std::move(callback));
-}
-
 scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunnerForTesting() {
   return base::SequencedTaskRunner::GetCurrentDefault();
 }
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 6b451b9e1..00b5dea 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2939,6 +2939,9 @@
 crbug.com/626703 external/wpt/css/css-multicol/file-control-crash.html [ Crash ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001.html [ Failure ]
+crbug.com/626703 [ Linux ] virtual/threaded/external/wpt/css/css-transforms/individual-transform/animation/individual-transform-ordering.html [ Failure ]
+crbug.com/626703 [ Mac12 ] virtual/threaded/external/wpt/css/css-transforms/individual-transform/animation/individual-transform-ordering.html [ Failure ]
 crbug.com/626703 virtual/fenced-frame-mparch/wpt_internal/fenced_frame/unfenced-top.https.html [ Skip Timeout ]
 crbug.com/626703 [ Win11 ] external/wpt/fetch/api/body/mime-type.any.worker.html [ Failure Timeout ]
 crbug.com/626703 [ Linux ] virtual/fenced-frame-mparch/external/wpt/html/anonymous-iframe/web-lock.tentative.https.window.html [ Timeout ]
@@ -3989,7 +3992,6 @@
 crbug.com/814585 [ Linux ] fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk.html [ Failure Pass ]
 
 # Sheriff failures 2018-02-22
-crbug.com/814889 idle-callback/test-runner-run-idle-tasks.html [ Crash Pass Timeout ]
 crbug.com/814953 fast/replaced/no-focus-ring-iframe.html [ Failure Pass ]
 crbug.com/814964 virtual/gpu-rasterization/images/yuv-decode-eligible/color-profile-border-radius.html [ Failure Pass ]
 
@@ -6139,8 +6141,6 @@
 crbug.com/1392781 [ Win ] http/tests/fetch/serviceworker/thorough/cookie-base-https-other-https.html [ Crash Failure Pass Timeout ]
 crbug.com/1392781 [ Win ] http/tests/fetch/window/thorough/auth-base-https-other-https.html [ Crash Failure Pass Timeout ]
 crbug.com/1375147 [ Win ] virtual/media-foundation-for-clear-dcomp/media/controls/singletap-on-overlay-closes-overflow-menu.html [ Failure ]
-# TODO(crbug.com/1394559): Re-enable this test
-crbug.com/1394559 virtual/fenced-frame-mparch/external/wpt/fenced-frame/unfenced-top.https.html [ Failure ]
 crbug.com/1395120 [ Mac11-arm64 ] fast/frames/sandboxed-iframe-plugins.html [ Failure ]
 crbug.com/1396079 [ Mac ] inspector-protocol/memory/forcibly-purge-javascript-memory.js [ Crash Failure ]
 crbug.com/1395840 [ Mac10.15 Release ] http/tests/accessibility/slow-document-load.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index fa72d43e..da6dc0e 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -141779,6 +141779,21 @@
         {}
        ]
       ]
+     },
+     "text-box-trim": {
+      "text-box-trim-half-leading-inline-box-001.html": [
+       "4316301bd1bff7e58862700c6b7511914d14d21f",
+       [
+        null,
+        [
+         [
+          "/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ]
      }
     },
     "css-layout-api": {
@@ -270081,11 +270096,11 @@
   "support": {
    ".cache": {
     "gitignore2.json": [
-     "2ad079ea1bbedfaa41e9d38a31e6e06cbc59b0b3",
+     "b6c6723d74a09940f307aad5bbfaf6b0edb6ed1d",
      []
     ],
     "mtime.json": [
-     "511d51003e6d595a1b207d02e8897149734895a4",
+     "df3af1930a36eb92e19135aeaf121f5d55a6220b",
      []
     ]
    },
@@ -285153,7 +285168,7 @@
      ],
      "mix-blend-mode": {
       "mix-blend-mode-animation.html.ini": [
-       "38a37baa050c2767293e2bcda497ad6b8bf22abb",
+       "d1016bd6de1d1046970b5ccf84776df0fa026dc9",
        []
       ],
       "mix-blend-mode-blended-element-overflow-scroll.html.ini": [
@@ -289364,11 +289379,11 @@
       []
      ],
      "import-conditions-expected.txt": [
-      "cdcdc59bba332c229c883a9461e6bce7ca0fa372",
+      "41edfce511dcb37f82353965c567782fc69942c8",
       []
      ],
      "import-conditions.html.ini": [
-      "5fe16a522e9d0df2672ec4d1b99c99bb08f64e6d",
+      "0803ac9d3b96f1dacb9671642bd59c60d0beec06",
       []
      ],
      "important-prop-ref.html": [
@@ -307406,6 +307421,16 @@
        "e731bc3dfb5e6c5a4e89bcd443729069936545cd",
        []
       ]
+     },
+     "text-box-trim": {
+      "text-box-trim-half-leading-inline-box-001-ref.html": [
+       "4824309291df136db30d79b4a9dddc115f48b117",
+       []
+      ],
+      "text-box-trim-half-leading-inline-box-001.html.ini": [
+       "8cf8c09698c9bb5e5335e29c4038394136beb29a",
+       []
+      ]
      }
     },
     "css-layout-api": {
@@ -308675,7 +308700,7 @@
        []
       ],
       "clip-path-filter-order.html.ini": [
-       "89641752a57a657adbcb0e5995559f949a2c1554",
+       "e376dae045e67471da622f7876f2f40c7aa5bd37",
        []
       ],
       "clip-path-fixed-nested-ref.html": [
@@ -316489,6 +316514,10 @@
       "a329e3b09595074f066a04f873920f82073c4b84",
       []
      ],
+     "min-content-negative-margin-crash.html.ini": [
+      "4b10df0223c3040ef26aa6cb11a12189e5ade033",
+      []
+     ],
      "nested-flexbox-image-percentage-max-height-computes-as-none-ref.html": [
       "6a290b23a80155f7989c148a3cca4a68df51012e",
       []
@@ -326908,6 +326937,10 @@
        "a99265efc1f46bdb74c46fab4e8aeaae7f49ad78",
        []
       ],
+      "kind-of-widget-fallback-input-reset-border-bottom-style-001.html.ini": [
+       "db28982f742486b0488287998c23342e2f3b557a",
+       []
+      ],
       "kind-of-widget-fallback-input-reset-border-end-end-radius-001.html.ini": [
        "0d57390a693bd6e3996478bca6da9c10e6b64d75",
        []
@@ -327180,12 +327213,16 @@
        "0a103751c35f49aefdaf0284d14ae70ecf9c3907",
        []
       ],
+      "kind-of-widget-fallback-input-submit-border-image-outset-001.html.ini": [
+       "e15d63511d3c68f7c6bf64d1675f8fe559e5cfb9",
+       []
+      ],
       "kind-of-widget-fallback-input-submit-border-image-repeat-001.html.ini": [
        "8231ecbb222b79927cb28b3b18a1a29ed1bff0b5",
        []
       ],
       "kind-of-widget-fallback-input-submit-border-image-slice-001.html.ini": [
-       "0c26f7d54b41705a6994f5d340ea8c490861273b",
+       "0657ff19abb69b9c13e25f146ebc33b0c1ccdc26",
        []
       ],
       "kind-of-widget-fallback-input-submit-border-image-source-001.html.ini": [
@@ -327704,7 +327741,7 @@
       []
      ],
      "outline-027.html.ini": [
-      "1ffe61f735d5d4c6efe39284c5517cff89b20b04",
+      "149e9affa3f9fecd02beab8f160d22c00d4930b2",
       []
      ],
      "outline-auto-dynamic-change-ref.html": [
@@ -334226,7 +334263,7 @@
       []
      ],
      "backdrop-filters-brightness.html.ini": [
-      "3fb8d11144d59cc6c49d68d17a101d7dd7931582",
+      "f370173739f059320d7dac71d68b93278922f9e8",
       []
      ],
      "backdrop-filters-contrast-ref.html": [
@@ -342555,6 +342592,22 @@
       "1b63235b7cdffe9ebb43bfac3a01d5220e1519fb",
       []
      ],
+     "default-enabled-features-subframe-fencedframe.https.html": [
+      "e0987365285b72889ac8d51a842d0eb5d7b3436d",
+      []
+     ],
+     "default-enabled-features-subframe-fencedframe.https.html.headers": [
+      "e52511f18abb8f8321895170f94d7a52ac49a108",
+      []
+     ],
+     "default-enabled-features-subframe-iframe.https.html": [
+      "a3ab056944dac17db17126ff04993b79c7113071",
+      []
+     ],
+     "default-enabled-features-subframe-iframe.https.html.headers": [
+      "6247f6d63211cd39dffca9fc507aefcdee586eba",
+      []
+     ],
      "download-helper.js": [
       "011d5c867f86f5a839de6d9ded45e498f5b589e8",
       []
@@ -362470,7 +362523,7 @@
         ]
        },
        "text-plain.window.js.ini": [
-        "367ff8954751da7da33e8ae1d2de5f268d3507bd",
+        "df58d5551529362f6621ea7a92a73dfe7901942f",
         []
        ],
        "urlencoded2.window.js.ini": [
@@ -392051,6 +392104,10 @@
       "0a16a392a2613129aa07950c9344517abbfbca22",
       []
      ],
+     "021.html.ini": [
+      "df8ef43ccfb465108a1afdb72b2dbf3279ac7032",
+      []
+     ],
      "025-1.js": [
       "bd1d778d9b32651b05f1b7364459ed4096646528",
       []
@@ -438530,7 +438587,7 @@
       ]
      ],
      "import-conditions.html": [
-      "e5e1c685a9e214af6f0cd4a9eefa4f67056665e8",
+      "9c1e5c6e8768eecc881414c281fec2b971fb84d9",
       [
        null,
        {}
@@ -493359,6 +493416,13 @@
       {}
      ]
     ],
+    "default-enabled-features-subframe.https.html": [
+     "a86a02b00a83ac8e04665b7deaacbd01c70ba531",
+     [
+      null,
+      {}
+     ]
+    ],
     "default-enabled-features-unset.https.html": [
      "0e9c300bdcb95f24bd11cabe5db6e4b13f458eac",
      [
@@ -552381,6 +552445,13 @@
         {}
        ]
       ],
+      "popover-dialog-initial-focus.html": [
+       "47b2252bf5f26bc5bd122b9e57035992da65855a",
+       [
+        null,
+        {}
+       ]
+      ],
       "popover-document-open.html": [
        "80ac86acedab246d5ceff8b54d57feb7e957d642",
        [
@@ -673596,7 +673667,7 @@
      },
      "back": {
       "back.py": [
-       "62434323e0ad5339a861d0752d29f7d1f95c81cc",
+       "21e8498ccd57da9b101055f39fedab02ef2f2fcb",
        [
         null,
         {}
@@ -673732,7 +673803,7 @@
        ]
       ],
       "navigate.py": [
-       "492718292a178e5bfe242d75acad4b6efc3cbf71",
+       "bada57942b4807e4b151f80514bf8598ac359262",
        [
         null,
         {}
@@ -674038,7 +674109,7 @@
      },
      "forward": {
       "forward.py": [
-       "f27be403f9e95bd2359d5ae6224f6ae2708ff7c8",
+       "61c66e201b9e9898cec78c86c37fbf894b48c457",
        [
         null,
         {}
@@ -674520,7 +674591,7 @@
        ]
       ],
       "navigate.py": [
-       "d61377af275902c48083d3d84b35c3bba30bc34e",
+       "a367fc105e126aba603a2c426f2bfe823ccad950",
        [
         null,
         {}
diff --git a/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-animation.html.ini b/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-animation.html.ini
index 38a37baa..d1016bd 100644
--- a/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-animation.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-animation.html.ini
@@ -1,5 +1,6 @@
 [mix-blend-mode-animation.html]
   expected:
+    if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions-expected.txt
index cdcdc59..41edfce5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions-expected.txt
@@ -20,5 +20,7 @@
 FAIL supports(font-format(opentype)) is a valid import condition assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
 FAIL supports(font-format(woff)) is a valid import condition assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
 PASS supports(font-format(invalid)) is not a valid import condition
+FAIL layer(A.B) supports(font-format(opentype)) is a valid import condition assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
+FAIL layer supports(selector(a)) is a valid import condition assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions.html b/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions.html
index e5e1c685..9c1e5c6 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions.html
@@ -4,7 +4,9 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <style>
-  .target { color: red; }
+  @layer {
+    .target { color: red; }
+  }
 </style>
 <div id="target" class="target"></div>
 <script>
@@ -99,6 +101,14 @@
       importCondition: "supports(font-format(invalid))",
       matches: false
     },
+    {
+      importCondition: "layer(A.B) supports(font-format(opentype))",
+      matches: true
+    },
+    {
+      importCondition: "layer supports(selector(a))",
+      matches: true
+    },
   ];
   let target = document.getElementById("target");
   for (let testCase of testCases) {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions.html.ini b/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions.html.ini
index 5fe16a5..0803ac9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/import-conditions.html.ini
@@ -1,4 +1,10 @@
 [import-conditions.html]
+  [layer supports(selector(a)) is a valid import condition]
+    expected: FAIL
+
+  [layer(A.B) supports(font-format(opentype)) is a valid import condition]
+    expected: FAIL
+
   [supports((display:block) and (display:flex)) is a valid import condition]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/style-container-for-shadow-dom.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/style-container-for-shadow-dom.html
new file mode 100644
index 0000000..c3ac961d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/style-container-for-shadow-dom.html
@@ -0,0 +1,271 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Container Queries Test: style query container for Shadow DOM</title>
+<link rel="help" href="https://drafts.csswg.org/css-contain-3/#query-container">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/declarative-shadow-dom-polyfill.js"></script>
+<script src="support/cq-testcommon.js"></script>
+
+<div id="inclusive-ancestor-across-root">
+  <div style="--foo: bar">
+    <template shadowrootmode="open">
+      <style>
+        @container style(--foo: bar) {
+          #t1 { color: green; }
+        }
+      </style>
+      <div id="t1"></div>
+    </template>
+  </div>
+</div>
+
+<div id="inclusive-ancestor-skip-slotting">
+  <div style="--foo: bar">
+    <template shadowrootmode="open">
+      <div style="--foo: baz">
+        <slot></slot>
+      </div>
+    </template>
+    <style>
+      @container style(--foo: bar) {
+        #t2 { color: green; }
+      }
+    </style>
+    <div id="t2"></div>
+  </div>
+</div>
+
+<div id="inclusive-ancestor-slotted">
+  <div style="--foo: baz">
+    <template shadowrootmode="open">
+      <style>
+        @container style(--foo: bar) {
+          ::slotted(#t3) { color: green; }
+        }
+      </style>
+      <slot style="--foo: bar"></slot>
+    </template>
+    <div id="t3"></div>
+  </div>
+</div>
+
+<div id="inclusive-ancestor-host" style="--foo: bar">
+  <div id="t4">
+    <template shadowrootmode="open">
+      <style>
+        @container style(--foo: bar) {
+          :host(#t4) { color: green; }
+        }
+      </style>
+    </template>
+  </div>
+</div>
+
+<div id="inclusive-ancestor-part">
+  <div style="--foo: bar">
+    <template shadowrootmode="open">
+      <div style="--foo: baz">
+        <span id="t5" part="part"></span>
+      </div>
+    </template>
+    <style>
+      @container style(--foo: bar) {
+        #inclusive-ancestor-part > div::part(part) { color: green; }
+      }
+    </style>
+  </div>
+</div>
+
+<div id="inclusive-ancestor-slotted-before">
+  <div>
+    <template shadowrootmode="open">
+      <style>
+        @container style(--foo: bar) {
+          ::slotted(#t6)::before {
+            content: "X";
+            color: green;
+          }
+        }
+      </style>
+      <slot style="--foo: bar"></slot>
+    </template>
+    <div id="t6" style="--foo: baz"></div>
+  </div>
+</div>
+
+<div id="inclusive-ancestor-host-before">
+  <div id="t7" style="--foo: bar">
+    <template shadowrootmode="open">
+      <style>
+        @container style(--foo: bar) {
+          :host(#t7)::before {
+            content: "X";
+            color: green;
+          }
+        }
+      </style>
+    </template>
+  </div>
+</div>
+
+<div id="inclusive-ancestor-part-before">
+  <style>
+    @container style(--foo: bar) {
+      #inclusive-ancestor-part-before > div::part(part)::before {
+        content: "X";
+        color: green;
+      }
+    }
+  </style>
+  <div style="--foo: bar">
+    <template shadowrootmode="open">
+      <div style="--foo: baz">
+        <span id="t8" part="part"></span>
+      </div>
+    </template>
+  </div>
+</div>
+
+<div id="inclusive-ancestor-inner-part">
+  <style>
+    @container style(--foo: bar) {
+      #inclusive-ancestor-inner-part > div::part(inner-part) { color: green; }
+    }
+  </style>
+  <div style="--foo: bar">
+    <template shadowrootmode="open">
+      <div exportparts="inner-part" style="-foo: baz">
+        <template shadowrootmode="open">
+          <style>
+            div {
+              width: 200px;
+              container-type: inline-size;
+            }
+          </style>
+          <div style="--foo: baz">
+            <span id="t9" part="inner-part"></span>
+          </div>
+        </template>
+      </div>
+    </template>
+  </div>
+</div>
+
+<div id="inclusive-ancestor-slot-fallback">
+  <div><template shadowrootmode="open">
+    <style>
+      @container style(--foo: bar) {
+        #t10 { color: green; }
+      }
+    </style>
+    <div>
+      <slot style="--foo: bar"><span id="t10"></span></slot>
+    </div>
+  </template></div>
+</div>
+
+<div id="no-container-for-part">
+  <div>
+    <template shadowrootmode="open">
+      <style>
+        #t11 { color: green; }
+      </style>
+      <div style="--foo: bar">
+        <span id="t11" part="part"></span>
+      </div>
+    </template>
+    <style>
+      @container style(--foo: bar) {
+        #no-container-for-part > div::part(part) { color: red; }
+      }
+    </style>
+  </div>
+</div>
+
+<div id="inner-scope-host-part" style="--foo: bar">
+  <div>
+    <template shadowrootmode="open">
+      <style>
+        @container style(--foo: bar) {
+          :host::part(part) { color: green; }
+        }
+      </style>
+      <div style="--foo: baz">
+        <span id="t12" part="part"></span>
+      </div>
+    </template>
+  </div>
+</div>
+
+<script>
+  setup(() => {
+    assert_implements_container_queries();
+    polyfill_declarative_shadow_dom(document);
+  });
+
+  const green = "rgb(0, 128, 0)";
+
+  test(() => {
+    const t1 = document.querySelector("#inclusive-ancestor-across-root > div").shadowRoot.querySelector("#t1");
+    assert_equals(getComputedStyle(t1).color, green);
+  }, "Match container in outer tree");
+
+  test(() => {
+    const t2 = document.querySelector("#t2");
+    assert_equals(getComputedStyle(t2).color, green);
+  }, "Match container in same tree, not walking flat tree ancestors");
+
+  test(() => {
+    const t3 = document.querySelector("#t3");
+    assert_equals(getComputedStyle(t3).color, green);
+  }, "Match container in ::slotted selector's originating element tree");
+
+  test(() => {
+    const t4 = document.querySelector("#t4");
+    assert_equals(getComputedStyle(t4).color, green);
+  }, "Match container in outer tree for :host");
+
+  test(() => {
+    const t5 = document.querySelector("#inclusive-ancestor-part > div").shadowRoot.querySelector("#t5");
+    assert_equals(getComputedStyle(t5).color, green);
+  }, "Match container in ::part selector's originating element tree");
+
+  test(() => {
+    const t6 = document.querySelector("#t6");
+    assert_equals(getComputedStyle(t6, "::before").color, green);
+  }, "Match container for ::before in ::slotted selector's originating element tree");
+
+  test(() => {
+    const t7 = document.querySelector("#t7");
+    assert_equals(getComputedStyle(t7, "::before").color, green);
+  }, "Match container in outer tree for :host::before");
+
+  test(() => {
+    const t8 = document.querySelector("#inclusive-ancestor-part-before > div").shadowRoot.querySelector("#t8");
+    assert_equals(getComputedStyle(t8, "::before").color, green);
+  }, "Match container for ::before in ::part selector's originating element tree");
+
+  test(() => {
+    const outerhost = document.querySelector("#inclusive-ancestor-inner-part > div");
+    const innerhost = outerhost.shadowRoot.querySelector("div");
+    const t9 = innerhost.shadowRoot.querySelector("#t9");
+    assert_equals(getComputedStyle(t9).color, green);
+  }, "Match container for ::part selector's originating element tree for exportparts");
+
+  test(() => {
+    const t10 = document.querySelector("#inclusive-ancestor-slot-fallback > div").shadowRoot.querySelector("#t10");
+    assert_equals(getComputedStyle(t10).color, green);
+  }, "Match container for slot light tree child fallback");
+
+  test(() => {
+    const t11 = document.querySelector("#no-container-for-part > div").shadowRoot.querySelector("#t11");
+    assert_equals(getComputedStyle(t11).color, green);
+  }, "Should not match container inside shadow tree for ::part()");
+
+  test(() => {
+    const t12 = document.querySelector("#inner-scope-host-part > div").shadowRoot.querySelector("#t12");
+    assert_equals(getComputedStyle(t12).color, green);
+  }, "A :host::part rule should match containers in the originating element tree");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/crashtests/contain-nested-crash-004.html b/third_party/blink/web_tests/external/wpt/css/css-contain/crashtests/contain-nested-crash-004.html
new file mode 100644
index 0000000..db29e14
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/crashtests/contain-nested-crash-004.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1439692">
+<style>
+body, fieldset { contain: strict; }
+</style>
+<script>
+function crash() {
+  document.body.offsetTop;
+  document.body.appendChild(document.createElement("fieldset"));
+}
+</script>
+<body onload="crash()">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001-ref.html
new file mode 100644
index 0000000..4824309
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Reference for trimming inline boxes</title>
+<link rel="help" href="https://drafts.csswg.org/css-inline-3/#leading-trim">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+
+<style>
+div {
+  border: 1px solid orange;
+  font-size: 20px;
+  line-height: 1;
+}
+
+span {
+  border: 1px solid blue;
+  font-family: Ahem;
+  font-size: 20px;
+  line-height: 1;
+  text-box-trim: both;
+}
+</style>
+
+<div>
+  <span>Test</span>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001.html b/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001.html
new file mode 100644
index 0000000..4316301b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Tests inline boxes are trimmed at text-over/text-under baselines</title>
+<link rel="help" href="https://drafts.csswg.org/css-inline-3/#leading-trim">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<link rel="match" href="text-box-trim-half-leading-inline-box-001-ref.html">
+
+<style>
+div {
+  border: 1px solid orange;
+  font-size: 20px;
+  line-height: 1;
+}
+
+span {
+  border: 1px solid blue;
+  font-family: Ahem;
+  font-size: 20px;
+  line-height: 3;
+  text-box-trim: both;
+}
+</style>
+
+<div>
+  <span>Test</span>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001.html.ini
new file mode 100644
index 0000000..8cf8c096
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001.html.ini
@@ -0,0 +1,2 @@
+[text-box-trim-half-leading-inline-box-001.html]
+  expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-filter-order.html.ini b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-filter-order.html.ini
index 89641752..e376dae 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-filter-order.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-filter-order.html.ini
@@ -1,6 +1,7 @@
 [clip-path-filter-order.html]
   expected:
-    if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
-    if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+    if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+    if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
+    if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/min-content-negative-margin-crash.html.ini b/third_party/blink/web_tests/external/wpt/css/css-sizing/min-content-negative-margin-crash.html.ini
new file mode 100644
index 0000000..4b10df0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/min-content-negative-margin-crash.html.ini
@@ -0,0 +1,3 @@
+[min-content-negative-margin-crash.html]
+  expected:
+    if (product == "content_shell") and (os == "mac") and (port == "mac11"): TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-reset-border-bottom-style-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-reset-border-bottom-style-001.html.ini
new file mode 100644
index 0000000..db28982
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-reset-border-bottom-style-001.html.ini
@@ -0,0 +1,3 @@
+[kind-of-widget-fallback-input-reset-border-bottom-style-001.html]
+  expected:
+    if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-image-outset-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-image-outset-001.html.ini
new file mode 100644
index 0000000..e15d635
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-image-outset-001.html.ini
@@ -0,0 +1,3 @@
+[kind-of-widget-fallback-input-submit-border-image-outset-001.html]
+  expected:
+    if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-image-slice-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-image-slice-001.html.ini
index 0c26f7d5..0657ff1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-image-slice-001.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-image-slice-001.html.ini
@@ -1,3 +1,4 @@
 [kind-of-widget-fallback-input-submit-border-image-slice-001.html]
   expected:
+    if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
     if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/outline-027.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/outline-027.html.ini
index 1ffe61f..149e9af 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ui/outline-027.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/outline-027.html.ini
@@ -1,4 +1,4 @@
 [outline-027.html]
   expected:
-    if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): FAIL
+    if (product == "content_shell") and (os == "win"): FAIL
     if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness.html.ini b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness.html.ini
index 3fb8d11..f370173 100644
--- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness.html.ini
@@ -1,4 +1,5 @@
 [backdrop-filters-brightness.html]
   expected:
-    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+    if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fledge-container-size-mutation-observer.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fledge-container-size-mutation-observer.https.html
new file mode 100644
index 0000000..b6085afc
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fledge-container-size-mutation-observer.https.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<title>Test that mutation observer doesn't break noassert container size setter.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="resources/utils.js"></script>
+
+<body>
+<script>
+
+async function checkMutationObserver() {
+  // Create a FLEDGE FF with a constant content size and given container size.
+  const requested_width_1 = '299px';
+  const requested_height_1 = '72px';
+  const frame = await attachFencedFrameContext({
+      generator_api: 'fledge', resolve_to_config: true, ad_with_size: true,
+      requested_size: [requested_width_1, requested_height_1]});
+
+  // Install a mutation observer.
+  const config = { attributes: true, childList: true, subtree: true };
+  const callback = (mutationList, observer) => {
+    throw new Error("mutation observed");
+  }
+  const observer = new MutationObserver(callback);
+  observer.observe(frame.element, config);
+
+  // Modify the container size manually.
+  const modified_width = '121px';
+  const modified_height = '444px';
+  frame.element.width = modified_width;
+  frame.element.height = modified_height;
+
+  // Navigate to a new FLEDGE FF config with a different container size.
+  const requested_width_2 = '321px';
+  const requested_height_2 = '49px';
+  const replaced_frame = await replaceFrameContext(frame, {
+      generator_api: 'fledge', resolve_to_config: true, ad_with_size: true,
+      requested_size: [requested_width_2, requested_height_2]});
+
+  observer.disconnect();
+}
+
+setup({allow_uncaught_exception: true});
+promise_test(async () => { return checkMutationObserver(); }, 'Container size assert no exception ignores mutation observer');
+
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fledge-container-size.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fledge-container-size.https.html
new file mode 100644
index 0000000..6f2c519d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fledge-container-size.https.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<title>Test container size in FLEDGE fenced frames.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="resources/utils.js"></script>
+
+<body>
+<script>
+async function checkSyntaxError(requested_width, requested_height) {
+  try {
+    const frame = await attachFencedFrameContext({
+        generator_api: "fledge", resolve_to_config: true, ad_with_size: true,
+        requested_size: [requested_width, requested_height]});
+  } catch(e) {
+    assert_equals(e.name, 'TypeError');
+    return;
+  }
+  assert_unreached('Missing expected type error');
+}
+
+async function checkSuccess() {
+  const assert_outer_dimensions =
+    (frame, label, expected_width, expected_height) => {
+    assert_equals(frame.element.width, expected_width,
+        label + ' outer attribute width');
+    assert_equals(frame.element.height, expected_height,
+        label + ' outer attribute height');
+    assert_equals(getComputedStyle(frame.element).width, expected_width,
+        label + ' outer computed width');
+    assert_equals(getComputedStyle(frame.element).height, expected_height,
+        label + ' outer computed height');
+  }
+
+  const assert_inner_dimensions =
+    (label, expected_width, expected_height) => {
+    assert_equals(getComputedStyle(document.documentElement).width, expected_width+'px',
+        label + ' inner computed width');
+    assert_equals(window.innerWidth, expected_width,
+        label + ' inner width');
+    assert_equals(window.innerHeight, expected_height,
+        label + ' inner height');
+  }
+
+  // `ad_with_size` is hardcoded to use '100px' by '50px'.
+  const content_width = 100;
+  const content_height = 50;
+
+  // Create a FLEDGE FF with a constant content size and given container size.
+  const requested_width_1 = '299px';
+  const requested_height_1 = '72px';
+  const frame = await attachFencedFrameContext({
+      generator_api: 'fledge', resolve_to_config: true, ad_with_size: true,
+      requested_size: [requested_width_1, requested_height_1]});
+
+  // The outer size should reflect the container size, and the inner size should reflect the content size.
+  await frame.execute(assert_inner_dimensions, ['First config', content_width, content_height]);
+  assert_outer_dimensions(frame, 'First config', requested_width_1, requested_height_1);
+
+  // Modify the container size manually.
+  const modified_width = '121px';
+  const modified_height = '444px';
+  frame.element.width = modified_width;
+  frame.element.height = modified_height;
+
+  // The outer size should reflect the new size, and the inner size should be unchanged.
+  await frame.execute(assert_inner_dimensions, ['Modified container size', content_width, content_height]);
+  assert_outer_dimensions(frame, 'Modified container size', modified_width, modified_height);
+
+  // Navigate to a new FLEDGE FF config with a different container size.
+  const requested_width_2 = '321px';
+  const requested_height_2 = '49px';
+  const replaced_frame = await replaceFrameContext(frame, {
+      generator_api: 'fledge', resolve_to_config: true, ad_with_size: true,
+      requested_size: [requested_width_2, requested_height_2]});
+
+  // The outer size should reflect the new size, and the inner size should be unchanged.
+  await replaced_frame.execute(assert_inner_dimensions, ['Second config', content_width, content_height]);
+  assert_outer_dimensions(replaced_frame, 'Second config', requested_width_2, requested_height_2);
+
+  // Navigate to a new FLEDGE FF config with no container size.
+  const replaced_frame_2 = await replaceFrameContext(frame, {
+      generator_api: 'fledge', resolve_to_config: true, ad_with_size: true});
+
+  // The dimensions should be unchanged.
+  await replaced_frame_2.execute(assert_inner_dimensions, ['Third config', content_width, content_height]);
+  assert_outer_dimensions(replaced_frame_2, 'Third config', requested_width_2, requested_height_2);
+}
+
+// Type error cases.
+promise_test(async () => { return checkSyntaxError('299', '72'); }, '299 x 72');
+promise_test(async () => { return checkSyntaxError('299px', '72'); }, '299px x 72');
+promise_test(async () => { return checkSyntaxError('299', '72px'); }, '299 x 72px');
+promise_test(async () => { return checkSyntaxError('-299px', '72px'); }, '-299px x 72px');
+promise_test(async () => { return checkSyntaxError('299px', '-72px'); }, '299px x -72px');
+promise_test(async () => { return checkSyntaxError('0px', '0px'); }, '0px x 0px');
+promise_test(async () => { return checkSyntaxError('299px', '72ab'); }, '299px x 72ab');
+promise_test(async () => { return checkSyntaxError('299bc', '72px'); }, '299bc x 72px');
+
+// Success cases.
+promise_test(async () => { return checkSuccess(); }, 'FLEDGE successful container size');
+
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/resources/utils.js b/third_party/blink/web_tests/external/wpt/fenced-frame/resources/utils.js
index d35855cb..2263fc1 100644
--- a/third_party/blink/web_tests/external/wpt/fenced-frame/resources/utils.js
+++ b/third_party/blink/web_tests/external/wpt/fenced-frame/resources/utils.js
@@ -70,7 +70,8 @@
 async function generateURNFromFledgeRawURL(href,
   nested_urls,
   resolve_to_config = false,
-  ad_with_size = false) {
+  ad_with_size = false,
+  requested_size = null) {
   const bidding_token = token();
   const seller_token = token();
 
@@ -106,13 +107,16 @@
   // ad interest group while the test runs.
   navigator.joinAdInterestGroup(interestGroup, /*durationSeconds=*/3000000);
 
-  const auctionConfig = {
+  let auctionConfig = {
     seller: location.origin,
     interestGroupBuyers: [location.origin],
     decisionLogicUrl: new URL(FLEDGE_DECISION_URL, location.origin),
     auctionSignals: {biddingToken: bidding_token, sellerToken: seller_token},
-    resolveToConfig: resolve_to_config,
+    resolveToConfig: resolve_to_config
   };
+  if (requested_size) {
+    auctionConfig['requestedSize'] = {width: requested_size[0], height: requested_size[1]};
+  }
   return navigator.runAdAuction(auctionConfig);
 }
 
@@ -133,9 +137,9 @@
 //                                                frame config.
 // @param {boolean} [ad_with_size = false] - Determines whether the auction is
 //                                           run with ad sizes specified.
-async function generateURNFromFledge(href, keylist, nested_urls=[], resolve_to_config = false, ad_with_size = false) {
+async function generateURNFromFledge(href, keylist, nested_urls=[], resolve_to_config = false, ad_with_size = false, requested_size = null) {
   const full_url = generateURL(href, keylist);
-  return generateURNFromFledgeRawURL(full_url, nested_urls, resolve_to_config, ad_with_size);
+  return generateURNFromFledgeRawURL(full_url, nested_urls, resolve_to_config, ad_with_size, requested_size);
 }
 
 // Extracts a list of UUIDs from the from the current page's URL.
@@ -240,23 +244,23 @@
 // function.
 // 1. crbug.com/1372536: resize-lock-input.https.html
 // 2. crbug.com/1394559: unfenced-top.https.html
-async function attachOpaqueContext(generator_api, resolve_to_config, ad_with_size, object_constructor, html, headers, origin) {
+async function attachOpaqueContext(generator_api, resolve_to_config, ad_with_size, requested_size, object_constructor, html, headers, origin) {
   const [uuid, url] = generateRemoteContextURL(headers, origin);
-  const id = await (generator_api == 'fledge' ? generateURNFromFledge(url, [], [], resolve_to_config, ad_with_size) : runSelectURL(url, [], resolve_to_config));
+  const id = await (generator_api == 'fledge' ? generateURNFromFledge(url, [], [], resolve_to_config, ad_with_size, requested_size) : runSelectURL(url, [], resolve_to_config));
   const object = object_constructor(id);
   return buildRemoteContextForObject(object, uuid, html);
 }
 
-function attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size, frame_constructor, html, headers, origin) {
+function attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size, requested_size, frame_constructor, html, headers, origin) {
   generator_api = generator_api.toLowerCase();
   if (generator_api == 'fledge' || generator_api == 'sharedstorage') {
-    return attachOpaqueContext(generator_api, resolve_to_config, ad_with_size, frame_constructor, html, headers, origin);
+    return attachOpaqueContext(generator_api, resolve_to_config, ad_with_size, requested_size, frame_constructor, html, headers, origin);
   } else {
     return attachContext(frame_constructor, html, headers, origin);
   }
 }
 
-function attachFrameContext(element_name, generator_api, resolve_to_config, ad_with_size, html, headers, attributes, origin) {
+function attachFrameContext(element_name, generator_api, resolve_to_config, ad_with_size, requested_size, html, headers, attributes, origin) {
   frame_constructor = (id) => {
     frame = document.createElement(element_name);
     attributes.forEach(attribute => {
@@ -273,10 +277,10 @@
     document.body.append(frame);
     return frame;
   };
-  return attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size, frame_constructor, html, headers, origin);
+  return attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size, requested_size, frame_constructor, html, headers, origin);
 }
 
-function replaceFrameContext(frame_proxy, {generator_api="", resolve_to_config=false, html="", headers=[], origin=""}={}) {
+function replaceFrameContext(frame_proxy, {generator_api="", resolve_to_config=false, ad_with_size=false, requested_size=null, html="", headers=[], origin=""}={}) {
   frame_constructor = (id) => {
     if (frame_proxy.element.nodeName == "IFRAME") {
       frame_proxy.element.src = id;
@@ -288,7 +292,7 @@
     }
     return frame_proxy.element;
   };
-  return attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size=false, frame_constructor, html, headers, origin);
+  return attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size, requested_size, frame_constructor, html, headers, origin);
 }
 
 // Attach a fenced frame that waits for scripts to execute.
@@ -301,20 +305,22 @@
 //    for FLEDGE and sharedStorage generator_api)
 // - ad_with_size: whether an ad auction is run with size specified for the ads
 //    and ad components. (currently only works for FLEDGE)
+// - requested_size: A 2-element list with the width and height for
+//    requestedSize in the FLEDGE auction config.
 // - html: extra HTML source code to inject into the loaded frame
 // - headers: an array of header pairs [[key, value], ...]
 // - attributes: an array of attribute pairs to set on the frame [[key, value], ...]
 // - origin: origin of the url, default to location.origin if not set
 // Returns a proxy that acts like the frame HTML element, but with an extra
 // function `execute`. See `attachFrameContext` or the README for more details.
-function attachFencedFrameContext({generator_api="", resolve_to_config=false, ad_with_size=false, html = "", headers=[], attributes=[], origin=""}={}) {
-  return attachFrameContext('fencedframe', generator_api, resolve_to_config, ad_with_size, html, headers, attributes, origin);
+function attachFencedFrameContext({generator_api="", resolve_to_config=false, ad_with_size=false, requested_size=null, html = "", headers=[], attributes=[], origin=""}={}) {
+  return attachFrameContext('fencedframe', generator_api, resolve_to_config, ad_with_size, requested_size, html, headers, attributes, origin);
 }
 
 // Attach an iframe that waits for scripts to execute.
 // See `attachFencedFrameContext` for more details.
 function attachIFrameContext({generator_api="", html="", headers=[], attributes=[], origin=""}={}) {
-  return attachFrameContext('iframe', generator_api, resolve_to_config=false, ad_with_size=false, html, headers, attributes, origin);
+  return attachFrameContext('iframe', generator_api, resolve_to_config=false, ad_with_size=false, requested_size=null, html, headers, attributes, origin);
 }
 
 // Open a window that waits for scripts to execute.
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/text-plain.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/text-plain.window.js.ini
index 367ff89..df58d555 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/text-plain.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/text-plain.window.js.ini
@@ -1,76 +1,3 @@
 [text-plain.window.html]
   expected:
-    if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): OK
-    if (product == "content_shell") and (os == "mac"): OK
-    [OK, TIMEOUT]
-  [text/plain: backslash in filename (formdata event)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: backslash in filename (normal form)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: backslash in name (formdata event)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: backslash in name (normal form)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: backslash in value (formdata event)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: backslash in value (normal form)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: character not in encoding in filename (formdata event)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: character not in encoding in filename (normal form)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: characters not in encoding in name and value (formdata event)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: characters not in encoding in name and value (normal form)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: non-ASCII in filename (formdata event)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: non-ASCII in filename (normal form)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: non-ASCII in name and value (formdata event)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: non-ASCII in name and value (normal form)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: single quote in filename (formdata event)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: single quote in filename (normal form)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: single quote in value (formdata event)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [text/plain: single quote in value (normal form)]
-    expected:
-      if product == "chrome": [PASS, TIMEOUT]
+    if (product == "content_shell") and (os == "mac") and (port == "mac11"): [TIMEOUT, OK]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-change-type.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-change-type.html
new file mode 100644
index 0000000..064a5b43
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-change-type.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://github.com/whatwg/html/issues/9034">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/html/semantics/popovers/resources/popover-utils.js"></script>
+
+<div id=mypopover>popover</div>
+
+<script>
+promise_test(async () => {
+  const mypopover = document.getElementById('mypopover');
+
+  mypopover.popover = "manual";
+  mypopover.showPopover();
+
+  await new Promise(resolve => {
+    mypopover.addEventListener("beforetoggle", (e) => {
+      if (e.newState === "closed") {
+        mypopover.remove();
+        requestAnimationFrame(() => {
+          document.body.append(mypopover);
+          mypopover.showPopover();
+          resolve();
+        });
+      }
+    }, {once: true});
+
+    mypopover.popover = "auto";
+  });
+
+  assert_true(mypopover.matches(':popover-open'),
+    'The popover should be open after the toggling sequence.');
+
+  await sendEscape(mypopover);
+  assert_false(mypopover.matches(':popover-open'),
+    'The popover should light dismiss because it is in the auto state.');
+}, 'Changing the popover attribute should always update the auto/manual behavior.');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js
index 04d2a2c..3f6835e 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js
@@ -29,9 +29,9 @@
 //     .send();
 //   await waitForRender();
 // }
-async function sendEscape() {
+async function sendEscape(element) {
   await waitForRender();
-  await new test_driver.send_keys(document.body,'\uE00C'); // Escape
+  await new test_driver.send_keys(element ? element : document.body,'\uE00C'); // Escape
   await waitForRender();
 }
 async function sendEnter() {
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/back/back.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/back/back.py
index 62434323..21e8498 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/back/back.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/back/back.py
@@ -164,6 +164,6 @@
 
     assert session.url == first_page
 
-    with pytest.raises(error.NoSuchElementException):
+    with pytest.raises(error.StaleElementReferenceException):
         elem.click()
     elem = session.find.css("#delete", all=False)
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/element_click/navigate.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/element_click/navigate.py
index 4927182..bada579 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/element_click/navigate.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/element_click/navigate.py
@@ -1,6 +1,5 @@
 import pytest
-
-from webdriver.error import NoSuchElementException
+from webdriver import error
 
 from tests.support.asserts import assert_success
 from tests.support.helpers import wait_for_new_handle
@@ -121,7 +120,7 @@
     wait = Poll(
         session,
         timeout=5,
-        ignored_exceptions=NoSuchElementException,
+        ignored_exceptions=error.NoSuchElementException,
         message="Expected element has not been found")
     wait.until(lambda s: s.find.css("#foo"))
 
@@ -160,7 +159,7 @@
     wait = Poll(
         session,
         timeout=5,
-        ignored_exceptions=NoSuchElementException,
+        ignored_exceptions=error.NoSuchElementException,
         message="Expected element has not been found")
     wait.until(lambda s: s.find.css("#foo"))
 
@@ -180,6 +179,8 @@
     assert_success(response)
 
     assert session.url == target_page
+    with pytest.raises(error.StaleElementReferenceException):
+        link.click()
 
     session.find.css("#delete", all=False)
 
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/forward/forward.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/forward/forward.py
index f27be403..61c66e2 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/forward/forward.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/forward/forward.py
@@ -190,6 +190,6 @@
 
     assert session.url == second_page
 
-    with pytest.raises(error.NoSuchElementException):
+    with pytest.raises(error.StaleElementReferenceException):
         elem.click()
     elem = session.find.css("#delete", all=False)
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/navigate_to/navigate.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/navigate_to/navigate.py
index d61377a..a367fc1 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/navigate_to/navigate.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/navigate_to/navigate.py
@@ -74,7 +74,7 @@
     assert_success(response)
 
     assert session.url == second_page
-    with pytest.raises(error.NoSuchElementException):
+    with pytest.raises(error.StaleElementReferenceException):
         elem.click()
 
     session.find.css("#delete", all=False)
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/without-ports/021.html.ini b/third_party/blink/web_tests/external/wpt/webmessaging/without-ports/021.html.ini
new file mode 100644
index 0000000..df8ef43c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webmessaging/without-ports/021.html.ini
@@ -0,0 +1,4 @@
+[021.html]
+  [cross-origin test]
+    expected:
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): [FAIL, PASS]
diff --git a/third_party/blink/web_tests/fast/canvas/multiple-readbacks-without-will-read-frequently-produces-warning-expected.txt b/third_party/blink/web_tests/fast/canvas/multiple-readbacks-without-will-read-frequently-produces-warning-expected.txt
index 3965e835..c0d7961 100644
--- a/third_party/blink/web_tests/fast/canvas/multiple-readbacks-without-will-read-frequently-produces-warning-expected.txt
+++ b/third_party/blink/web_tests/fast/canvas/multiple-readbacks-without-will-read-frequently-produces-warning-expected.txt
@@ -7,6 +7,8 @@
 Second pixel of canvas with willReadFrequently set to true: 0,0,0,0
 First pixel of canvas with willReadFrequently set to false: 255,0,255,255
 Second pixel of canvas with willReadFrequently set to false: 0,0,0,0
+First pixel of canvas with willReadFrequently not set: 255,0,255,255
+Second pixel of canvas with willReadFrequently not set: 0,0,0,0
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/blink/web_tests/fast/canvas/multiple-readbacks-without-will-read-frequently-produces-warning.html b/third_party/blink/web_tests/fast/canvas/multiple-readbacks-without-will-read-frequently-produces-warning.html
index f74be4d..58afc32 100644
--- a/third_party/blink/web_tests/fast/canvas/multiple-readbacks-without-will-read-frequently-produces-warning.html
+++ b/third_party/blink/web_tests/fast/canvas/multiple-readbacks-without-will-read-frequently-produces-warning.html
@@ -24,6 +24,15 @@
         debug(`First pixel of canvas with willReadFrequently set to false: ${pixel3}`);
         const pixel4 = nonWrfCtx.getImageData(20, 20, 1, 1).data;
         debug(`Second pixel of canvas with willReadFrequently set to false: ${pixel4}`);
+
+        const defWrfCanvas = document.createElement("canvas");
+        const defWrfCtx = defWrfCanvas.getContext("2d");
+        defWrfCtx.fillStyle = "magenta";
+        defWrfCtx.fillRect(0, 0, 10, 10);
+        const pixel5 = defWrfCtx.getImageData(0, 0, 1, 1).data;
+        debug(`First pixel of canvas with willReadFrequently not set: ${pixel5}`);
+        const pixel6 = defWrfCtx.getImageData(20, 20, 1, 1).data;
+        debug(`Second pixel of canvas with willReadFrequently not set: ${pixel6}`);
     </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/idle-callback/test-runner-run-idle-tasks-expected.txt b/third_party/blink/web_tests/idle-callback/test-runner-run-idle-tasks-expected.txt
deleted file mode 100644
index fcc243e..0000000
--- a/third_party/blink/web_tests/idle-callback/test-runner-run-idle-tasks-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Tests that testRunner.runIdleTasks will force idle tasks to run.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-PASS x is false
-PASS x is true
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-Hello, world!
diff --git a/third_party/blink/web_tests/idle-callback/test-runner-run-idle-tasks.html b/third_party/blink/web_tests/idle-callback/test-runner-run-idle-tasks.html
deleted file mode 100644
index d5a3683..0000000
--- a/third_party/blink/web_tests/idle-callback/test-runner-run-idle-tasks.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/js-test.js"></script>
-<div>Hello, world!</div>
-<script>
-description("Tests that testRunner.runIdleTasks will force idle tasks to run.");
-self.jsTestIsAsync = true;
-
-var x = false;
-
-function cb1(t) {
-  shouldBeFalse("x");
-  x = true;
-}
-
-function cb2(t) {
-  shouldBeTrue("x");
-  finishJSTest();
-}
-
-requestIdleCallback(cb1);
-if (self.testRunner)
-  testRunner.runIdleTasks(cb2);
-else
-  requestIdleCallback(cb2);
-</script>
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/webmessaging/postMessage_cross_domain_image_transfer_webgl.sub-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/webmessaging/postMessage_cross_domain_image_transfer_webgl.sub-expected.txt
new file mode 100644
index 0000000..dda9fad7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/webmessaging/postMessage_cross_domain_image_transfer_webgl.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught TypeError: Cannot read properties of null (reading 'viewport')
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/external/wpt/webmessaging/postMessage_cross_domain_image_transfer_webgl.sub-expected.txt b/third_party/blink/web_tests/platform/mac-mac12-arm64/external/wpt/webmessaging/postMessage_cross_domain_image_transfer_webgl.sub-expected.txt
new file mode 100644
index 0000000..dda9fad7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/external/wpt/webmessaging/postMessage_cross_domain_image_transfer_webgl.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught TypeError: Cannot read properties of null (reading 'viewport')
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/external/wpt/webmessaging/postMessage_cross_domain_image_transfer_webgl.sub-expected.txt b/third_party/blink/web_tests/platform/mac-mac13-arm64/external/wpt/webmessaging/postMessage_cross_domain_image_transfer_webgl.sub-expected.txt
new file mode 100644
index 0000000..dda9fad7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac13-arm64/external/wpt/webmessaging/postMessage_cross_domain_image_transfer_webgl.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught TypeError: Cannot read properties of null (reading 'viewport')
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-deduplication.sub.https.html b/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-deduplication.sub.https.html
index 8ed9e6e4..f45c310 100644
--- a/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-deduplication.sub.https.html
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-deduplication.sub.https.html
@@ -1,172 +1,97 @@
 <!doctype html>
 <meta charset=utf-8>
 <meta name=timeout content=long>
+<meta name="variant" content="?input=no_keys">
+<meta name="variant" content="?input=filters_match">
+<meta name="variant" content="?input=filters_not_match">
+<meta name="variant" content="?input=negated_filters_match">
+<meta name="variant" content="?input=negated_filters_not_match">
+<meta name="variant" content="?input=different_deduplication_key">
+<meta name="variant" content="?input=null_deduplication_key">
+<meta name="variant" content="?input=multiple_deduplication_keys">
 <script src="/resources/testdriver.js"></script>
 <script src="/resources/testdriver-vendor.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/helpers.js"></script>
 <script>
-const aggregatable_dedup_promise_test = (testCase) => {
-  attribution_reporting_promise_test(async t => {
-    const host = 'https://{{host}}';
+attribution_reporting_promise_test(async t => {
+  const searchParams = new URLSearchParams(location.search);
+  const input = searchParams.get('input');
+  const inputJSON =
+      await fetch(`resources/aggregatable_deduplication_keys/${input}.json`)
+                .then((response) => response.json());
 
-    const source = {
-      source_event_id: generateSourceEventId(),
-      destination: host,
-      aggregation_keys: {
-        campaignCounts: '0x159',
-      },
-      debug_key: '456',
-      debug_reporting: true,
-      filter_data: {
-        'x': ['y', 'z'],
-      }
-    };
-    await registerAttributionSrc({
-      source,
-      method: 'open',
-      cookie: attributionDebugCookie,
-    });
-    await waitForSourceToBeRegistered(source.source_event_id);
+  const host = 'https://{{host}}';
 
-    const trigger = {
-      aggregatable_trigger_data: [{
-        key_piece: '0x400',
-        source_keys: ['campaignCounts'],
-      }],
-      aggregatable_values: {
-        campaignCounts: 32768,
-      },
-      aggregatable_deduplication_keys: [{
-        'deduplication_key': '666',
-      }],
-      debug_reporting: true,
-    };
-
-    await registerAttributionSrc({
-      trigger,
-    });
-
-    const payload = await pollAggregatableReports();
-    assert_equals(payload.reports.length, 1);
-    const report = JSON.parse(payload.reports[0].body);
-    assert_own_property(report, 'shared_info');
-    const shared_info = JSON.parse(report.shared_info);
-    assert_equals(shared_info.attribution_destination, host);
-
-    trigger.aggregatable_deduplication_keys =
-        testCase.aggregatable_deduplication_keys;
-
-    await registerAttributionSrc({
-      trigger,
-      cookie: attributionDebugCookie,
-    });
-
-    if (testCase.expectDeduplicated) {
-      const debugPayload = await pollVerboseDebugReports();
-      assert_equals(debugPayload.reports.length, 1);
-      const debugReport = JSON.parse(debugPayload.reports[0].body);
-      assert_equals(debugReport.length, 1);
-      assert_equals(debugReport[0].type, 'trigger-aggregate-deduplicated');
-      assert_own_property(debugReport[0], 'body');
-      const debugReportBody = debugReport[0].body;
-      assert_equals(debugReportBody.attribution_destination, host);
-      assert_equals(debugReportBody.source_event_id, source.source_event_id);
-      assert_equals(debugReportBody.source_site, host);
-      assert_equals(debugReportBody.source_debug_key, '456');
-      assert_not_own_property(debugReportBody, 'trigger_debug_key');
-      return;
+  const source = {
+    source_event_id: generateSourceEventId(),
+    destination: host,
+    aggregation_keys: {
+      campaignCounts: '0x159',
+    },
+    debug_key: '456',
+    debug_reporting: true,
+    filter_data: {
+      'x': ['y', 'z'],
     }
+  };
+  await registerAttributionSrc({
+    source,
+    method: 'open',
+    cookie: attributionDebugCookie,
+  });
+  await waitForSourceToBeRegistered(source.source_event_id);
 
-    const payload2 = await pollAggregatableReports();
-    assert_equals(payload2.reports.length, 1);
-  }, testCase.testName);
-};
+  const trigger = {
+    aggregatable_trigger_data: [{
+      key_piece: '0x400',
+      source_keys: ['campaignCounts'],
+    }],
+    aggregatable_values: {
+      campaignCounts: 32768,
+    },
+    aggregatable_deduplication_keys: [{
+      'deduplication_key': '666',
+    }],
+    debug_reporting: true,
+  };
 
-[
-  {
-    testName: 'No deduplication key',
-    aggregatable_deduplication_keys: [],
-    expectDeduplicated: false,
-  },
-  {
-    testName: 'Filters match',
-    aggregatable_deduplication_keys: [
-      {
-        'deduplication_key': '666',
-        'filters': {'x': ['y']},
-      }
-    ],
-    expectDeduplicated: true,
-  },
-  {
-    testName: 'Filters does not match',
-    aggregatable_deduplication_keys: [
-      {
-        'deduplication_key': '666',
-        'filters': {'x': ['x']},
-      }
-    ],
-    expectDeduplicated: false,
-  },
-  {
-    testName: 'Negated filters match',
-    aggregatable_deduplication_keys: [
-      {
-        'deduplication_key': '666',
-        'not_filters': {'x': ['y']},
-      }
-    ],
-    expectDeduplicated: false,
-  },
-  {
-    testName: 'Negated filters does not match',
-    aggregatable_deduplication_keys: [
-      {
-        'deduplication_key': '666',
-        'not_filters': {'x': ['x']},
-      }
-    ],
-    expectDeduplicated: true,
-  },
-  {
-    testName: 'Different deduplication key',
-    aggregatable_deduplication_keys: [
-      {
-        'deduplication_key': '456',
-        'filters': {'x': ['y']}
-      }
-    ],
-    expectDeduplicated: false,
-  },
-  {
-    testName: 'Null deduplication key',
-    aggregatable_deduplication_keys: [
-      {
-        'filters': {'x': ['y']}
-      }
-    ],
-    expectDeduplicated: false,
-  },
-  {
-    testName: 'Multiple deduplication keys',
-    aggregatable_deduplication_keys: [
-      {
-        'deduplication_key': '555',
-        'filters': {'x': ['x']},
-      },
-      {
-        'deduplication_key': '666',
-        'filters': {'x': ['y']},
-      },
-      {
-        'deduplication_key': '777',
-        'filters': {'x': ['z']},
-      },
-    ],
-    expectDeduplicated: true,
-  },
-].forEach(aggregatable_dedup_promise_test);
+  await registerAttributionSrc({
+    trigger,
+  });
 
+  const payload = await pollAggregatableReports();
+  assert_equals(payload.reports.length, 1);
+  const report = JSON.parse(payload.reports[0].body);
+  assert_own_property(report, 'shared_info');
+  const shared_info = JSON.parse(report.shared_info);
+  assert_equals(shared_info.attribution_destination, host);
+
+  trigger.aggregatable_deduplication_keys = inputJSON.aggregatable_deduplication_keys;
+
+  await registerAttributionSrc({
+    trigger,
+    cookie: attributionDebugCookie,
+  });
+
+  if (inputJSON.expect_deduplicated) {
+    const debugPayload = await pollVerboseDebugReports();
+    assert_equals(debugPayload.reports.length, 1);
+    const debugReport = JSON.parse(debugPayload.reports[0].body);
+    assert_equals(debugReport.length, 1);
+    assert_equals(debugReport[0].type, 'trigger-aggregate-deduplicated');
+    assert_own_property(debugReport[0], 'body');
+    const debugReportBody = debugReport[0].body;
+    assert_equals(debugReportBody.attribution_destination, host);
+    assert_equals(debugReportBody.source_event_id, source.source_event_id);
+    assert_equals(debugReportBody.source_site, host);
+    assert_equals(debugReportBody.source_debug_key, '456');
+    assert_not_own_property(debugReportBody, 'trigger_debug_key');
+    return;
+  }
+
+  const payload2 = await pollAggregatableReports();
+  assert_equals(payload2.reports.length, 1);
+}, 'Aggregatable deduplication keys');
 </script>
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/different_deduplication_key.json b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/different_deduplication_key.json
new file mode 100644
index 0000000..04c64c3
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/different_deduplication_key.json
@@ -0,0 +1,11 @@
+{
+  "aggregatable_deduplication_keys": [
+    {
+      "deduplication_key": "456",
+      "filters": {
+        "x": ["y"]
+      }
+    }
+  ],
+  "expect_deduplicated": false
+}
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/filters_match.json b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/filters_match.json
new file mode 100644
index 0000000..a3608bf
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/filters_match.json
@@ -0,0 +1,11 @@
+{
+  "aggregatable_deduplication_keys": [
+    {
+      "deduplication_key": "666",
+      "filters": {
+        "x": ["y"]
+      }
+    }
+  ],
+  "expect_deduplicated": true
+}
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/filters_not_match.json b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/filters_not_match.json
new file mode 100644
index 0000000..899c33d
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/filters_not_match.json
@@ -0,0 +1,11 @@
+{
+  "aggregatable_deduplication_keys": [
+    {
+      "deduplication_key": "666",
+      "filters": {
+        "x": ["x"]
+      }
+    }
+  ],
+  "expect_deduplicated": false
+}
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/multiple_deduplication_keys.json b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/multiple_deduplication_keys.json
new file mode 100644
index 0000000..ca59cfd
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/multiple_deduplication_keys.json
@@ -0,0 +1,23 @@
+{
+  "aggregatable_deduplication_keys": [
+    {
+      "deduplication_key": "555",
+      "filters": {
+        "x": ["x"]
+      }
+    },
+    {
+      "deduplication_key": "666",
+      "filters": {
+          "x": ["y"]
+      }
+    },
+    {
+      "deduplication_key": "777",
+      "filters": {
+        "x": ["z"]
+      }
+    }
+  ],
+  "expect_deduplicated": true
+}
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/negated_filters_match.json b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/negated_filters_match.json
new file mode 100644
index 0000000..76e0188
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/negated_filters_match.json
@@ -0,0 +1,11 @@
+{
+  "aggregatable_deduplication_keys": [
+    {
+      "deduplication_key": "666",
+      "not_filters": {
+          "x": ["y"]
+      }
+    }
+  ],
+  "expect_deduplicated": false
+}
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/negated_filters_not_match.json b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/negated_filters_not_match.json
new file mode 100644
index 0000000..57a3aa1c
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/negated_filters_not_match.json
@@ -0,0 +1,11 @@
+{
+  "aggregatable_deduplication_keys": [
+    {
+      "deduplication_key": "666",
+      "not_filters": {
+          "x": ["x"]
+      }
+    }
+  ],
+  "expect_deduplicated": true
+}
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/no_keys.json b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/no_keys.json
new file mode 100644
index 0000000..19bc99bf
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/no_keys.json
@@ -0,0 +1,4 @@
+{
+  "aggregatable_deduplication_keys": [],
+  "expect_deduplicated": false
+}
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/null_deduplication_key.json b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/null_deduplication_key.json
new file mode 100644
index 0000000..8cf2ae6
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/aggregatable_deduplication_keys/null_deduplication_key.json
@@ -0,0 +1,10 @@
+{
+  "aggregatable_deduplication_keys": [
+    {
+      "filters": {
+        "x": ["y"]
+      }
+    }
+  ],
+  "expect_deduplicated": false
+}
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/utils.js b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/utils.js
index 4686272..19e60605 100644
--- a/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/utils.js
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/utils.js
@@ -70,7 +70,8 @@
 async function generateURNFromFledgeRawURL(href,
   nested_urls,
   resolve_to_config = false,
-  ad_with_size = false) {
+  ad_with_size = false,
+  requested_size = null) {
   const bidding_token = token();
   const seller_token = token();
 
@@ -106,13 +107,16 @@
   // ad interest group while the test runs.
   navigator.joinAdInterestGroup(interestGroup, /*durationSeconds=*/3000000);
 
-  const auctionConfig = {
+  let auctionConfig = {
     seller: location.origin,
     interestGroupBuyers: [location.origin],
     decisionLogicUrl: new URL(FLEDGE_DECISION_URL, location.origin),
     auctionSignals: {biddingToken: bidding_token, sellerToken: seller_token},
-    resolveToConfig: resolve_to_config,
+    resolveToConfig: resolve_to_config
   };
+  if (requested_size) {
+    auctionConfig['requestedSize'] = {width: requested_size[0], height: requested_size[1]};
+  }
   return navigator.runAdAuction(auctionConfig);
 }
 
@@ -133,9 +137,9 @@
 //                                                frame config.
 // @param {boolean} [ad_with_size = false] - Determines whether the auction is
 //                                           run with ad sizes specified.
-async function generateURNFromFledge(href, keylist, nested_urls=[], resolve_to_config = false, ad_with_size = false) {
+async function generateURNFromFledge(href, keylist, nested_urls=[], resolve_to_config = false, ad_with_size = false, requested_size = null) {
   const full_url = generateURL(href, keylist);
-  return generateURNFromFledgeRawURL(full_url, nested_urls, resolve_to_config, ad_with_size);
+  return generateURNFromFledgeRawURL(full_url, nested_urls, resolve_to_config, ad_with_size, requested_size);
 }
 
 // Extracts a list of UUIDs from the from the current page's URL.
@@ -240,23 +244,23 @@
 // function.
 // 1. crbug.com/1372536: resize-lock-input.https.html
 // 2. crbug.com/1394559: unfenced-top.https.html
-async function attachOpaqueContext(generator_api, resolve_to_config, ad_with_size, object_constructor, html, headers, origin) {
+async function attachOpaqueContext(generator_api, resolve_to_config, ad_with_size, requested_size, object_constructor, html, headers, origin) {
   const [uuid, url] = generateRemoteContextURL(headers, origin);
-  const id = await (generator_api == 'fledge' ? generateURNFromFledge(url, [], [], resolve_to_config, ad_with_size) : runSelectURL(url, [], resolve_to_config));
+  const id = await (generator_api == 'fledge' ? generateURNFromFledge(url, [], [], resolve_to_config, ad_with_size, requested_size) : runSelectURL(url, [], resolve_to_config));
   const object = object_constructor(id);
   return buildRemoteContextForObject(object, uuid, html);
 }
 
-function attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size, frame_constructor, html, headers, origin) {
+function attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size, requested_size, frame_constructor, html, headers, origin) {
   generator_api = generator_api.toLowerCase();
   if (generator_api == 'fledge' || generator_api == 'sharedstorage') {
-    return attachOpaqueContext(generator_api, resolve_to_config, ad_with_size, frame_constructor, html, headers, origin);
+    return attachOpaqueContext(generator_api, resolve_to_config, ad_with_size, requested_size, frame_constructor, html, headers, origin);
   } else {
     return attachContext(frame_constructor, html, headers, origin);
   }
 }
 
-function attachFrameContext(element_name, generator_api, resolve_to_config, ad_with_size, html, headers, attributes, origin) {
+function attachFrameContext(element_name, generator_api, resolve_to_config, ad_with_size, requested_size, html, headers, attributes, origin) {
   frame_constructor = (id) => {
     frame = document.createElement(element_name);
     attributes.forEach(attribute => {
@@ -273,10 +277,10 @@
     document.body.append(frame);
     return frame;
   };
-  return attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size, frame_constructor, html, headers, origin);
+  return attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size, requested_size, frame_constructor, html, headers, origin);
 }
 
-function replaceFrameContext(frame_proxy, {generator_api="", resolve_to_config=false, html="", headers=[], origin=""}={}) {
+function replaceFrameContext(frame_proxy, {generator_api="", resolve_to_config=false, ad_with_size=false, requested_size=null, html="", headers=[], origin=""}={}) {
   frame_constructor = (id) => {
     if (frame_proxy.element.nodeName == "IFRAME") {
       frame_proxy.element.src = id;
@@ -288,7 +292,7 @@
     }
     return frame_proxy.element;
   };
-  return attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size=false, frame_constructor, html, headers, origin);
+  return attachPotentiallyOpaqueContext(generator_api, resolve_to_config, ad_with_size, requested_size, frame_constructor, html, headers, origin);
 }
 
 // Attach a fenced frame that waits for scripts to execute.
@@ -301,20 +305,22 @@
 //    for FLEDGE and sharedStorage generator_api)
 // - ad_with_size: whether an ad auction is run with size specified for the ads
 //    and ad components. (currently only works for FLEDGE)
+// - requested_size: A 2-element list with the width and height for
+//    requestedSize in the FLEDGE auction config.
 // - html: extra HTML source code to inject into the loaded frame
 // - headers: an array of header pairs [[key, value], ...]
 // - attributes: an array of attribute pairs to set on the frame [[key, value], ...]
 // - origin: origin of the url, default to location.origin if not set
 // Returns a proxy that acts like the frame HTML element, but with an extra
 // function `execute`. See `attachFrameContext` or the README for more details.
-function attachFencedFrameContext({generator_api="", resolve_to_config=false, ad_with_size=false, html = "", headers=[], attributes=[], origin=""}={}) {
-  return attachFrameContext('fencedframe', generator_api, resolve_to_config, ad_with_size, html, headers, attributes, origin);
+function attachFencedFrameContext({generator_api="", resolve_to_config=false, ad_with_size=false, requested_size=null, html = "", headers=[], attributes=[], origin=""}={}) {
+  return attachFrameContext('fencedframe', generator_api, resolve_to_config, ad_with_size, requested_size, html, headers, attributes, origin);
 }
 
 // Attach an iframe that waits for scripts to execute.
 // See `attachFencedFrameContext` for more details.
 function attachIFrameContext({generator_api="", html="", headers=[], attributes=[], origin=""}={}) {
-  return attachFrameContext('iframe', generator_api, resolve_to_config=false, ad_with_size=false, html, headers, attributes, origin);
+  return attachFrameContext('iframe', generator_api, resolve_to_config=false, ad_with_size=false, requested_size=null, html, headers, attributes, origin);
 }
 
 // Open a window that waits for scripts to execute.
diff --git a/third_party/leveldatabase/README.chromium b/third_party/leveldatabase/README.chromium
index 9069527..21ad04c 100644
--- a/third_party/leveldatabase/README.chromium
+++ b/third_party/leveldatabase/README.chromium
@@ -29,3 +29,8 @@
 * leveldb_chrome::NewMemEnv() to create memory Env instances that are tracked to
   know if a database open request is in-memory. These memory Env instances report
   memory usage to memory-infra.
+* leveldb_chrome.cc and env_chromium.cc to use
+  base::SysInfo::IsLowEndDeviceOrPartialLowEndModeEnabled() instead of
+  base::SysUtils::IsLowEndDevice(). Will run an experiment with
+  PartialLowEndMode enabled on Android 4gb and 6gb devices to see how
+  memory performance and cpu performance will change.
diff --git a/third_party/leveldatabase/env_chromium.cc b/third_party/leveldatabase/env_chromium.cc
index 5ea8cc9..0d31cc65 100644
--- a/third_party/leveldatabase/env_chromium.cc
+++ b/third_party/leveldatabase/env_chromium.cc
@@ -472,7 +472,7 @@
   // memory buffer which won't be written until it hits the maximum size
   // (leveldb::Options::write_buffer_size - 4MB by default). The downside here
   // is that databases opens take longer as the open is blocked on compaction.
-  reuse_logs = !base::SysInfo::IsLowEndDevice();
+  reuse_logs = !base::SysInfo::IsLowEndDeviceOrPartialLowEndModeEnabled();
 #endif
   // By default use a single shared block cache to conserve memory. The owner of
   // this object can create their own, or set to NULL to have leveldb create a
diff --git a/third_party/leveldatabase/leveldb_chrome.cc b/third_party/leveldatabase/leveldb_chrome.cc
index 27b3fa5..36f7082b 100644
--- a/third_party/leveldatabase/leveldb_chrome.cc
+++ b/third_party/leveldatabase/leveldb_chrome.cc
@@ -40,10 +40,11 @@
 namespace {
 
 size_t DefaultBlockCacheSize() {
-  if (base::SysInfo::IsLowEndDevice())
+  if (base::SysInfo::IsLowEndDeviceOrPartialLowEndModeEnabled()) {
     return 1 << 20;  // 1MB
-  else
+  } else {
     return 8 << 20;  // 8MB
+  }
 }
 
 std::string GetDumpNameForMemEnv(const leveldb::Env* memenv) {
@@ -60,9 +61,10 @@
   }
 
   Globals()
-      : web_block_cache_(base::SysInfo::IsLowEndDevice()
-                             ? nullptr
-                             : NewLRUCache(DefaultBlockCacheSize())),
+      : web_block_cache_(
+            base::SysInfo::IsLowEndDeviceOrPartialLowEndModeEnabled()
+                ? nullptr
+                : NewLRUCache(DefaultBlockCacheSize())),
         browser_block_cache_(NewLRUCache(DefaultBlockCacheSize())),
         // Using |this| here (when Globals is only partially constructed) is
         // safe because base::MemoryPressureListener calls our callback
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index d0328b7..4b131c1 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -19,8 +19,10 @@
     <classpathentry kind="src" path="android_webview/glue/java/src"/>
     <classpathentry kind="src" path="android_webview/java/src"/>
     <classpathentry kind="src" path="android_webview/javatests/src"/>
+    <classpathentry kind="src" path="android_webview/js_sandbox/java/src"/>
     <classpathentry kind="src" path="android_webview/junit/src"/>
     <classpathentry kind="src" path="android_webview/nonembedded/java/src"/>
+    <classpathentry kind="src" path="android_webview/support_library/boundary_interfaces/src"/>
     <classpathentry kind="src" path="android_webview/support_library/callback/java/src"/>
     <classpathentry kind="src" path="android_webview/support_library/java/src"/>
     <classpathentry kind="src" path="android_webview/test/embedded_test_server/java/src"/>
@@ -29,6 +31,7 @@
     <classpathentry kind="src" path="android_webview/tools/automated_ui_tests/javatests/src"/>
     <classpathentry kind="src" path="android_webview/tools/system_webview_shell/apk/src"/>
     <classpathentry kind="src" path="android_webview/tools/system_webview_shell/layout_tests/src"/>
+    <classpathentry kind="src" path="android_webview/tools/system_webview_shell/page_cycler/src"/>
     <classpathentry kind="src" path="android_webview/unittestjava/src"/>
     <classpathentry kind="src" path="base/android/java/src"/>
     <classpathentry kind="src" path="base/android/javatests/src"/>
@@ -37,45 +40,45 @@
     <classpathentry kind="src" path="base/test/android/java/src"/>
     <classpathentry kind="src" path="base/test/android/javatests/src"/>
     <classpathentry kind="src" path="base/test/android/junit/src"/>
+    <classpathentry kind="src" path="build/android/gtest_apk/java/src"/>
+    <classpathentry kind="src" path="build/android/java/src"/>
+    <classpathentry kind="src" path="build/android/junit/src"/>
     <classpathentry kind="src" path="build/android/pylib/device/commands/java/src"/>
-    <classpathentry kind="src" path="chrome/android/features/dev_ui/java/src"/>
+    <classpathentry kind="src" path="build/config/android/test/classpath_order/java/src"/>
+    <classpathentry kind="src" path="build/config/android/test/resource_overlay/java/src"/>
+    <classpathentry kind="src" path="cc/base/android/java/src"/>
+    <classpathentry kind="src" path="chrome/android/features/android_library_factory/junit/src"/>
+    <classpathentry kind="src" path="chrome/android/features/android_library_factory/test/java/src"/>
+    <classpathentry kind="src" path="chrome/android/features/autofill_assistant/guided_browsing/javatests/src"/>
+    <classpathentry kind="src" path="chrome/android/features/autofill_assistant/javatests/src"/>
+    <classpathentry kind="src" path="chrome/android/features/autofill_assistant/public/java/src"/>
+    <classpathentry kind="src" path="chrome/android/features/cablev2_authenticator/java/src"/>
+    <classpathentry kind="src" path="chrome/android/features/dev_ui/internal/java/src"/>
     <classpathentry kind="src" path="chrome/android/features/dev_ui/public/java/src"/>
     <classpathentry kind="src" path="chrome/android/features/keyboard_accessory/factory/java/src"/>
     <classpathentry kind="src" path="chrome/android/features/keyboard_accessory/internal/java/src"/>
     <classpathentry kind="src" path="chrome/android/features/keyboard_accessory/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/features/keyboard_accessory/junit/src"/>
     <classpathentry kind="src" path="chrome/android/features/keyboard_accessory/public/java/src"/>
-    <classpathentry kind="src" path="chrome/android/features/media_router/java/src"/>
-    <classpathentry kind="src" path="chrome/android/features/media_router/javatests/src"/>
-    <classpathentry kind="src" path="chrome/android/features/media_router/junit/src"/>
-    <classpathentry kind="src" path="chrome/android/features/stack_unwinder/internal/java/src"/>
-    <classpathentry kind="src" path="chrome/android/features/stack_unwinder/public/java/src"/>
-    <classpathentry kind="src" path="chrome/android/features/start_surface/internal/dummy/java/src"/>
-    <classpathentry kind="src" path="chrome/android/features/start_surface/internal/java/src"/>
-    <classpathentry kind="src" path="chrome/android/features/start_surface/internal/javatests/src"/>
-    <classpathentry kind="src" path="chrome/android/features/start_surface/internal/junit/src"/>
-    <classpathentry kind="src" path="chrome/android/features/start_surface/public/java/src"/>
+    <classpathentry kind="src" path="chrome/android/features/start_surface/java/src"/>
+    <classpathentry kind="src" path="chrome/android/features/start_surface/javatests/src"/>
+    <classpathentry kind="src" path="chrome/android/features/start_surface/junit/src"/>
     <classpathentry kind="src" path="chrome/android/features/tab_ui/java/src"/>
     <classpathentry kind="src" path="chrome/android/features/tab_ui/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/features/tab_ui/junit/src"/>
-    <classpathentry kind="src" path="chrome/android/features/test_dummy/internal/java/src"/>
-    <classpathentry kind="src" path="chrome/android/features/test_dummy/public/java/src"/>
+    <classpathentry kind="src" path="chrome/android/features/tab_ui/public/android/java/src"/>
     <classpathentry kind="src" path="chrome/android/features/vr/java/src"/>
     <classpathentry kind="src" path="chrome/android/feed/core/java/src"/>
     <classpathentry kind="src" path="chrome/android/feed/core/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/feed/dummy/java/src"/>
     <classpathentry kind="src" path="chrome/android/java/src"/>
+    <classpathentry kind="src" path="chrome/android/java/src"/>
     <classpathentry kind="src" path="chrome/android/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/junit/src"/>
-    <classpathentry kind="src" path="chrome/android/modules/chime/internal/java/src"/>
-    <classpathentry kind="src" path="chrome/android/modules/chime/public/java/src"/>
+    <classpathentry kind="src" path="chrome/android/modules/cablev2_authenticator/internal/java/src"/>
+    <classpathentry kind="src" path="chrome/android/modules/cablev2_authenticator/public/java/src"/>
     <classpathentry kind="src" path="chrome/android/modules/dev_ui/provider/java/src"/>
-    <classpathentry kind="src" path="chrome/android/modules/extra_icu/internal/java/src"/>
-    <classpathentry kind="src" path="chrome/android/modules/extra_icu/provider/java/src"/>
-    <classpathentry kind="src" path="chrome/android/modules/extra_icu/public/java/src"/>
-    <classpathentry kind="src" path="chrome/android/modules/image_editor/internal/java/src"/>
     <classpathentry kind="src" path="chrome/android/modules/image_editor/provider/java/src"/>
-    <classpathentry kind="src" path="chrome/android/modules/image_editor/public/java/src"/>
     <classpathentry kind="src" path="chrome/android/modules/stack_unwinder/internal/java/src"/>
     <classpathentry kind="src" path="chrome/android/modules/stack_unwinder/provider/java/src"/>
     <classpathentry kind="src" path="chrome/android/modules/stack_unwinder/public/java/src"/>
@@ -83,88 +86,271 @@
     <classpathentry kind="src" path="chrome/android/modules/test_dummy/provider/java/src"/>
     <classpathentry kind="src" path="chrome/android/modules/test_dummy/public/java/src"/>
     <classpathentry kind="src" path="chrome/android/native_java_unittests/src"/>
-    <classpathentry kind="src" path="chrome/android/third_party/compositor_animator/java/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/libs/client/junit/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/libs/client/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/libs/common/src"/>
+    <classpathentry kind="src" path="chrome/android/webapk/libs/runtime_library/javatests/apk_with_webapk_service/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/libs/runtime_library/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/libs/runtime_library/src"/>
-    <classpathentry kind="src" path="chrome/android/webapk/shell_apk/javatests/dex_optimizer/src"/>
+    <classpathentry kind="src" path="chrome/android/webapk/shell_apk/javatests/canary_lib/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/shell_apk/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/shell_apk/junit/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/shell_apk/src"/>
+    <classpathentry kind="src" path="chrome/android/webapk/test/src"/>
+    <classpathentry kind="src" path="chrome/browser/accessibility/hierarchysnapshotter/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/android/browserservices/intents/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/android/browserservices/metrics/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/android/browserservices/verification/java/src"/>
     <classpathentry kind="src" path="chrome/browser/android/crypto/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/android/customtabs/branding/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/android/examples/partner_browser_customizations_provider/src"/>
+    <classpathentry kind="src" path="chrome/browser/android/httpclient/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/android/httpclient/public/src"/>
     <classpathentry kind="src" path="chrome/browser/android/lifecycle/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/android/messages/java/src"/>
     <classpathentry kind="src" path="chrome/browser/android/metrics/javatests/src"/>
-    <classpathentry kind="src" path="chrome/browser/android/thin_webview/internal/java/src"/>
-    <classpathentry kind="src" path="chrome/browser/android/thin_webview/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/autofill/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/back_press/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/banners/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/battery/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/bluetooth/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/bluetooth/android/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/browser_controls/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/commerce/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/commerce/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/commerce/merchant_viewer/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/commerce/merchant_viewer/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/commerce/price_tracking/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/commerce/price_tracking/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/commerce/subscriptions/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/commerce/subscriptions/test/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/consent_auditor/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/content_creation/notes/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/content_creation/notes/internal/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/content_creation/reactions/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/contextmenu/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/creator/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/dependency_injection/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/device/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/device_reauth/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/download/android/java/src"/>
-    <classpathentry kind="src" path="chrome/browser/download/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/download/internal/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/endpoint_fetcher/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/engagement/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/enterprise/util/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/feature_engagement/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/feature_guide/notifications/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/feed/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/feedback/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/first_run/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/flags/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/fullscreen/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/gsa/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/history_clusters/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/image_descriptions/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/image_editor/internal/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/image_editor/public/android/java/src"/>
-    <classpathentry kind="src" path="chrome/browser/image_fetcher/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/incognito/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/incognito/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/language/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/lens/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/loading_modal/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/loading_modal/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/loading_modal/android/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/locale/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/metrics_settings/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/notifications/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/notifications/chime/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/offline_pages/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/omaha/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/optimization_guide/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/optimization_guide/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/page_annotations/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/page_annotations/test/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/paint_preview/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/paint_preview/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/partnerbookmarks/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/partnercustomizations/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/partnercustomizations/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/password_check/android/internal/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/password_check/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/password_check/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/password_check/android/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/password_edit_dialog/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/password_entry_edit/android/internal/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/password_entry_edit/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/password_manager/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/password_manager/android/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/password_manager/android/test_support/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/payments/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/policy/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/preferences/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/prefetch/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/privacy_guide/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/privacy_guide/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/privacy_guide/android/junit/src"/>
     <classpathentry kind="src" path="chrome/browser/privacy/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/privacy_sandbox/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/privacy_sandbox/android/javatests/src"/>
     <classpathentry kind="src" path="chrome/browser/privacy/settings/java/src"/>
     <classpathentry kind="src" path="chrome/browser/profiles/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/safe_browsing/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/safe_browsing/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/safety_check/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/safety_check/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/search_engines/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/search_resumption/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/search_resumption/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/segmentation_platform/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/selection/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/settings/android/java/src"/>
-    <classpathentry kind="src" path="chrome/browser/settings/android/widget/java/src"/>
     <classpathentry kind="src" path="chrome/browser/share/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/share/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/signin/services/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/signin/services/android/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/supervised_user/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/supervised_user/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/sync/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/sync/test/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/tab_group/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/tab_group/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/tab_group/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/tab/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/tabmodel/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/tabmodel/internal/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/tabpersistence/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/test_dummy/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/test_dummy/internal/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/thumbnail/generator/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/touch_to_fill/android/internal/java/src"/>
     <classpathentry kind="src" path="chrome/browser/touch_to_fill/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/touch_to_fill/android/javatests/src"/>
     <classpathentry kind="src" path="chrome/browser/touch_to_fill/android/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/touch_to_fill/payments/android/internal/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/touch_to_fill/payments/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/ui/android/appmenu/internal/java/src"/>
     <classpathentry kind="src" path="chrome/browser/ui/android/appmenu/java/src"/>
     <classpathentry kind="src" path="chrome/browser/ui/android/appmenu/test/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/autofill/internal/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/default_browser_promo/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/fast_checkout/internal/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/fast_checkout/internal/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/fast_checkout/java/src"/>
     <classpathentry kind="src" path="chrome/browser/ui/android/favicon/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/layouts/glue/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/layouts/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/layouts/test/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/logo/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/management/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/multiwindow/java/src"/>
     <classpathentry kind="src" path="chrome/browser/ui/android/native_page/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/night_mode/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/omnibox/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/page_info/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/quickactionsearchwidget/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/searchactivityutils/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/signin/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/signin/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/theme/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/toolbar/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/webid/internal/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/ui/android/webid/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/uid/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/uid/android/junit/src"/>
     <classpathentry kind="src" path="chrome/browser/ui/messages/android/java/src"/>
-    <classpathentry kind="src" path="chrome/browser/upboarding/query_tiles/android/java/src"/>
-    <classpathentry kind="src" path="chrome/browser/upboarding/query_tiles/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/browser/usb/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/usb/android/junit/src"/>
+    <classpathentry kind="src" path="chrome/browser/user_education/java/src"/>
     <classpathentry kind="src" path="chrome/browser/util/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/video_tutorials/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/video_tutorials/internal/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/webapps/android/java/src"/>
+    <classpathentry kind="src" path="chrome/browser/webauthn/android/java/src"/>
     <classpathentry kind="src" path="chrome/browser/xsurface/android/java/src"/>
-    <classpathentry kind="src" path="chrome/test/android/cast_emulator/src"/>
+    <classpathentry kind="src" path="chrome/test/android/browsertests_apk/src"/>
     <classpathentry kind="src" path="chrome/test/android/javatests/src"/>
+    <classpathentry kind="src" path="chrome/test/android/test_support/src"/>
+    <classpathentry kind="src" path="chrome/test/android/test_trusted_web_activity/src"/>
     <classpathentry kind="src" path="chrome/test/chromedriver/test/webview_shell/java/src"/>
     <classpathentry kind="src" path="chromecast/base/java/src"/>
     <classpathentry kind="src" path="chromecast/browser/android/apk/src"/>
     <classpathentry kind="src" path="chromecast/browser/android/junit/src"/>
     <classpathentry kind="src" path="chromecast/media/cma/backend/android/java/src"/>
     <classpathentry kind="src" path="components/about_ui/android/java/src"/>
+    <classpathentry kind="src" path="components/android_autofill/browser/java/src"/>
+    <classpathentry kind="src" path="components/android_autofill/browser/junit/src"/>
+    <classpathentry kind="src" path="components/android_autofill/browser/test_support/java/src"/>
     <classpathentry kind="src" path="components/autofill/android/java/src"/>
+    <classpathentry kind="src" path="components/autofill_assistant/android/java/src"/>
+    <classpathentry kind="src" path="components/autofill_assistant/android/public/java/src"/>
+    <classpathentry kind="src" path="components/autofill_assistant/android/public/junit/src"/>
+    <classpathentry kind="src" path="components/autofill_assistant/guided_browsing/android/java/src"/>
     <classpathentry kind="src" path="components/background_task_scheduler/android/java/src"/>
     <classpathentry kind="src" path="components/background_task_scheduler/internal/android/java/src"/>
-    <classpathentry kind="src" path="components/background_task_scheduler/internal/android/javatests/src"/>
     <classpathentry kind="src" path="components/background_task_scheduler/internal/android/junit/src"/>
     <classpathentry kind="src" path="components/bookmarks/common/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/accessibility/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/banners/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/bottomsheet/android/internal/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/bottomsheet/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/bottomsheet/android/test/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/client_certificate/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/contacts_picker/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/display_cutout/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/http_auth/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/media/android/java/src"/>
     <classpathentry kind="src" path="components/browser_ui/modaldialog/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/notifications/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/photo_picker/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/settings/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/settings/android/widget/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/settings/android/widget/javatests/src"/>
+    <classpathentry kind="src" path="components/browser_ui/share/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/site_settings/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/site_settings/android/javatests/src"/>
+    <classpathentry kind="src" path="components/browser_ui/site_settings/android/junit/src"/>
+    <classpathentry kind="src" path="components/browser_ui/sms/android/java/src"/>
     <classpathentry kind="src" path="components/browser_ui/styles/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/test/android/src"/>
     <classpathentry kind="src" path="components/browser_ui/util/android/java/src"/>
+    <classpathentry kind="src" path="components/browser_ui/webshare/android/java/src"/>
     <classpathentry kind="src" path="components/browser_ui/widget/android/java/src"/>
     <classpathentry kind="src" path="components/browser_ui/widget/android/test/java/src"/>
+    <classpathentry kind="src" path="components/commerce/core/android/java/src"/>
+    <classpathentry kind="src" path="components/component_updater/android/java/src"/>
     <classpathentry kind="src" path="components/content_capture/android/java/src"/>
+    <classpathentry kind="src" path="components/content_capture/android/junit/src"/>
+    <classpathentry kind="src" path="components/content_capture/android/test_support/java/src"/>
+    <classpathentry kind="src" path="components/content_creation/notes/android/java/src"/>
+    <classpathentry kind="src" path="components/content_creation/reactions/android/java/src"/>
+    <classpathentry kind="src" path="components/content_settings/android/java/src"/>
     <classpathentry kind="src" path="components/crash/android/java/src"/>
+    <classpathentry kind="src" path="components/crash/android/junit/src"/>
     <classpathentry kind="src" path="components/cronet/android/api/src"/>
     <classpathentry kind="src" path="components/cronet/android/java/src"/>
     <classpathentry kind="src" path="components/cronet/android/sample/javatests/src"/>
+    <classpathentry kind="src" path="components/cronet/android/sample/src"/>
     <classpathentry kind="src" path="components/cronet/android/test/javaperftests/src"/>
     <classpathentry kind="src" path="components/cronet/android/test/javatests/src"/>
+    <classpathentry kind="src" path="components/cronet/android/test/smoketests/src"/>
     <classpathentry kind="src" path="components/cronet/android/test/src"/>
+    <classpathentry kind="src" path="components/digital_asset_links/android/java/src"/>
     <classpathentry kind="src" path="components/dom_distiller/content/browser/android/java/src"/>
     <classpathentry kind="src" path="components/dom_distiller/core/android/java/src"/>
     <classpathentry kind="src" path="components/download/internal/background_service/android/java/src"/>
     <classpathentry kind="src" path="components/download/internal/common/android/java/src"/>
     <classpathentry kind="src" path="components/download/network/android/java/src"/>
+    <classpathentry kind="src" path="components/download/network/android/junit/src"/>
     <classpathentry kind="src" path="components/embedder_support/android/java/src"/>
+    <classpathentry kind="src" path="components/embedder_support/android/javatests/src"/>
     <classpathentry kind="src" path="components/embedder_support/android/junit/src"/>
     <classpathentry kind="src" path="components/embedder_support/android/metrics/java/src"/>
+    <classpathentry kind="src" path="components/embedder_support/android/native_java_unittests/src"/>
+    <classpathentry kind="src" path="components/externalauth/android/java/src"/>
+    <classpathentry kind="src" path="components/externalauth/android/junit/src"/>
     <classpathentry kind="src" path="components/external_intents/android/java/src"/>
+    <classpathentry kind="src" path="components/external_intents/android/javatests/src"/>
+    <classpathentry kind="src" path="components/favicon/android/java/src"/>
     <classpathentry kind="src" path="components/feature_engagement/internal/android/java/src"/>
     <classpathentry kind="src" path="components/feature_engagement/public/android/java/src"/>
     <classpathentry kind="src" path="components/find_in_page/android/java/src"/>
@@ -172,16 +358,29 @@
     <classpathentry kind="src" path="components/gcm_driver/android/junit/src"/>
     <classpathentry kind="src" path="components/gcm_driver/instance_id/android/java/src"/>
     <classpathentry kind="src" path="components/gcm_driver/instance_id/android/javatests/src"/>
-    <classpathentry kind="src" path="components/heap_profiling/javatests/src"/>
+    <classpathentry kind="src" path="components/heap_profiling/multi_process/javatests/src"/>
+    <classpathentry kind="src" path="components/image_fetcher/android/java/src"/>
+    <classpathentry kind="src" path="components/image_fetcher/android/junit/src"/>
+    <classpathentry kind="src" path="components/infobars/android/java/src"/>
+    <classpathentry kind="src" path="components/installedapp/android/java/src"/>
     <classpathentry kind="src" path="components/javascript_dialogs/android/java/src"/>
     <classpathentry kind="src" path="components/language/android/java/src"/>
     <classpathentry kind="src" path="components/location/android/java/src"/>
+    <classpathentry kind="src" path="components/media_router/browser/android/java/src"/>
+    <classpathentry kind="src" path="components/media_router/browser/android/javatests/src"/>
+    <classpathentry kind="src" path="components/media_router/browser/android/junit/src"/>
+    <classpathentry kind="src" path="components/media_router/test/android/cast_emulator/src"/>
+    <classpathentry kind="src" path="components/messages/android/internal/java/src"/>
+    <classpathentry kind="src" path="components/messages/android/java/src"/>
+    <classpathentry kind="src" path="components/messages/android/test/java/src"/>
+    <classpathentry kind="src" path="components/metrics/android/java/src"/>
     <classpathentry kind="src" path="components/minidump_uploader/android/java/src"/>
     <classpathentry kind="src" path="components/minidump_uploader/android/javatests/src"/>
     <classpathentry kind="src" path="components/module_installer/android/java/src"/>
     <classpathentry kind="src" path="components/module_installer/android/junit/src"/>
     <classpathentry kind="src" path="components/navigation_interception/android/java/src"/>
     <classpathentry kind="src" path="components/offline_items_collection/core/android/java/src"/>
+    <classpathentry kind="src" path="components/offline_items_collection/core/android/native_java_unittests/src"/>
     <classpathentry kind="src" path="components/omnibox/browser/android/java/src"/>
     <classpathentry kind="src" path="components/page_info/android/java/src"/>
     <classpathentry kind="src" path="components/paint_preview/browser/android/java/src"/>
@@ -189,30 +388,51 @@
     <classpathentry kind="src" path="components/paint_preview/player/android/javatests/src"/>
     <classpathentry kind="src" path="components/paint_preview/player/android/junit/src"/>
     <classpathentry kind="src" path="components/payments/content/android/java/src"/>
+    <classpathentry kind="src" path="components/payments/content/android/javatests/src"/>
+    <classpathentry kind="src" path="components/payments/content/android/junit/src"/>
     <classpathentry kind="src" path="components/permissions/android/java/src"/>
     <classpathentry kind="src" path="components/permissions/android/junit/src"/>
     <classpathentry kind="src" path="components/policy/android/java/src"/>
     <classpathentry kind="src" path="components/policy/android/javatests/src"/>
     <classpathentry kind="src" path="components/policy/android/junit/src"/>
+    <classpathentry kind="src" path="components/prefs/android/java/src"/>
+    <classpathentry kind="src" path="components/query_tiles/android/java/src"/>
     <classpathentry kind="src" path="components/safe_browsing/android/java/src"/>
     <classpathentry kind="src" path="components/search_engines/android/java/src"/>
     <classpathentry kind="src" path="components/security_interstitials/content/android/java/src"/>
     <classpathentry kind="src" path="components/security_state/content/android/java/src"/>
+    <classpathentry kind="src" path="components/segmentation_platform/internal/android/java/src"/>
+    <classpathentry kind="src" path="components/segmentation_platform/public/android/java/src"/>
     <classpathentry kind="src" path="components/signin/public/android/java/src"/>
-    <classpathentry kind="src" path="components/signin/public/android/javatests/src"/>
+    <classpathentry kind="src" path="components/signin/public/android/junit/src"/>
+    <classpathentry kind="src" path="components/site_engagement/content/android/java/src"/>
     <classpathentry kind="src" path="components/spellcheck/browser/android/java/src"/>
+    <classpathentry kind="src" path="components/strictmode/android/java/src"/>
+    <classpathentry kind="src" path="components/strictmode/android/javatests/src"/>
+    <classpathentry kind="src" path="components/stylus_handwriting/android/java/src"/>
+    <classpathentry kind="src" path="components/stylus_handwriting/android/junit/src"/>
     <classpathentry kind="src" path="components/subresource_filter/android/java/src"/>
     <classpathentry kind="src" path="components/sync/android/java/src"/>
-    <classpathentry kind="src" path="components/sync/android/javatests/src"/>
-    <classpathentry kind="src" path="components/sync/test/android/javatests/src"/>
     <classpathentry kind="src" path="components/test/android/browsertests_apk/src"/>
+    <classpathentry kind="src" path="components/thin_webview/internal/java/src"/>
+    <classpathentry kind="src" path="components/thin_webview/java/src"/>
+    <classpathentry kind="src" path="components/translate/content/android/java/src"/>
+    <classpathentry kind="src" path="components/ukm/android/java/src"/>
     <classpathentry kind="src" path="components/url_formatter/android/java/src"/>
-    <classpathentry kind="src" path="components/url_formatter/android/native_java_unittests/src"/>
+    <classpathentry kind="src" path="components/url_formatter/android/javatests/src"/>
+    <classpathentry kind="src" path="components/user_prefs/android/java/src"/>
     <classpathentry kind="src" path="components/variations/android/java/src"/>
     <classpathentry kind="src" path="components/variations/android/junit/src"/>
     <classpathentry kind="src" path="components/version_info/android/java/src"/>
     <classpathentry kind="src" path="components/viz/common/java/src"/>
     <classpathentry kind="src" path="components/viz/service/java/src"/>
+    <classpathentry kind="src" path="components/webapk/android/libs/client/src"/>
+    <classpathentry kind="src" path="components/webapk/android/libs/common/src"/>
+    <classpathentry kind="src" path="components/webapps/browser/android/java/src"/>
+    <classpathentry kind="src" path="components/webapps/common/android/java/src"/>
+    <classpathentry kind="src" path="components/webauthn/android/java/src"/>
+    <classpathentry kind="src" path="components/webrtc/android/java/src"/>
+    <classpathentry kind="src" path="components/webxr/android/java/src"/>
     <classpathentry kind="src" path="content/public/android/java/src"/>
     <classpathentry kind="src" path="content/public/android/javatests/src"/>
     <classpathentry kind="src" path="content/public/android/junit/src"/>
@@ -226,8 +446,8 @@
     <classpathentry kind="src" path="device/bluetooth/test/android/java/src"/>
     <classpathentry kind="src" path="device/gamepad/android/java/src"/>
     <classpathentry kind="src" path="device/gamepad/android/junit/src"/>
-    <classpathentry kind="src" path="device/usb/android/java/src"/>
     <classpathentry kind="src" path="device/vr/android/java/src"/>
+    <classpathentry kind="src" path="gpu/config/android/java/src"/>
     <classpathentry kind="src" path="media/base/android/java/src"/>
     <classpathentry kind="src" path="media/capture/content/android/java/src"/>
     <classpathentry kind="src" path="media/capture/video/android/java/src"/>
@@ -261,43 +481,88 @@
     <classpathentry kind="src" path="services/device/vibration/android/java/src"/>
     <classpathentry kind="src" path="services/device/wake_lock/power_save_blocker/android/java/src"/>
     <classpathentry kind="src" path="services/media_session/public/cpp/android/java/src"/>
+    <classpathentry kind="src" path="services/network/public/java/src"/>
     <classpathentry kind="src" path="services/service_manager/public/java/src"/>
     <classpathentry kind="src" path="services/shape_detection/android/java/src"/>
     <classpathentry kind="src" path="services/shape_detection/android/javatests/src"/>
     <classpathentry kind="src" path="services/shape_detection/android/junit/src"/>
+    <classpathentry kind="src" path="services/tracing/android/test/src"/>
     <classpathentry kind="src" path="testing/android/broker/java/src"/>
-    <classpathentry kind="src" path="testing/android/driver/java/src"/>
     <classpathentry kind="src" path="testing/android/junit/java/src"/>
     <classpathentry kind="src" path="testing/android/junit/javatests/src"/>
     <classpathentry kind="src" path="testing/android/native_test/java/src"/>
     <classpathentry kind="src" path="testing/android/reporter/java/src"/>
-    <classpathentry kind="src" path="third_party/android_data_chart/java/src"/>
+    <classpathentry kind="src" path="third_party/android_build_tools/json/src"/>
+    <classpathentry kind="src" path="third_party/android_build_tools/lint/java/src"/>
     <classpathentry kind="src" path="third_party/android_media/java/src"/>
     <classpathentry kind="src" path="third_party/android_protobuf/src/java/src"/>
     <classpathentry kind="src" path="third_party/android_protobuf/src/java/src/main/java" including="com/google/protobuf/nano/*"/>
+    <classpathentry kind="src" path="third_party/android_provider/java/src"/>
     <classpathentry kind="src" path="third_party/android_swipe_refresh/java/src"/>
-    <classpathentry kind="src" path="third_party/androidx_browser/src/browser/src"/>
-    <classpathentry kind="src" path="third_party/custom_tabs_client/src/customtabs/junit/src"/>
     <classpathentry kind="src" path="third_party/gif_player/src"/>
     <classpathentry kind="src" path="third_party/junit/src"/>
     <classpathentry kind="src" path="third_party/junit/src/src/main/java"/>
     <classpathentry kind="src" path="third_party/mockito/src/src/main/java"/>
     <classpathentry kind="src" path="third_party/protobuf/benchmarks/java/src"/>
+    <classpathentry kind="src" path="third_party/angle/src/android_system_settings/src"/>
+    <classpathentry kind="src" path="third_party/angle/src/tests/test_utils/runner/android/java/src"/>
+    <classpathentry kind="src" path="third_party/angle/third_party/glmark2/src/android/src"/>
+    <classpathentry kind="src" path="third_party/angle/third_party/VK-GL-CTS/src/android/cts/runner/src"/>
+    <classpathentry kind="src" path="third_party/angle/third_party/VK-GL-CTS/src/android/cts/runner/tests/src"/>
+    <classpathentry kind="src" path="third_party/angle/third_party/VK-GL-CTS/src/android/openglcts/src"/>
+    <classpathentry kind="src" path="third_party/angle/third_party/VK-GL-CTS/src/android/package/src"/>
+    <classpathentry kind="src" path="third_party/flatbuffers/src/kotlin/flatbuffers-kotlin/src/commonMain/kotlin"/>
+    <classpathentry kind="src" path="third_party/flatbuffers/src/kotlin/flatbuffers-kotlin/src/commonTest/kotlin"/>
+    <classpathentry kind="src" path="third_party/libaddressinput/src/common/src/main/java"/>
+    <classpathentry kind="src" path="third_party/libaddressinput/src/common/src/test/java"/>
+    <classpathentry kind="src" path="third_party/libphonenumber/dist/java/carrier/src"/>
+    <classpathentry kind="src" path="third_party/libphonenumber/dist/java/geocoder/src"/>
+    <classpathentry kind="src" path="third_party/libphonenumber/dist/java/internal/prefixmapper/src"/>
+    <classpathentry kind="src" path="third_party/libphonenumber/dist/java/libphonenumber/src"/>
+    <classpathentry kind="src" path="third_party/libphonenumber/dist/tools/java/common/src"/>
+    <classpathentry kind="src" path="third_party/libphonenumber/dist/tools/java/cpp-build/src"/>
+    <classpathentry kind="src" path="third_party/libphonenumber/dist/tools/java/data/src"/>
+    <classpathentry kind="src" path="third_party/libphonenumber/dist/tools/java/java-build/src"/>
+    <classpathentry kind="src" path="third_party/openh264/src/codec/build/android/dec/src"/>
+    <classpathentry kind="src" path="third_party/openh264/src/codec/build/android/enc/src"/>
+    <classpathentry kind="src" path="third_party/openh264/src/test/build/android/src"/>
+    <classpathentry kind="src" path="third_party/r8/java/src"/>
     <classpathentry kind="src" path="third_party/robolectric/custom_asynctask/java/src"/>
-    <classpathentry kind="src" path="third_party/robolectric/robolectric/junit/src"/>
+    <classpathentry kind="src" path="third_party/tflite/src/tensorflow/lite/tools/benchmark/android/src"/>
+    <classpathentry kind="src" path="third_party/tflite/src/tensorflow/lite/tools/benchmark/experimental/delegate_performance/android/src"/>
+    <classpathentry kind="src" path="third_party/tflite/src/tensorflow/lite/tools/benchmark/experimental/firebase/android/src"/>
+    <classpathentry kind="src" path="third_party/tflite/src/tensorflow/tools/android/test/src"/>
+    <classpathentry kind="src" path="third_party/tflite_support/src/tensorflow_lite_support/odml/java/image/src"/>
+    <classpathentry kind="src" path="third_party/tflite_support/src/tensorflow_lite_support/odml/java/image/tests/src"/>
+    <classpathentry kind="src" path="third_party/webgl/src/other/test-runner/android/PortForwarderService/src"/>
+    <classpathentry kind="src" path="third_party/webgl/src/sdk/demos/google/nvidia-vertex-buffer-object/android-vertex-buffer-object/src"/>
+    <classpathentry kind="src" path="third_party/webrtc/examples/androidapp/src"/>
+    <classpathentry kind="src" path="third_party/webrtc/examples/androidjunit/src"/>
+    <classpathentry kind="src" path="third_party/webrtc/examples/androidtests/src"/>
     <classpathentry kind="src" path="third_party/webrtc/examples/unityplugin/java/src"/>
     <classpathentry kind="src" path="third_party/webrtc/modules/audio_device/android/java/src"/>
     <classpathentry kind="src" path="third_party/webrtc/rtc_base/java/src"/>
+    <classpathentry kind="src" path="third_party/webrtc/rtc_tools/network_tester/androidapp/src"/>
+    <classpathentry kind="src" path="third_party/webrtc/sdk/android/instrumentationtests/src"/>
+    <classpathentry kind="src" path="third_party/webrtc/sdk/android/tests/src"/>
     <classpathentry kind="src" path="tools/android/audio_focus_grabber/java/src"/>
     <classpathentry kind="src" path="tools/android/customtabs_benchmark/java/src"/>
+    <classpathentry kind="src" path="tools/android/errorprone_plugin/src"/>
+    <classpathentry kind="src" path="tools/android/errorprone_plugin/test/src"/>
+    <classpathentry kind="src" path="tools/android/kerberos/SpnegoAuthenticator/src"/>
     <classpathentry kind="src" path="tools/android/memconsumer/java/src"/>
+    <classpathentry kind="src" path="tools/android/push_apps_to_background/src"/>
     <classpathentry kind="src" path="ui/android/java/src"/>
     <classpathentry kind="src" path="ui/android/javatests/src"/>
     <classpathentry kind="src" path="ui/android/junit/src"/>
     <classpathentry kind="src" path="url/android/java/src"/>
     <classpathentry kind="src" path="url/android/javatests/src"/>
+    <classpathentry kind="src" path="url/android/junit/src"/>
+    <classpathentry kind="src" path="url/android/test/java/src"/>
     <classpathentry kind="src" path="weblayer/browser/android/javatests/src"/>
-    <classpathentry kind="lib" path="../src/third_party/android_sdk/public/platforms/android-31/android.jar" sourcepath="../src/third_party/android_sdk/public/sources/">
+    <classpathentry kind="src" path="weblayer/shell/android/browsertests_apk/src"/>
+    <classpathentry kind="src" path="weblayer/shell/android/webengine_shell_apk/src"/>
+    <classpathentry kind="lib" path="../src/third_party/android_sdk/public/platforms/android-33/android.jar" sourcepath="../src/third_party/android_sdk/public/sources/">
         <attributes>
             <attribute name="javadoc_location" value="http://developer.android.com/reference/"/>
         </attributes>
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index ab770cc..3c54e7f 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -21539,6 +21539,25 @@
   <description>User adds one new bookmark, in the iOS tab grid.</description>
 </action>
 
+<action name="MobileTabGridOpenInactiveTab">
+  <owner>alionadangla@chromium.org</owner>
+  <owner>lpromero@chromium.org</owner>
+  <owner>chromeleon@google.com</owner>
+  <description>
+    User in the iOS tab grid opened an inactive tab by tapping on it.
+  </description>
+</action>
+
+<action name="MobileTabGridOpenInactiveTabSearchResult">
+  <owner>alionadangla@chromium.org</owner>
+  <owner>lpromero@chromium.org</owner>
+  <owner>chromeleon@google.com</owner>
+  <description>
+    User in the iOS tab grid opened an inactive tab by tapping on it from search
+    results.
+  </description>
+</action>
+
 <action name="MobileTabGridOpenIncognitoTab">
   <owner>edchin@chromium.org</owner>
   <owner>marq@chromium.org</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index bd3b9bd1..96c036e 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -41696,7 +41696,7 @@
       label="CrossOriginOpenerPolicySameOriginAllowPopupsReportOnly"/>
   <int value="4090" label="CrossOriginOpenerPolicySameOriginReportOnly"/>
   <int value="4091" label="ImageLoadAtDismissalEvent"/>
-  <int value="4092" label="PrivateNetworkAccessIgnoredPreflightError"/>
+  <int value="4092" label="OBSOLETE_PrivateNetworkAccessIgnoredPreflightError"/>
   <int value="4093" label="AbortPaymentRespondWithTrue"/>
   <int value="4094" label="AllowPaymentRequestAttributeHasEffect"/>
   <int value="4095" label="V8PaymentResponse_Retry_Method"/>
@@ -54220,6 +54220,7 @@
   <int value="5" label="Lockscreen launcher widget - Incognito"/>
   <int value="6" label="Lockscreen launcher widget - Voice Search"/>
   <int value="7" label="Lockscreen launcher widget - Dino Game"/>
+  <int value="8" label="Shortcuts widget"/>
 </enum>
 
 <enum name="IOSWKWebViewLinkPreviewAction">
@@ -62425,6 +62426,7 @@
   <int value="119185738"
       label="OmniboxUIExperimentMaxAutocompleteMatches:disabled"/>
   <int value="119309423" label="WebAssemblyThreads:disabled"/>
+  <int value="120031435" label="MemorySavingsReportingImprovements:disabled"/>
   <int value="120097846" label="SmartLockSignInRemoved:enabled"/>
   <int value="120429808" label="disable-new-profile-management"/>
   <int value="120519004" label="NavigationPredictor:disabled"/>
@@ -65699,6 +65701,7 @@
   <int value="1893463366" label="EnableHtmlBaseUsernameDetector:enabled"/>
   <int value="1893561439" label="HighEfficiencyModeAvailable:disabled"/>
   <int value="1893693031" label="FreezeUserAgent:enabled"/>
+  <int value="1894900449" label="MemorySavingsReportingImprovements:enabled"/>
   <int value="1895993853" label="NtpRealboxRoundedCorners:enabled"/>
   <int value="1896456311" label="enable-password-save-in-page-navigation"/>
   <int value="1896527497" label="ImmersiveUiMode:enabled"/>
@@ -80254,6 +80257,13 @@
   <int value="3" label="New pref is 'on', legacy pref is 'on'"/>
 </enum>
 
+<enum name="PasswordManagerPromoCard">
+  <int value="0" label="Checkup promo"/>
+  <int value="1" label="Web password manager promo"/>
+  <int value="2" label="Add shortcut promo"/>
+  <int value="3" label="Access on any device promo"/>
+</enum>
+
 <enum name="PasswordManagerPslDomainMatchTriggering">
   <summary>
     The value indicates whether an entry returned by password autofill contains
@@ -91144,6 +91154,16 @@
   <int value="11" label="Lax to Cross context with Lax cookie; secure origin."/>
 </enum>
 
+<enum name="SameSiteCookieValue">
+  <summary>
+    The possible values of SameSite a cookie's SameSite attribute.
+  </summary>
+  <int value="-1" label="Unspecified"/>
+  <int value="0" label="No Restriction"/>
+  <int value="1" label="Lax Mode"/>
+  <int value="2" label="Strict Mode"/>
+</enum>
+
 <enum name="SamlInSessionPasswordChangeEvent">
   <summary>
     Track how often we try to guide users through the in-session flow to change
diff --git a/tools/metrics/histograms/metadata/cryptohome/histograms.xml b/tools/metrics/histograms/metadata/cryptohome/histograms.xml
index a5a6ccd..9f5490ce 100644
--- a/tools/metrics/histograms/metadata/cryptohome/histograms.xml
+++ b/tools/metrics/histograms/metadata/cryptohome/histograms.xml
@@ -238,147 +238,6 @@
   <summary>Records the result of triggering disk cleanup.</summary>
 </histogram>
 
-<histogram name="Cryptohome.Error.AllLocations" enum="CryptohomeErrorLocation"
-    expires_after="2023-05-01">
-  <owner>zuan@chromium.org</owner>
-  <owner>cros-hwsec+uma@chromium.org</owner>
-  <summary>
-    Background context on this histogram: A CryptohomeError in this context
-    refers to an error that occurred in response to a dbus request to selected
-    cryptohomed APIs. The set of APIs with this CryptohomeError is generally
-    those related to authentication, and contains CryptohomeErrorInfo field in
-    the dbus Reply protobuf. Currently that includes methods that are called
-    during login. A CryptohomeError consists of a linear stack of
-    ErrorLocations, each one of them is an actual line in the cryptohomed
-    codebase which the error passed through, and could have certain attributes,
-    known as ErrorAction attached to them. The ErrorLocation in the bottom of
-    the stack could optionally have a TPM Error Code associated, if the source
-    of error is TPM related.
-
-    For this histogram, for every CryptohomeError that occurs, we individually
-    report each individual ErrorLocation's corresponding enum value when an
-    error ocurred.
-
-    This is useful to cryptohome developers in the sense that they'll be able to
-    know which lines that handle error in cryptohomed has been triggered due to
-    an error.
-  </summary>
-</histogram>
-
-<histogram name="Cryptohome.Error.DevUnexpectedState"
-    enum="CryptohomeErrorLocation" expires_after="2023-09-03">
-  <owner>zuan@chromium.org</owner>
-  <owner>cros-hwsec+uma@chromium.org</owner>
-  <summary>
-    Background context on this histogram: A CryptohomeError in this context
-    refers to an error that occurred in response to a dbus request to selected
-    cryptohomed APIs. The set of APIs with this CryptohomeError is generally
-    those related to authentication, and contains CryptohomeErrorInfo field in
-    the dbus Reply protobuf. Currently that includes methods that are called
-    during login. A CryptohomeError consists of a linear stack of
-    ErrorLocations, each one of them is an actual line in the cryptohomed
-    codebase which the error passed through, and could have certain attributes,
-    known as ErrorAction attached to them. The ErrorLocation in the bottom of
-    the stack could optionally have a TPM Error Code associated, if the source
-    of error is TPM related.
-
-    For this histogram, for every CryptohomeError, we individually report all
-    ErrorLocation that has the kDevCheckUnexpectedState ErrorAction associated
-    with it. The kDevCheckUnexpectedState ErrorAction is used by developers when
-    the developer believes that this error should never occur, so from a
-    notification standpoint, it functions similar to a DCHECK(), except it never
-    crashes cryptohome and handles the error in a graceful manner.
-
-    This is useful to cryptohome developers because they'll be alerted when any
-    of the situations that the developers doesn't expect to occur occurs.
-  </summary>
-</histogram>
-
-<histogram name="Cryptohome.Error.HashedStack" enum="CryptohomeErrorHashed"
-    expires_after="2023-09-03">
-  <owner>zuan@chromium.org</owner>
-  <owner>cros-hwsec+uma@chromium.org</owner>
-  <summary>
-    Background context on this histogram: A CryptohomeError in this context
-    refers to an error that occurred in response to a dbus request to selected
-    cryptohomed APIs. The set of APIs with this CryptohomeError is generally
-    those related to authentication, and contains CryptohomeErrorInfo field in
-    the dbus Reply protobuf. Currently that includes methods that are called
-    during login. A CryptohomeError consists of a linear stack of
-    ErrorLocations, each one of them is an actual line in the cryptohomed
-    codebase which the error passed through, and could have certain attributes,
-    known as ErrorAction attached to them. The ErrorLocation in the bottom of
-    the stack could optionally have a TPM Error Code associated, if the source
-    of error is TPM related.
-
-    For this histogram, we take the entire CryptohomeError's linear stack of
-    ErrorLocation, and hash the entire stack, then we report the hash. The
-    original stack of ErrorLocation is logged.
-
-    This is useful to cryptohome developers because we're able to classify the
-    CryptohomeError by the content of the stack, and identify new ways the error
-    can occur if they do occur.
-  </summary>
-</histogram>
-
-<histogram name="Cryptohome.Error.LeafErrorWithoutTPM"
-    enum="CryptohomeErrorLocation" expires_after="2023-09-03">
-  <owner>zuan@chromium.org</owner>
-  <owner>cros-hwsec+uma@chromium.org</owner>
-  <summary>
-    Background context on this histogram: A CryptohomeError in this context
-    refers to an error that occurred in response to a dbus request to selected
-    cryptohomed APIs. The set of APIs with this CryptohomeError is generally
-    those related to authentication, and contains CryptohomeErrorInfo field in
-    the dbus Reply protobuf. Currently that includes methods that are called
-    during login. A CryptohomeError consists of a linear stack of
-    ErrorLocations, each one of them is an actual line in the cryptohomed
-    codebase which the error passed through, and could have certain attributes,
-    known as ErrorAction attached to them. The ErrorLocation in the bottom of
-    the stack could optionally have a TPM Error Code associated, if the source
-    of error is TPM related.
-
-    For this histogram, for every CryptohomeError that occurred, we report the
-    last ErrorLocation in the stack of ErrorLocation in the CryptohomeError, if
-    the last ErrorLocation does not have a TPM Error Code associated with it.
-
-    This is useful to cryptohome developers because frequently, the last
-    ErrorLocation in the stack would be able to uniquely identify the error, and
-    this histogram doesn't involve hashing, so it would be more convenient for
-    the developers.
-  </summary>
-</histogram>
-
-<histogram name="Cryptohome.Error.LeafErrorWithTPM"
-    enum="CryptohomeErrorLocationWithTPMError" expires_after="2023-09-03">
-  <owner>zuan@chromium.org</owner>
-  <owner>cros-hwsec+uma@chromium.org</owner>
-  <summary>
-    Background context on this histogram: A CryptohomeError in this context
-    refers to an error that occurred in response to a dbus request to selected
-    cryptohomed APIs. The set of APIs with this CryptohomeError is generally
-    those related to authentication, and contains CryptohomeErrorInfo field in
-    the dbus Reply protobuf. Currently that includes methods that are called
-    during login. A CryptohomeError consists of a linear stack of
-    ErrorLocations, each one of them is an actual line in the cryptohomed
-    codebase which the error passed through, and could have certain attributes,
-    known as ErrorAction attached to them. The ErrorLocation in the bottom of
-    the stack could optionally have a TPM Error Code associated, if the source
-    of error is TPM related.
-
-    For this histogram, for every CryptohomeError that occurred, we report the
-    last ErrorLocation and the second last ErrorLocation in the CryptohomeError,
-    if the last ErrorLocation have a TPM Error Code associated with it. The
-    upper and lower 16-bit value of the reported value contains the second last
-    ErrorLocation and the TPM Error Code, correspondingly.
-
-    This is useful to cryptohome developers because frequently, the last and
-    second last ErrorLocation in the stack would be able to uniquely identify
-    the error, and this histogram doesn't involve hashing, so it woul dbe more
-    convenient for the developers.
-  </summary>
-</histogram>
-
 <histogram name="Cryptohome.Errors" enum="CryptohomeError"
     expires_after="2023-10-08">
   <owner>apronin@chromium.org</owner>
@@ -1128,6 +987,202 @@
   </token>
 </histogram>
 
+<histogram name="Cryptohome.{ErrorBucket}.AllLocations"
+    enum="CryptohomeErrorLocation" expires_after="2023-05-01">
+  <owner>zuan@chromium.org</owner>
+  <owner>cros-hwsec+uma@chromium.org</owner>
+  <summary>
+    Background context on this histogram: A CryptohomeError in this context
+    refers to an error that occurred in response to a dbus request to selected
+    cryptohomed APIs. The set of APIs with this CryptohomeError is generally
+    those related to authentication, and contains CryptohomeErrorInfo field in
+    the dbus Reply protobuf. Currently that includes methods that are called
+    during login. A CryptohomeError consists of a linear stack of
+    ErrorLocations, each one of them is an actual line in the cryptohomed
+    codebase which the error passed through, and could have certain attributes,
+    known as ErrorAction attached to them. The ErrorLocation in the bottom of
+    the stack could optionally have a TPM Error Code associated, if the source
+    of error is TPM related.
+
+    For this histogram, for every CryptohomeError that occurs, we individually
+    report each individual ErrorLocation's corresponding enum value when an
+    error ocurred.
+
+    This histogram is also separated into several {ErrorBucket}s. The most
+    standard error bucket is 'Error', which collects the errors populated in
+    dbus responses. Other buckets are errors we collect in some subrountines,
+    like migration. Migration errors are not surfaced to dbus responses, but
+    silently fail instead. We collect those errors in separate buckets.
+
+    This is useful to cryptohome developers in the sense that they'll be able to
+    know which lines that handle error in cryptohomed has been triggered due to
+    an error.
+  </summary>
+  <token key="ErrorBucket">
+    <variant name="Error"/>
+    <variant name="RecreateAuthFactorError.Pin"/>
+    <variant name="UssMigrationError"/>
+  </token>
+</histogram>
+
+<histogram name="Cryptohome.{ErrorBucket}.DevUnexpectedState"
+    enum="CryptohomeErrorLocation" expires_after="2023-09-03">
+  <owner>zuan@chromium.org</owner>
+  <owner>cros-hwsec+uma@chromium.org</owner>
+  <summary>
+    Background context on this histogram: A CryptohomeError in this context
+    refers to an error that occurred in response to a dbus request to selected
+    cryptohomed APIs. The set of APIs with this CryptohomeError is generally
+    those related to authentication, and contains CryptohomeErrorInfo field in
+    the dbus Reply protobuf. Currently that includes methods that are called
+    during login. A CryptohomeError consists of a linear stack of
+    ErrorLocations, each one of them is an actual line in the cryptohomed
+    codebase which the error passed through, and could have certain attributes,
+    known as ErrorAction attached to them. The ErrorLocation in the bottom of
+    the stack could optionally have a TPM Error Code associated, if the source
+    of error is TPM related.
+
+    For this histogram, for every CryptohomeError, we individually report all
+    ErrorLocation that has the kDevCheckUnexpectedState ErrorAction associated
+    with it. The kDevCheckUnexpectedState ErrorAction is used by developers when
+    the developer believes that this error should never occur, so from a
+    notification standpoint, it functions similar to a DCHECK(), except it never
+    crashes cryptohome and handles the error in a graceful manner.
+
+    This histogram is also separated into several {ErrorBucket}s. The most
+    standard error bucket is 'Error', which collects the errors populated in
+    dbus responses. Other buckets are errors we collect in some subrountines,
+    like migration. Migration errors are not surfaced to dbus responses, but
+    silently fail instead. We collect those errors in separate buckets.
+
+    This is useful to cryptohome developers because they'll be alerted when any
+    of the situations that the developers doesn't expect to occur occurs.
+  </summary>
+  <token key="ErrorBucket">
+    <variant name="Error"/>
+    <variant name="RecreateAuthFactorError.Pin"/>
+    <variant name="UssMigrationError"/>
+  </token>
+</histogram>
+
+<histogram name="Cryptohome.{ErrorBucket}.HashedStack"
+    enum="CryptohomeErrorHashed" expires_after="2023-09-03">
+  <owner>zuan@chromium.org</owner>
+  <owner>cros-hwsec+uma@chromium.org</owner>
+  <summary>
+    Background context on this histogram: A CryptohomeError in this context
+    refers to an error that occurred in response to a dbus request to selected
+    cryptohomed APIs. The set of APIs with this CryptohomeError is generally
+    those related to authentication, and contains CryptohomeErrorInfo field in
+    the dbus Reply protobuf. Currently that includes methods that are called
+    during login. A CryptohomeError consists of a linear stack of
+    ErrorLocations, each one of them is an actual line in the cryptohomed
+    codebase which the error passed through, and could have certain attributes,
+    known as ErrorAction attached to them. The ErrorLocation in the bottom of
+    the stack could optionally have a TPM Error Code associated, if the source
+    of error is TPM related.
+
+    For this histogram, we take the entire CryptohomeError's linear stack of
+    ErrorLocation, and hash the entire stack, then we report the hash. The
+    original stack of ErrorLocation is logged.
+
+    This histogram is also separated into several {ErrorBucket}s. The most
+    standard error bucket is 'Error', which collects the errors populated in
+    dbus responses. Other buckets are errors we collect in some subrountines,
+    like migration. Migration errors are not surfaced to dbus responses, but
+    silently fail instead. We collect those errors in separate buckets.
+
+    This is useful to cryptohome developers because we're able to classify the
+    CryptohomeError by the content of the stack, and identify new ways the error
+    can occur if they do occur.
+  </summary>
+  <token key="ErrorBucket">
+    <variant name="Error"/>
+    <variant name="RecreateAuthFactorError.Pin"/>
+    <variant name="UssMigrationError"/>
+  </token>
+</histogram>
+
+<histogram name="Cryptohome.{ErrorBucket}.LeafErrorWithoutTPM"
+    enum="CryptohomeErrorLocation" expires_after="2023-09-03">
+  <owner>zuan@chromium.org</owner>
+  <owner>cros-hwsec+uma@chromium.org</owner>
+  <summary>
+    Background context on this histogram: A CryptohomeError in this context
+    refers to an error that occurred in response to a dbus request to selected
+    cryptohomed APIs. The set of APIs with this CryptohomeError is generally
+    those related to authentication, and contains CryptohomeErrorInfo field in
+    the dbus Reply protobuf. Currently that includes methods that are called
+    during login. A CryptohomeError consists of a linear stack of
+    ErrorLocations, each one of them is an actual line in the cryptohomed
+    codebase which the error passed through, and could have certain attributes,
+    known as ErrorAction attached to them. The ErrorLocation in the bottom of
+    the stack could optionally have a TPM Error Code associated, if the source
+    of error is TPM related.
+
+    For this histogram, for every CryptohomeError that occurred, we report the
+    last ErrorLocation in the stack of ErrorLocation in the CryptohomeError, if
+    the last ErrorLocation does not have a TPM Error Code associated with it.
+
+    This histogram is also separated into several {ErrorBucket}s. The most
+    standard error bucket is 'Error', which collects the errors populated in
+    dbus responses. Other buckets are errors we collect in some subrountines,
+    like migration. Migration errors are not surfaced to dbus responses, but
+    silently fail instead. We collect those errors in separate buckets.
+
+    This is useful to cryptohome developers because frequently, the last
+    ErrorLocation in the stack would be able to uniquely identify the error, and
+    this histogram doesn't involve hashing, so it would be more convenient for
+    the developers.
+  </summary>
+  <token key="ErrorBucket">
+    <variant name="Error"/>
+    <variant name="RecreateAuthFactorError.Pin"/>
+    <variant name="UssMigrationError"/>
+  </token>
+</histogram>
+
+<histogram name="Cryptohome.{ErrorBucket}.LeafErrorWithTPM"
+    enum="CryptohomeErrorLocationWithTPMError" expires_after="2023-09-03">
+  <owner>zuan@chromium.org</owner>
+  <owner>cros-hwsec+uma@chromium.org</owner>
+  <summary>
+    Background context on this histogram: A CryptohomeError in this context
+    refers to an error that occurred in response to a dbus request to selected
+    cryptohomed APIs. The set of APIs with this CryptohomeError is generally
+    those related to authentication, and contains CryptohomeErrorInfo field in
+    the dbus Reply protobuf. Currently that includes methods that are called
+    during login. A CryptohomeError consists of a linear stack of
+    ErrorLocations, each one of them is an actual line in the cryptohomed
+    codebase which the error passed through, and could have certain attributes,
+    known as ErrorAction attached to them. The ErrorLocation in the bottom of
+    the stack could optionally have a TPM Error Code associated, if the source
+    of error is TPM related.
+
+    For this histogram, for every CryptohomeError that occurred, we report the
+    last ErrorLocation and the second last ErrorLocation in the CryptohomeError,
+    if the last ErrorLocation have a TPM Error Code associated with it. The
+    upper and lower 16-bit value of the reported value contains the second last
+    ErrorLocation and the TPM Error Code, correspondingly.
+
+    This histogram is also separated into several {ErrorBucket}s. The most
+    standard error bucket is 'Error', which collects the errors populated in
+    dbus responses. Other buckets are errors we collect in some subrountines,
+    like migration. Migration errors are not surfaced to dbus responses, but
+    silently fail instead. We collect those errors in separate buckets.
+
+    This is useful to cryptohome developers because frequently, the last and
+    second last ErrorLocation in the stack would be able to uniquely identify
+    the error, and this histogram doesn't involve hashing, so it woul dbe more
+    convenient for the developers.
+  </summary>
+  <token key="ErrorBucket">
+    <variant name="Error"/>
+    <variant name="RecreateAuthFactorError.Pin"/>
+    <variant name="UssMigrationError"/>
+  </token>
+</histogram>
+
 <histogram name="CryptohomeClient" units="ms" expires_after="2023-07-24">
   <owner>zuan@chromium.org</owner>
   <owner>cros-hwsec+uma@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml
index 1673696..0376d727 100644
--- a/tools/metrics/histograms/metadata/password/histograms.xml
+++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -3151,6 +3151,36 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.PromoCard.ActionButtonClicked"
+    enum="PasswordManagerPromoCard" expires_after="2023-09-30">
+  <owner>vasilii@chromium.org</owner>
+  <owner>vsemeniuk@google.com</owner>
+  <summary>
+    Records the type of a promo card for which user clicked action button in the
+    Password Manager UI. Recorded when a promo card action button is clicked.
+  </summary>
+</histogram>
+
+<histogram name="PasswordManager.PromoCard.Dismissed"
+    enum="PasswordManagerPromoCard" expires_after="2023-09-30">
+  <owner>vasilii@chromium.org</owner>
+  <owner>vsemeniuk@google.com</owner>
+  <summary>
+    Records the type of a promo card dismissed in the Password Manager UI.
+    Recorded when a promo card is dismissed.
+  </summary>
+</histogram>
+
+<histogram name="PasswordManager.PromoCard.Shown"
+    enum="PasswordManagerPromoCard" expires_after="2023-09-30">
+  <owner>vasilii@chromium.org</owner>
+  <owner>vsemeniuk@google.com</owner>
+  <summary>
+    Records the type of a promo card shown in the Password Manager UI. Recorded
+    when a promo card is shown.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.ProvisionalSaveFailure"
     enum="ProvisionalSaveFailure" expires_after="2023-10-31">
   <owner>kazinova@google.com</owner>
@@ -4146,7 +4176,7 @@
 
 <histogram
     name="PasswordManager.{Store}TimesPasswordUsed3.{PasswordType}{CustomPassphraseStatus}"
-    units="PasswordUses" expires_after="2023-06-01">
+    units="PasswordUses" expires_after="2023-11-01">
   <owner>kazinova@google.com</owner>
   <owner>battre@chromium.org</owner>
   <owner>mamir@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/performance_manager/histograms.xml b/tools/metrics/histograms/metadata/performance_manager/histograms.xml
index 653ba2a..3188316 100644
--- a/tools/metrics/histograms/metadata/performance_manager/histograms.xml
+++ b/tools/metrics/histograms/metadata/performance_manager/histograms.xml
@@ -14,6 +14,26 @@
 
 <histograms>
 
+<histogram name="PerformanceManager.Experimental.AccessibilityModeFlag"
+    enum="AccessibilityModeFlagEnum" expires_after="2023-10-21">
+  <owner>anthonyvd@chromium.org</owner>
+  <owner>chrome-catan@google.com</owner>
+  <summary>
+    Whether individual accessibility mode flags are set. Recorded with every UMA
+    report to attempt to slice other metrics based on which a11y flags are set.
+  </summary>
+</histogram>
+
+<histogram name="PerformanceManager.Experimental.HasAccessibilityModeFlag"
+    enum="Boolean" expires_after="2023-10-21">
+  <owner>anthonyvd@chromium.org</owner>
+  <owner>chrome-catan@google.com</owner>
+  <summary>
+    Whether any accessibility mode flags are set. Recorded with every UMA report
+    to attempt to slice other metrics based on whether a11y is active.
+  </summary>
+</histogram>
+
 <histogram name="PerformanceManager.UserTuning.EfficiencyMode"
     enum="EfficiencyMode" expires_after="2023-09-10">
   <owner>anthonyvd@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index 823a24e..8ea4c49 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -485,38 +485,6 @@
   </summary>
 </histogram>
 
-<histogram name="Tab.TabUnder.PopupToTabUnderTime" units="ms"
-    expires_after="M85">
-  <owner>csharrison@chromium.org</owner>
-  <summary>
-    Measures the time from when a tab opens a popup to when it performs a
-    tab-under (i.e. navigates cross origin, in the background without a user
-    gesture).
-  </summary>
-</histogram>
-
-<histogram name="Tab.TabUnder.VisibleTime" units="ms" expires_after="M77">
-  <owner>csharrison@chromium.org</owner>
-  <summary>
-    Measures the total time a tab is visible after it navigates itself
-    cross-origin in the background, without a user gesture. The tab must have
-    opened a popup since the last user gesture in the tab. Measured at
-    WebContents destruction. The total visible time for the tab is the sum of
-    this metric and Tab.TabUnder.VisibleTimeBefore.
-  </summary>
-</histogram>
-
-<histogram name="Tab.TabUnder.VisibleTimeBefore" units="ms" expires_after="M85">
-  <owner>csharrison@chromium.org</owner>
-  <summary>
-    Measures the total time a tab is visible before it navigates itself
-    cross-origin in the background, without a user gesture. The tab must have
-    opened a popup since the last user gesture in the tab. Measured at
-    WebContents destruction. The total visible time for the tab is the sum of
-    this metric and Tab.TabUnder.VisibleTime.
-  </summary>
-</histogram>
-
 <histogram name="Tab.TotalTabCount.BeforeLeavingApp" units="tabs"
     expires_after="M85">
   <owner>tedchoc@chromium.org</owner>
@@ -528,15 +496,6 @@
   </summary>
 </histogram>
 
-<histogram name="Tab.VisibleTime" units="ms" expires_after="M77">
-  <owner>csharrison@chromium.org</owner>
-  <summary>
-    Measures the total time a tab is visible. Measured at the WebContents layer
-    so this metric does not attempt to account for things like session restore.
-    Logged at WebContents destruction.
-  </summary>
-</histogram>
-
 <histogram name="TabGroups.CollapsedGroupCountPerLoad" units="groups"
     expires_after="2023-10-22">
   <owner>dpenning@chromium.org</owner>
diff --git a/tools/metrics/histograms/print_expanded_histograms.py b/tools/metrics/histograms/print_expanded_histograms.py
index 625eee8d..6b7766f 100755
--- a/tools/metrics/histograms/print_expanded_histograms.py
+++ b/tools/metrics/histograms/print_expanded_histograms.py
@@ -46,6 +46,12 @@
 
 
 def main(args):
+  try:
+    pattern = re.compile(args.pattern)
+  except re.error:
+    print("Non valid regex pattern.")
+    return
+
   # Extract all histograms into a dict.
   doc = merge_xml.MergeFiles(filenames=histogram_paths.ALL_XMLS,
                              should_expand_owners=True)
@@ -58,7 +64,7 @@
   configuration = doc.createElement('histogram-configuration')
   histograms_node = doc.createElement('histograms')
   for name, histogram in histograms.items():
-    if re.match(args.pattern, name):
+    if re.match(pattern, name):
       histograms_node.appendChild(ConstructHistogram(doc, name, histogram))
   configuration.appendChild(histograms_node)
   doc.appendChild(configuration)
@@ -69,7 +75,7 @@
   parser = argparse.ArgumentParser(description='Print expanded histograms.')
   parser.add_argument('--pattern',
                       type=str,
-                      default='*',
+                      default='.*',
                       help='The histogram regex you want to print.')
   args = parser.parse_args()
   main(args)
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index c07bdbcf..d132925c 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -20381,6 +20381,36 @@
   </metric>
 </event>
 
+<event name="SamesiteRedirectContextDowngrade">
+  <owner>bingler@chromium.org</owner>
+  <summary>
+    A collection of metrics which are recorded for cookies whose inclusion would
+    be changed if the redirect chain was considered in their same-site
+    calculation. This change in inclusion is because the same-site context would
+    &quot;downgrade&quot; from a more permissive context to a less permissive
+    context, one which may not allow a cookie's inclusion.
+  </summary>
+  <metric name="AgePerCookie">
+    <summary>
+      Records the age of the cookies, in minutes, for cookies which are being
+      read (on a requset or via JS). The value rounded down to the exponential
+      bucket with factor of 2.0.
+    </summary>
+  </metric>
+  <metric name="SamesiteValueReadPerCookie" enum="SameSiteCookieValue">
+    <summary>
+      Records the SameSite value of the cookie for cookies which are being read
+      (on a request or via JS).
+    </summary>
+  </metric>
+  <metric name="SamesiteValueWritePerCookie" enum="SameSiteCookieValue">
+    <summary>
+      Records the SameSite value of the cookie for cookies which are being
+      written (on a response or via JS).
+    </summary>
+  </metric>
+</event>
+
 <event name="SchemefulSameSiteContextDowngrade">
   <owner>bingler@chromium.org</owner>
   <metric name="RequestPerCookie"
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index d1c64e2..cab6078 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -6,7 +6,7 @@
         },
         "win": {
             "hash": "4aa50a24ddb9a4c3ed8030e9f42f8f4bca2de186",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/20b114cd063623e63ef1b0a31167d60081567e51/trace_processor_shell.exe"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/28f2116ecab68413f729f6ce15cbebd450bb8389/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "1d229abc94dea54ab4bb4327e78e18f942d08bf9",
@@ -14,15 +14,15 @@
         },
         "mac": {
             "hash": "3543a8889331e0aa162550aa9c4dc4c97349f19c",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/20b114cd063623e63ef1b0a31167d60081567e51/trace_processor_shell"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/28f2116ecab68413f729f6ce15cbebd450bb8389/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "7a4026b8718994145a52586fdec6e9447573345a",
             "full_remote_path": "perfetto-luci-artifacts/adbbb6c78e3a86c5e87b0338d9e42eb6b4ddbf4d/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "e37031bb126628ab866fb6be371269051e802e91",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/20b114cd063623e63ef1b0a31167d60081567e51/trace_processor_shell"
+            "hash": "b1073e513de0866cfe6345af838261a72aabfd22",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/f2da6df2f144e41e1c1428f11e8b388eaf8a2209/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc
index 85aa276..d699c9e 100644
--- a/ui/accessibility/platform/ax_platform_node_base.cc
+++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -1262,10 +1262,11 @@
         break;
       case ax::mojom::DescriptionFrom::kNone:
       case ax::mojom::DescriptionFrom::kAttributeExplicitlyEmpty:
-        NOTREACHED();
+        break;
     }
-    DCHECK(!from.empty());
-    AddAttributeToList("description-from", from, attributes);
+    if (!from.empty()) {
+      AddAttributeToList("description-from", from, attributes);
+    }
   }
 
   AddAttributeToList(ax::mojom::StringAttribute::kAriaBrailleLabel,
diff --git a/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java b/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
index af229106..4be06ebc1 100644
--- a/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
+++ b/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
@@ -219,10 +219,20 @@
 
         // Force WindowAndroid#showIntent to succeed and make sure the pipeline remains open when
         // the test reruns.
-        Mockito.doAnswer((invocation) -> { return true; })
+        IntentArgumentMatcher chooserIntentArgumentMatcher =
+                new IntentArgumentMatcher(new Intent(Intent.ACTION_CHOOSER));
+        Mockito.doAnswer((invocation) -> {
+                   Intent chooserIntent = (Intent) invocation.getArguments()[0];
+                   Intent getContentIntent = (Intent) chooserIntent.getExtra(Intent.EXTRA_INTENT);
+                   assertEquals(null, getContentIntent.getExtra(Intent.EXTRA_ALLOW_MULTIPLE));
+                   assertEquals("*/*", getContentIntent.getType());
+                   assertEquals(null, getContentIntent.getExtra(Intent.EXTRA_MIME_TYPES));
+                   assertEquals(null, getContentIntent.getExtra(Intent.EXTRA_INITIAL_INTENTS));
+                   return true;
+               })
                 .when(windowAndroid)
-                .showIntent(
-                        (Intent) anyObject(), (WindowAndroid.IntentCallback) anyObject(), anyInt());
+                .showIntent(ArgumentMatchers.argThat(chooserIntentArgumentMatcher),
+                        (WindowAndroid.IntentCallback) anyObject(), anyInt());
 
         // Rerun the test. Because showIntent now reports success, the upload should still be in
         // progress.
diff --git a/ui/aura/test/run_all_unittests.cc b/ui/aura/test/run_all_unittests.cc
index 683b6cf..2f6b8f4 100644
--- a/ui/aura/test/run_all_unittests.cc
+++ b/ui/aura/test/run_all_unittests.cc
@@ -8,14 +8,17 @@
 #include "mojo/core/embedder/embedder.h"
 #include "ui/aura/env.h"
 #include "ui/aura/test/aura_test_suite.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/test/gl_surface_test_support.h"
 
 class AuraTestSuite;
 
 namespace {
+
 AuraTestSuite* g_test_suite = nullptr;
-}
+
+}  // namespace
 
 class AuraTestSuite : public base::TestSuite {
  public:
@@ -34,6 +37,10 @@
     base::TestSuite::Initialize();
     gl::GLSurfaceTestSupport::InitializeOneOff();
     env_ = aura::Env::CreateInstance();
+
+    ui::ResourceBundle::InitSharedInstanceWithLocale(
+        "en-US", /*delegate=*/nullptr,
+        ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES);
   }
 
   void Shutdown() override {
diff --git a/ui/base/clipboard/clipboard.cc b/ui/base/clipboard/clipboard.cc
index 8cb3edd..a328ffc 100644
--- a/ui/base/clipboard/clipboard.cc
+++ b/ui/base/clipboard/clipboard.cc
@@ -338,6 +338,25 @@
   return id;
 }
 
+void Clipboard::AddObserver(ClipboardWriteObserver* observer) {
+  write_observers_.AddObserver(observer);
+}
+
+void Clipboard::RemoveObserver(ClipboardWriteObserver* observer) {
+  write_observers_.RemoveObserver(observer);
+}
+
+void Clipboard::NotifyCopyWithUrl(const base::StringPiece text,
+                                  const GURL& frame,
+                                  const GURL& main_frame) {
+  GURL text_url(text);
+  if (text_url.is_valid()) {
+    for (ClipboardWriteObserver& obs : write_observers_) {
+      obs.OnCopyURL(text_url, frame, main_frame);
+    }
+  }
+}
+
 // static
 std::vector<base::PlatformThreadId>& Clipboard::AllowedThreads() {
   static base::NoDestructor<std::vector<base::PlatformThreadId>>
diff --git a/ui/base/clipboard/clipboard.h b/ui/base/clipboard/clipboard.h
index 5c3ae82..8b86333 100644
--- a/ui/base/clipboard/clipboard.h
+++ b/ui/base/clipboard/clipboard.h
@@ -16,7 +16,9 @@
 #include "base/component_export.h"
 #include "base/containers/flat_map.h"
 #include "base/functional/callback.h"
+#include "base/observer_list.h"
 #include "base/process/process.h"
+#include "base/strings/string_piece.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_checker.h"
@@ -67,6 +69,18 @@
       base::OnceCallback<void(std::u16string title, GURL url)>;
   using ReadDataCallback = base::OnceCallback<void(std::string result)>;
 
+  // An observer interface for content copied to the clipboard.
+  class ClipboardWriteObserver : public base::CheckedObserver {
+   public:
+    ~ClipboardWriteObserver() override = default;
+
+    // Notifies observers when a valid URL is copied to the clipboard with a
+    // valid source URL
+    virtual void OnCopyURL(const GURL& url,
+                           const GURL& source_frame_url,
+                           const GURL& source_main_frame_url) = 0;
+  };
+
   Clipboard(const Clipboard&) = delete;
   Clipboard& operator=(const Clipboard&) = delete;
 
@@ -274,6 +288,18 @@
       ClipboardBuffer buffer,
       const DataTransferEndpoint* data_dst) const;
 
+  // Add an observer for text pasted to clipboard with a URL source.
+  void AddObserver(ClipboardWriteObserver* observer);
+
+  // Remove an observer for text pasted to clipboard with a URL source.
+  void RemoveObserver(ClipboardWriteObserver* observer);
+
+  // Notify all subscribers of new text pasted to the clipboard when there is a
+  // source URL.
+  void NotifyCopyWithUrl(const base::StringPiece text,
+                         const GURL& frame,
+                         const GURL& main_frame);
+
  protected:
   // PortableFormat designates the type of data to be stored in the clipboard.
   // This designation is shared across all OSes. The system-specific designation
@@ -439,6 +465,8 @@
 
   // Mutex that controls access to |g_clipboard_map|.
   static base::Lock& ClipboardMapLock();
+
+  base::ObserverList<ClipboardWriteObserver> write_observers_;
 };
 
 }  // namespace ui
diff --git a/ui/base/clipboard/scoped_clipboard_writer.cc b/ui/base/clipboard/scoped_clipboard_writer.cc
index 069a4481..0aef31c 100644
--- a/ui/base/clipboard/scoped_clipboard_writer.cc
+++ b/ui/base/clipboard/scoped_clipboard_writer.cc
@@ -43,6 +43,17 @@
         Clipboard::ObjectMapParams(std::move(parameters),
                                    ClipboardContentType::kUnsanitized);
   }
+
+  if (main_frame_url_.is_valid() || frame_url_.is_valid()) {
+    auto it = objects_.find(Clipboard::PortableFormat::kText);
+    if (it != objects_.end()) {
+      auto current = *(it->second.data.begin());
+      base::StringPiece text(current.data(), current.size());
+      Clipboard::GetForCurrentThread()->NotifyCopyWithUrl(text, frame_url_,
+                                                          main_frame_url_);
+    }
+  }
+
   if (!objects_.empty() || !platform_representations_.empty()) {
     Clipboard::GetForCurrentThread()->WritePortableAndPlatformRepresentations(
         buffer_, objects_, std::move(platform_representations_),
@@ -58,6 +69,12 @@
   data_src_ = std::move(data_src);
 }
 
+void ScopedClipboardWriter::SetDataSourceURL(const GURL& main_frame,
+                                             const GURL& frame_url) {
+  main_frame_url_ = main_frame;
+  frame_url_ = frame_url;
+}
+
 void ScopedClipboardWriter::WriteText(const std::u16string& text) {
   RecordWrite(ClipboardFormatMetric::kText);
   std::string utf8_text = base::UTF16ToUTF8(text);
diff --git a/ui/base/clipboard/scoped_clipboard_writer.h b/ui/base/clipboard/scoped_clipboard_writer.h
index 2a9964f..569aa7f 100644
--- a/ui/base/clipboard/scoped_clipboard_writer.h
+++ b/ui/base/clipboard/scoped_clipboard_writer.h
@@ -44,6 +44,10 @@
   // Sets the clipboard's source metadata.
   void SetDataSource(std::unique_ptr<DataTransferEndpoint> data_src);
 
+  // Set the clipboards source URL.
+  // Typically used for attributing content originally copied from a web page.
+  void SetDataSourceURL(const GURL& main_frame, const GURL& frame);
+
   // Converts |text| to UTF-8 and adds it to the clipboard.
   void WriteText(const std::u16string& text);
 
@@ -122,6 +126,12 @@
   // not set, or the source of the data can't be represented by
   // DataTransferEndpoint.
   std::unique_ptr<DataTransferEndpoint> data_src_;
+
+  // The URL of the mainframe the contents are from.
+  GURL main_frame_url_;
+
+  // The URL of the frame the contents are from.
+  GURL frame_url_;
 };
 
 }  // namespace ui
diff --git a/ui/base/layout.cc b/ui/base/layout.cc
index 6ed1bd1b..9b1a348 100644
--- a/ui/base/layout.cc
+++ b/ui/base/layout.cc
@@ -10,6 +10,7 @@
 #include <cmath>
 #include <limits>
 
+#include "base/check.h"
 #include "base/check_op.h"
 #include "build/build_config.h"
 #include "ui/base/pointer/pointer_device.h"
@@ -27,8 +28,11 @@
 
 void SetSupportedResourceScaleFactors(
     const std::vector<ResourceScaleFactor>& scale_factors) {
-  if (g_supported_resource_scale_factors != nullptr)
+  CHECK(!scale_factors.empty());
+
+  if (g_supported_resource_scale_factors != nullptr) {
     delete g_supported_resource_scale_factors;
+  }
 
   g_supported_resource_scale_factors =
       new std::vector<ResourceScaleFactor>(scale_factors);
@@ -50,29 +54,48 @@
 }
 
 const std::vector<ResourceScaleFactor>& GetSupportedResourceScaleFactors() {
-  DCHECK(g_supported_resource_scale_factors != nullptr);
+  CHECK_NE(g_supported_resource_scale_factors, nullptr)
+      << "ResourceBundle needs to be intialized.";
+
   return *g_supported_resource_scale_factors;
 }
 
 ResourceScaleFactor GetSupportedResourceScaleFactor(float scale) {
-  DCHECK(g_supported_resource_scale_factors != nullptr);
+  CHECK_NE(g_supported_resource_scale_factors, nullptr)
+      << "ResourceBundle needs to be intialized.";
+
   ResourceScaleFactor closest_match = k100Percent;
-  float smallest_diff =  std::numeric_limits<float>::max();
-  for (auto scale_factor : *g_supported_resource_scale_factors) {
-    float diff = std::abs(GetScaleForResourceScaleFactor(scale_factor) - scale);
+  float smallest_diff = std::numeric_limits<float>::max();
+  for (const auto scale_factor : *g_supported_resource_scale_factors) {
+    const float diff =
+        std::abs(GetScaleForResourceScaleFactor(scale_factor) - scale);
     if (diff < smallest_diff) {
       closest_match = scale_factor;
       smallest_diff = diff;
+    } else {
+      break;
     }
   }
-  DCHECK_NE(closest_match, kScaleFactorNone);
+
+  CHECK_NE(closest_match, kScaleFactorNone);
   return closest_match;
 }
 
+ResourceScaleFactor GetMaxSupportedResourceScaleFactor() {
+  CHECK_NE(g_supported_resource_scale_factors, nullptr)
+      << "ResourceBundle needs to be intialized.";
+
+  return g_supported_resource_scale_factors->back();
+}
+
 bool IsSupportedScale(float scale) {
-  for (auto scale_factor_idx : *g_supported_resource_scale_factors) {
-    if (GetScaleForResourceScaleFactor(scale_factor_idx) == scale)
+  CHECK_NE(g_supported_resource_scale_factors, nullptr)
+      << "ResourceBundle needs to be intialized.";
+
+  for (const auto scale_factor_idx : *g_supported_resource_scale_factors) {
+    if (GetScaleForResourceScaleFactor(scale_factor_idx) == scale) {
       return true;
+    }
   }
   return false;
 }
diff --git a/ui/base/layout.h b/ui/base/layout.h
index ba382ff..9251363 100644
--- a/ui/base/layout.h
+++ b/ui/base/layout.h
@@ -28,11 +28,13 @@
 const std::vector<ResourceScaleFactor>& GetSupportedResourceScaleFactors();
 
 // Returns the supported ResourceScaleFactor which most closely matches |scale|.
-// Converting from float to ResourceScaleFactor is inefficient and should be
-// done as little as possible.
 COMPONENT_EXPORT(UI_BASE)
 ResourceScaleFactor GetSupportedResourceScaleFactor(float image_scale);
 
+// Returns the maximum supported ResourceScaleFactor.
+COMPONENT_EXPORT(UI_BASE)
+ResourceScaleFactor GetMaxSupportedResourceScaleFactor();
+
 // Returns the ResourceScaleFactor used by |view|.
 COMPONENT_EXPORT(UI_BASE)
 float GetScaleFactorForNativeView(gfx::NativeView view);
diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc
index a013ab3..c6b1c58 100644
--- a/ui/base/resource/resource_bundle.cc
+++ b/ui/base/resource/resource_bundle.cc
@@ -888,7 +888,7 @@
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
   return max_scale_factor_;
 #else
-  return GetSupportedResourceScaleFactors().back();
+  return GetMaxSupportedResourceScaleFactor();
 #endif
 }
 
diff --git a/ui/gfx/image/image_skia.cc b/ui/gfx/image/image_skia.cc
index 41f317f..d1b8637 100644
--- a/ui/gfx/image/image_skia.cc
+++ b/ui/gfx/image/image_skia.cc
@@ -10,6 +10,7 @@
 #include <limits>
 #include <memory>
 
+#include "base/check.h"
 #include "base/check_op.h"
 #include "base/command_line.h"
 #include "base/containers/contains.h"
@@ -237,8 +238,9 @@
 
     ImageSkiaRep image;
     float resource_scale = scale;
-    if (!HasRepresentationAtAllScales() && g_supported_scales)
+    if (!HasRepresentationAtAllScales()) {
       resource_scale = ImageSkia::MapToResourceScale(scale);
+    }
     if (scale != resource_scale) {
       auto iter = FindRepresentation(resource_scale, fetch_new_image);
       CHECK(iter != image_reps_.end());
@@ -320,17 +322,19 @@
 
 // static
 const std::vector<float>& ImageSkia::GetSupportedScales() {
-  DCHECK(g_supported_scales != NULL);
+  CHECK_NE(g_supported_scales, nullptr);
   return *g_supported_scales;
 }
 
 // static
 float ImageSkia::GetMaxSupportedScale() {
+  CHECK_NE(g_supported_scales, nullptr);
   return g_supported_scales->back();
 }
 
 // static
 float ImageSkia::MapToResourceScale(float scale) {
+  CHECK_NE(g_supported_scales, nullptr);
   // Returns an exact match, a smaller scale within 0.2 units, the nearest
   // larger scale, or the min/max supported scale.
   for (float supported_scale : *g_supported_scales) {
diff --git a/ui/ozone/platform/scenic/scenic_window.cc b/ui/ozone/platform/scenic/scenic_window.cc
index 1bfa940..ff7074bb 100644
--- a/ui/ozone/platform/scenic/scenic_window.cc
+++ b/ui/ozone/platform/scenic/scenic_window.cc
@@ -6,7 +6,6 @@
 
 #include <fidl/fuchsia.ui.pointer/cpp/hlcpp_conversion.h>
 #include <fidl/fuchsia.ui.views/cpp/hlcpp_conversion.h>
-#include <fuchsia/sys/cpp/fidl.h>
 #include <lib/async/default.h>
 #include <lib/sys/cpp/component_context.h>