diff --git a/DEPS b/DEPS
index 9f3afdd..b066896 100644
--- a/DEPS
+++ b/DEPS
@@ -308,7 +308,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'src_internal_revision': 'ee061f481382201645e2569b5cfb8bc70f5685ef',
+  'src_internal_revision': '9f3d71f2b078ed96b1334c3921e47d2a2735a9c5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
@@ -316,11 +316,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '408938972fdca848d564d0bd80139df8a90e53a5',
+  'v8_revision': '68087ab41a76501a5364273a52cd395f0e7033b3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '69f5e9ca60cd6adfecd9eb8c969beeec30a4813d',
+  'angle_revision': '1ceddbf6977926d674c0c5a78b398f684d0052b1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -347,7 +347,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling googletest
   # and whatever else without interference from each other.
-  'googletest_revision': '76bb2afb8b522d24496ad1c757a49784fbfa2e42',
+  'googletest_revision': 'dda72ef32181edbfcd32a8c52b4740cd8061ab6f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling lighttpd
   # and whatever else without interference from each other.
@@ -387,7 +387,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling chromium_variations
   # and whatever else without interference from each other.
-  'chromium_variations_revision': '32e2e5c8d0343434cf154f2b928775c2d95ad8c5',
+  'chromium_variations_revision': '2f49c50b79ab7a6ee16f324656f0185a44fa50a6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # and whatever else without interference from each other.
@@ -827,12 +827,12 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '5ac8fb250ea25c91a12158f768d4f5c03976f15e',
+    'eadffcd4b5ec79ec69e29f75c6695edf9c69aff1',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + '7918c586771aed5e170cb5ce33fdfc38f6203063',
+    'url': Var('chromium_git') + '/website.git' + '@' + 'f2eab19faaecbab4992d4633704136e5778faabc',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -1049,7 +1049,7 @@
       'packages': [
           {
                'package': 'chromium/third_party/android_build_tools/lint',
-               'version': 'H3namO3zonlUj075eXGd_my1zHGpGDoXubhIWd9CG0EC',
+               'version': 'KICH09fjzlFXmYj2dj16tG91b6Ueo_BM3DDwKcjK0b0C',
           },
       ],
       'condition': 'checkout_android',
@@ -1199,7 +1199,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1ac3eb7b9844751478c7bdae4614f4d1e8b9b0f8',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'fbb0301f1f70813fb62e1f64e05410b730c8417e',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1654,7 +1654,7 @@
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '09a4f3ec842a8932341b195c5b01e141c8a16eb7',
 
   'src/third_party/openscreen/src':
-    Var('chromium_git') + '/openscreen' + '@' + 'ab2e34151f1f147f3dd56f73cdf3ea5c6ad2d0a5',
+    Var('chromium_git') + '/openscreen' + '@' + '614d391f2236a5035b6e7be8d0278db63bddbce0',
 
   'src/third_party/openxr/src': {
     'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '95fe35ffb383710a6e0567e958ead9a3b66e930c',
@@ -1850,7 +1850,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '98673cc24786be6c10dd8908e0b0b4ed27625c6a',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'e5ac106a357e2a1a088b732f0232d470de42f0cb',
+    Var('webrtc_git') + '/src.git' + '@' + 'ede75295d43032370f24bd4295693972ad27aaf0',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
diff --git a/ash/birch/birch_model.cc b/ash/birch/birch_model.cc
index eb8c0208..7be307b 100644
--- a/ash/birch/birch_model.cc
+++ b/ash/birch/birch_model.cc
@@ -5,6 +5,7 @@
 #include "ash/birch/birch_model.h"
 
 #include <algorithm>
+#include <limits>
 #include <memory>
 #include <vector>
 
@@ -13,6 +14,7 @@
 #include "ash/birch/birch_weather_provider.h"
 #include "ash/constants/ash_features.h"
 #include "ash/shell.h"
+#include "base/containers/cxx20_erase_vector.h"
 #include "base/functional/callback_forward.h"
 #include "base/time/time.h"
 
@@ -145,6 +147,80 @@
   return all_items;
 }
 
+std::vector<std::unique_ptr<BirchItem>> BirchModel::GetItemsForDisplay() {
+  std::vector<std::unique_ptr<BirchItem>> all_items = GetAllItems();
+
+  // Remove any items with no ranking.
+  base::EraseIf(all_items, [](const auto& item) {
+    return item->ranking == std::numeric_limits<float>::max();
+  });
+
+  std::vector<std::unique_ptr<BirchItem>> results;
+
+  // Make multiple passes through all items, with each pass putting at most one
+  // item of each type in the results vector.
+  constexpr int kMaxResults = 4;
+  for (int pass = 0; pass < 2 && results.size() < kMaxResults; ++pass) {
+    bool have_calendar = false;
+    bool have_attachment = false;
+    bool have_tab = false;
+    bool have_file = false;
+    bool have_weather = false;
+    for (auto it = all_items.begin(); it != all_items.end(); ++it) {
+      // Early exit once enough results are found.
+      if (results.size() == kMaxResults) {
+        break;
+      }
+      // An earlier pass might have left this item null.
+      if (!*it) {
+        continue;
+      }
+      // If this is the first time an item of this type is encountered, move it
+      // into the results list. Set the `all_items` entry to null so the item
+      // will be ignored on future passes through the list.
+      if ((*it)->GetItemType() == BirchCalendarItem::kItemType &&
+          !have_calendar) {
+        results.push_back(std::move(*it));
+        *it = nullptr;
+        have_calendar = true;
+        continue;
+      }
+      if ((*it)->GetItemType() == BirchAttachmentItem::kItemType &&
+          !have_attachment) {
+        results.push_back(std::move(*it));
+        *it = nullptr;
+        have_attachment = true;
+        continue;
+      }
+      if ((*it)->GetItemType() == BirchTabItem::kItemType && !have_tab) {
+        results.push_back(std::move(*it));
+        *it = nullptr;
+        have_tab = true;
+        continue;
+      }
+      if ((*it)->GetItemType() == BirchFileItem::kItemType && !have_file) {
+        results.push_back(std::move(*it));
+        *it = nullptr;
+        have_file = true;
+        continue;
+      }
+      if ((*it)->GetItemType() == BirchWeatherItem::kItemType &&
+          !have_weather) {
+        results.push_back(std::move(*it));
+        *it = nullptr;
+        have_weather = true;
+        continue;
+      }
+    }
+  }
+  // Sort the returned items by ranking.
+  std::sort(results.begin(), results.end(),
+            [](const auto& item_a, const auto& item_b) {
+              return item_a->ranking < item_b->ranking;
+            });
+  return results;
+}
+
 bool BirchModel::IsDataFresh() {
   return (!birch_client_ ||
           (is_calendar_data_fresh_ && is_attachment_data_fresh_ &&
diff --git a/ash/birch/birch_model.h b/ash/birch/birch_model.h
index e8a137c..85d9a29 100644
--- a/ash/birch/birch_model.h
+++ b/ash/birch/birch_model.h
@@ -56,6 +56,10 @@
 
   std::vector<std::unique_ptr<BirchItem>> GetAllItems();
 
+  // Returns at most 4 items. Prefers higher ranked items. Prefers not to
+  // return multiple items of the same type, where possible.
+  std::vector<std::unique_ptr<BirchItem>> GetItemsForDisplay();
+
   // Returns whether all data in the model is currently fresh.
   bool IsDataFresh();
 
diff --git a/ash/birch/birch_model_unittest.cc b/ash/birch/birch_model_unittest.cc
index cff16725..fec132b 100644
--- a/ash/birch/birch_model_unittest.cc
+++ b/ash/birch/birch_model_unittest.cc
@@ -434,4 +434,168 @@
   EXPECT_STREQ(all_items[4]->GetItemType(), BirchWeatherItem::kItemType);
 }
 
+TEST_F(BirchModelTest, GetItemsForDisplay_EnoughTypes) {
+  BirchModel* model = Shell::Get()->birch_model();
+
+  // Insert one item of each type.
+  std::vector<BirchCalendarItem> calendar_item_list;
+  calendar_item_list.emplace_back(u"Event 1");
+  calendar_item_list.back().ranking = 5.f;
+  model->SetCalendarItems(std::move(calendar_item_list));
+
+  std::vector<BirchAttachmentItem> attachment_item_list;
+  attachment_item_list.emplace_back(u"Attachment 1");
+  attachment_item_list.back().ranking = 4.f;
+  model->SetAttachmentItems(std::move(attachment_item_list));
+
+  std::vector<BirchTabItem> tab_item_list;
+  tab_item_list.emplace_back(u"tab", GURL("foo.bar"), base::Time(),
+                             GURL("favicon"), "session");
+  tab_item_list.back().ranking = 3.f;
+  model->SetRecentTabItems(std::move(tab_item_list));
+
+  std::vector<BirchFileItem> file_item_list;
+  file_item_list.emplace_back(base::FilePath("test path 1"), base::Time());
+  file_item_list.back().ranking = 2.f;
+  model->SetFileSuggestItems(std::move(file_item_list));
+
+  std::vector<BirchWeatherItem> weather_item_list;
+  weather_item_list.emplace_back(u"cloudy", u"16 c", ui::ImageModel());
+  weather_item_list.back().ranking = 1.f;
+  model->SetWeatherItems(std::move(weather_item_list));
+
+  std::vector<std::unique_ptr<BirchItem>> items = model->GetItemsForDisplay();
+
+  // The maximum of 4 items are returned.
+  ASSERT_EQ(items.size(), 4u);
+
+  // The items are in priority order.
+  EXPECT_FLOAT_EQ(items[0]->ranking, 1.f);
+  EXPECT_STREQ(items[0]->GetItemType(), BirchWeatherItem::kItemType);
+  EXPECT_FLOAT_EQ(items[1]->ranking, 2.f);
+  EXPECT_STREQ(items[1]->GetItemType(), BirchFileItem::kItemType);
+  EXPECT_FLOAT_EQ(items[2]->ranking, 3.f);
+  EXPECT_STREQ(items[2]->GetItemType(), BirchTabItem::kItemType);
+  EXPECT_FLOAT_EQ(items[3]->ranking, 4.f);
+  EXPECT_STREQ(items[3]->GetItemType(), BirchAttachmentItem::kItemType);
+}
+
+TEST_F(BirchModelTest, GetItemsForDisplay_AvoidDuplicateTypes) {
+  BirchModel* model = Shell::Get()->birch_model();
+
+  // Insert 2 calendar events with high priority.
+  std::vector<BirchCalendarItem> calendar_item_list;
+  calendar_item_list.emplace_back(u"Event 1");
+  calendar_item_list.back().ranking = 1.f;
+  calendar_item_list.emplace_back(u"Event 2");
+  calendar_item_list.back().ranking = 2.f;
+  model->SetCalendarItems(std::move(calendar_item_list));
+
+  // Then insert 3 other items with lower priority.
+  std::vector<BirchAttachmentItem> attachment_item_list;
+  attachment_item_list.emplace_back(u"Attachment 1");
+  attachment_item_list.back().ranking = 3.f;
+  model->SetAttachmentItems(std::move(attachment_item_list));
+
+  std::vector<BirchTabItem> tab_item_list;
+  tab_item_list.emplace_back(u"tab", GURL("foo.bar"), base::Time(),
+                             GURL("favicon"), "session");
+  tab_item_list.back().ranking = 4.f;
+  model->SetRecentTabItems(std::move(tab_item_list));
+
+  std::vector<BirchFileItem> file_item_list;
+  file_item_list.emplace_back(base::FilePath("test path 1"), base::Time());
+  file_item_list.back().ranking = 5.f;
+  model->SetFileSuggestItems(std::move(file_item_list));
+
+  std::vector<std::unique_ptr<BirchItem>> items = model->GetItemsForDisplay();
+
+  // The maximum of 4 items are returned.
+  ASSERT_EQ(items.size(), 4u);
+
+  // The second calendar event is skipped, despite being high priority, because
+  // the algorithm avoids duplicate types.
+  EXPECT_FLOAT_EQ(items[0]->ranking, 1.f);
+  EXPECT_STREQ(items[0]->GetItemType(), BirchCalendarItem::kItemType);
+  EXPECT_FLOAT_EQ(items[1]->ranking, 3.f);
+  EXPECT_STREQ(items[1]->GetItemType(), BirchAttachmentItem::kItemType);
+  EXPECT_FLOAT_EQ(items[2]->ranking, 4.f);
+  EXPECT_STREQ(items[2]->GetItemType(), BirchTabItem::kItemType);
+  EXPECT_FLOAT_EQ(items[3]->ranking, 5.f);
+  EXPECT_STREQ(items[3]->GetItemType(), BirchFileItem::kItemType);
+}
+
+TEST_F(BirchModelTest, GetItemsForDisplay_TwoDuplicateTypes) {
+  BirchModel* model = Shell::Get()->birch_model();
+
+  // Insert 2 items of the same type.
+  std::vector<BirchCalendarItem> calendar_item_list;
+  calendar_item_list.emplace_back(u"Event 1");
+  calendar_item_list.back().ranking = 1.f;
+  calendar_item_list.emplace_back(u"Event 2");
+  calendar_item_list.back().ranking = 2.f;
+  model->SetCalendarItems(std::move(calendar_item_list));
+
+  // Insert 2 more items of a different type.
+  std::vector<BirchAttachmentItem> attachment_item_list;
+  attachment_item_list.emplace_back(u"Attachment 1");
+  attachment_item_list.back().ranking = 3.f;
+  attachment_item_list.emplace_back(u"Attachment 2");
+  attachment_item_list.back().ranking = 4.f;
+  model->SetAttachmentItems(std::move(attachment_item_list));
+
+  std::vector<std::unique_ptr<BirchItem>> items = model->GetItemsForDisplay();
+
+  ASSERT_EQ(items.size(), 4u);
+  EXPECT_FLOAT_EQ(items[0]->ranking, 1.f);
+  EXPECT_STREQ(items[0]->GetItemType(), BirchCalendarItem::kItemType);
+  EXPECT_FLOAT_EQ(items[1]->ranking, 2.f);
+  EXPECT_STREQ(items[1]->GetItemType(), BirchCalendarItem::kItemType);
+  EXPECT_FLOAT_EQ(items[2]->ranking, 3.f);
+  EXPECT_STREQ(items[2]->GetItemType(), BirchAttachmentItem::kItemType);
+  EXPECT_FLOAT_EQ(items[3]->ranking, 4.f);
+  EXPECT_STREQ(items[3]->GetItemType(), BirchAttachmentItem::kItemType);
+}
+
+TEST_F(BirchModelTest, GetItemsForDisplay_NotEnoughItems) {
+  BirchModel* model = Shell::Get()->birch_model();
+
+  // Insert 3 items of the same type.
+  std::vector<BirchCalendarItem> calendar_item_list;
+  calendar_item_list.emplace_back(u"Event 1");
+  calendar_item_list.back().ranking = 1.f;
+  calendar_item_list.emplace_back(u"Event 2");
+  calendar_item_list.back().ranking = 2.f;
+  calendar_item_list.emplace_back(u"Event 3");
+  calendar_item_list.back().ranking = 3.f;
+  model->SetCalendarItems(std::move(calendar_item_list));
+
+  std::vector<std::unique_ptr<BirchItem>> items = model->GetItemsForDisplay();
+
+  // Only 2 items are returned.
+  ASSERT_EQ(items.size(), 2u);
+  EXPECT_FLOAT_EQ(items[0]->ranking, 1.f);
+  EXPECT_STREQ(items[0]->GetItemType(), BirchCalendarItem::kItemType);
+  EXPECT_FLOAT_EQ(items[1]->ranking, 2.f);
+  EXPECT_STREQ(items[1]->GetItemType(), BirchCalendarItem::kItemType);
+}
+
+TEST_F(BirchModelTest, GetItemsForDisplay_NotRankedItem) {
+  BirchModel* model = Shell::Get()->birch_model();
+
+  // Insert 1 regular item and 1 item with no ranking.
+  std::vector<BirchCalendarItem> calendar_item_list;
+  calendar_item_list.emplace_back(u"Ranked");
+  calendar_item_list.back().ranking = 1.f;
+  calendar_item_list.emplace_back(u"Unranked");
+  model->SetCalendarItems(std::move(calendar_item_list));
+
+  std::vector<std::unique_ptr<BirchItem>> items = model->GetItemsForDisplay();
+
+  // Only 1 item is returned because the unranked item is discarded.
+  ASSERT_EQ(items.size(), 1u);
+  EXPECT_FLOAT_EQ(items[0]->ranking, 1.f);
+  EXPECT_STREQ(items[0]->GetItemType(), BirchCalendarItem::kItemType);
+}
+
 }  // namespace ash
diff --git a/ash/login/ui/lock_screen_media_controls_view.h b/ash/login/ui/lock_screen_media_controls_view.h
index 0ac194664..be21d5a2 100644
--- a/ash/login/ui/lock_screen_media_controls_view.h
+++ b/ash/login/ui/lock_screen_media_controls_view.h
@@ -121,6 +121,9 @@
   void MediaControllerImageChanged(
       media_session::mojom::MediaSessionImageType type,
       const SkBitmap& bitmap) override;
+  // This view is used before `media::kGlobalMediaControlsCrOSUpdatedUI` is
+  // enabled. So we don't need to implement this method since there's no chapter
+  // images in this view.
   void MediaControllerChapterImageChanged(int chapter_index,
                                           const SkBitmap& bitmap) override {}
 
diff --git a/ash/login/ui/lock_screen_media_view.cc b/ash/login/ui/lock_screen_media_view.cc
index ed87bf7..22e9eeab 100644
--- a/ash/login/ui/lock_screen_media_view.cc
+++ b/ash/login/ui/lock_screen_media_view.cc
@@ -270,6 +270,17 @@
   view_->UpdateWithMediaArtwork(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
 }
 
+void LockScreenMediaView::MediaControllerChapterImageChanged(
+    int chapter_index,
+    const SkBitmap& bitmap) {
+  if (switch_media_delay_timer_->IsRunning()) {
+    return;
+  }
+
+  view_->UpdateWithChapterArtwork(chapter_index,
+                                  gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // media_message_center::MediaNotificationContainer implementations:
 
diff --git a/ash/login/ui/lock_screen_media_view.h b/ash/login/ui/lock_screen_media_view.h
index 4c5471b..2973c526 100644
--- a/ash/login/ui/lock_screen_media_view.h
+++ b/ash/login/ui/lock_screen_media_view.h
@@ -69,7 +69,7 @@
       media_session::mojom::MediaSessionImageType type,
       const SkBitmap& bitmap) override;
   void MediaControllerChapterImageChanged(int chapter_index,
-                                          const SkBitmap& bitmap) override {}
+                                          const SkBitmap& bitmap) override;
 
   // media_message_center::MediaNotificationContainer:
   void OnExpanded(bool expanded) override {}
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc
index 6589d642..c1fe13d8 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc
@@ -554,6 +554,15 @@
   UpdateMask(false /* force_update */);
 }
 
+void ArcNotificationContentView::SetVisible(bool visible) {
+  NativeViewHost::SetVisible(visible);
+  if (visible) {
+    EnsureSurfaceAttached();
+  } else {
+    EnsureSurfaceDetached();
+  }
+}
+
 void ArcNotificationContentView::EnsureSurfaceAttached() {
   if (!surface_ || surface_->IsAttached()) {
     return;
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h
index 16e93bf3..e597dae 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h
@@ -65,11 +65,12 @@
   void OnContainerAnimationStarted();
   void OnContainerAnimationEnded();
   void ActivateWidget(bool activate);
-  void EnsureSurfaceAttached();
-  void EnsureSurfaceDetached();
 
   bool slide_in_progress() const { return slide_in_progress_; }
 
+  // views::NativeViewHost
+  void SetVisible(bool visible) override;
+
  private:
   friend class ArcNotificationViewTest;
   friend class ArcNotificationContentViewTest;
@@ -92,6 +93,8 @@
   bool IsExpanded() const;
   void SetManuallyExpandedOrCollapsed(bool value);
   bool IsManuallyExpandedOrCollapsed() const;
+  void EnsureSurfaceAttached();
+  void EnsureSurfaceDetached();
 
   void ShowCopiedSurface();
   void HideCopiedSurface();
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_view.cc b/ash/public/cpp/external_arc/message_center/arc_notification_view.cc
index b96ca3b2..d4495906 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_view.cc
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_view.cc
@@ -273,11 +273,6 @@
 
   collapsed_summary_view_->SetVisible(!expanded);
   content_view_->SetVisible(expanded);
-  if (expanded) {
-    content_view_->EnsureSurfaceAttached();
-  } else {
-    content_view_->EnsureSurfaceDetached();
-  }
 }
 
 void ArcNotificationView::AnimateGroupedChildExpandedCollapse(bool expanded) {
diff --git a/ash/system/input_device_settings/input_device_settings_controller_impl.cc b/ash/system/input_device_settings/input_device_settings_controller_impl.cc
index 8fdde22..e3cf3d93 100644
--- a/ash/system/input_device_settings/input_device_settings_controller_impl.cc
+++ b/ash/system/input_device_settings/input_device_settings_controller_impl.cc
@@ -1756,6 +1756,14 @@
     return;
   }
 
+  // If there is no active account id or local state isn't initialized, use
+  // default graphics tablet settings. This can happen as an uncommon race
+  // condition when first signing in on the login screen.
+  if (!active_account_id_ || !local_state_) {
+    graphics_tablet->settings = mojom::GraphicsTabletSettings::New();
+    return;
+  }
+
   graphics_tablet_pref_handler_->InitializeLoginScreenGraphicsTabletSettings(
       local_state_, active_account_id_.value(), graphics_tablet);
 }
diff --git a/ash/system/input_device_settings/input_device_settings_controller_unittest.cc b/ash/system/input_device_settings/input_device_settings_controller_unittest.cc
index 8d753d4..6645eea 100644
--- a/ash/system/input_device_settings/input_device_settings_controller_unittest.cc
+++ b/ash/system/input_device_settings/input_device_settings_controller_unittest.cc
@@ -287,6 +287,7 @@
   void InitializeWithDefaultKeyboardSettings(
       const mojom::KeyboardPolicies& keyboard_policies,
       mojom::Keyboard* keyboard) override {
+    keyboard->settings = CreateNewKeyboardSettings();
     num_initialize_default_keyboard_settings_calls_++;
   }
 
@@ -489,22 +490,27 @@
     auto user_2_prefs = std::make_unique<TestingPrefServiceSimple>();
     RegisterUserProfilePrefs(user_2_prefs->registry(), /*country=*/"",
                              /*for_test=*/true);
-    session_controller->AddUserSession(kUserEmail1,
-                                       user_manager::UserType::kRegular,
-                                       /*provide_pref_service=*/false);
-    session_controller->SetUserPrefService(account_id_1,
-                                           std::move(user_1_prefs));
-    session_controller->AddUserSession(kUserEmail2,
-                                       user_manager::UserType::kRegular,
-                                       /*provide_pref_service=*/false);
-    session_controller->SetUserPrefService(account_id_2,
-                                           std::move(user_2_prefs));
-    session_controller->AddUserSession(kUserEmail3,
-                                       user_manager::UserType::kRegular,
-                                       /*provide_pref_service=*/false);
 
-    session_controller->SwitchActiveUser(account_id_1);
-    session_controller->SetSessionState(session_manager::SessionState::ACTIVE);
+    if (should_sign_in_) {
+      session_controller->AddUserSession(kUserEmail1,
+                                         user_manager::UserType::kRegular,
+                                         /*provide_pref_service=*/false);
+      session_controller->SetUserPrefService(account_id_1,
+                                             std::move(user_1_prefs));
+      session_controller->AddUserSession(kUserEmail2,
+                                         user_manager::UserType::kRegular,
+                                         /*provide_pref_service=*/false);
+      session_controller->SetUserPrefService(account_id_2,
+                                             std::move(user_2_prefs));
+      session_controller->AddUserSession(kUserEmail3,
+                                         user_manager::UserType::kRegular,
+                                         /*provide_pref_service=*/false);
+
+      session_controller->SwitchActiveUser(account_id_1);
+      session_controller->SetSessionState(
+          session_manager::SessionState::ACTIVE);
+    }
+
     // Reset the `num_keyboard_settings_initialized_` to account for the
     // `InitializeKeyboardSettings` call made after test setup where we
     // simualate
@@ -542,6 +548,11 @@
       scoped_resetter_;
   raw_ptr<FakeKeyboardPrefHandler, DanglingUntriaged> keyboard_pref_handler_ =
       nullptr;
+
+  // Used by other instances of the InputDeviceSettingsControllerTest to control
+  // whether or not to sign in within the SetUp() function. Configured to sign
+  // in by default.
+  bool should_sign_in_ = true;
 };
 
 TEST_F(InputDeviceSettingsControllerTest, KeyboardAddingOne) {
@@ -1560,4 +1571,59 @@
   EXPECT_EQ(2u, observer_->num_pointing_stick_settings_updated());
 }
 
+class InputDeviceSettingsControllerNoSignInTest
+    : public InputDeviceSettingsControllerTest {
+ public:
+  InputDeviceSettingsControllerNoSignInTest() { should_sign_in_ = false; }
+};
+
+TEST_F(InputDeviceSettingsControllerNoSignInTest,
+       NoCrashOnPodSelectionRaceConditionMouse) {
+  ui::DeviceDataManagerTestApi().SetMouseDevices({kSampleMouseUsb});
+
+  auto* mouse = controller_->GetMouse(kSampleMouseUsb.id);
+  ASSERT_TRUE(mouse);
+  ASSERT_TRUE(mouse->settings);
+}
+
+TEST_F(InputDeviceSettingsControllerNoSignInTest,
+       NoCrashOnPodSelectionRaceConditionKeyboard) {
+  ui::DeviceDataManagerTestApi().SetKeyboardDevices({kSampleKeyboardInternal});
+
+  auto* keyboard = controller_->GetKeyboard(kSampleKeyboardInternal.id);
+  ASSERT_TRUE(keyboard);
+  ASSERT_TRUE(keyboard->settings);
+}
+
+TEST_F(InputDeviceSettingsControllerNoSignInTest,
+       NoCrashOnPodSelectionRaceConditionTouchpad) {
+  ui::DeviceDataManagerTestApi().SetTouchpadDevices({kSampleTouchpadInternal});
+
+  auto* touchpad = controller_->GetTouchpad(kSampleTouchpadInternal.id);
+  ASSERT_TRUE(touchpad);
+  ASSERT_TRUE(touchpad->settings);
+}
+
+TEST_F(InputDeviceSettingsControllerNoSignInTest,
+       NoCrashOnPodSelectionRaceConditionPointingStick) {
+  ui::DeviceDataManagerTestApi().SetPointingStickDevices(
+      {kSamplePointingStickExternal});
+
+  auto* pointing_stick =
+      controller_->GetPointingStick(kSamplePointingStickExternal.id);
+  ASSERT_TRUE(pointing_stick);
+  ASSERT_TRUE(pointing_stick->settings);
+}
+
+TEST_F(InputDeviceSettingsControllerNoSignInTest,
+       NoCrashOnPodSelectionRaceConditionGraphicsTablet) {
+  ui::DeviceDataManagerTestApi().SetGraphicsTabletDevices(
+      {kSampleGraphicsTablet});
+
+  auto* graphics_tablet =
+      controller_->GetGraphicsTablet(kSampleGraphicsTablet.id);
+  ASSERT_TRUE(graphics_tablet);
+  ASSERT_TRUE(graphics_tablet->settings);
+}
+
 }  // namespace ash
diff --git a/ash/system/mahi/mahi_panel_view.cc b/ash/system/mahi/mahi_panel_view.cc
index 96693ee..fc06576 100644
--- a/ash/system/mahi/mahi_panel_view.cc
+++ b/ash/system/mahi/mahi_panel_view.cc
@@ -5,6 +5,7 @@
 #include "ash/system/mahi/mahi_panel_view.h"
 
 #include <algorithm>
+#include <climits>
 #include <memory>
 #include <string>
 
@@ -32,11 +33,13 @@
 #include "ui/views/background.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/link.h"
+#include "ui/views/controls/scroll_view.h"
 #include "ui/views/highlight_border.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/box_layout_view.h"
 #include "ui/views/layout/flex_layout_view.h"
 #include "ui/views/layout/layout_types.h"
+#include "ui/views/metadata/view_factory_internal.h"
 #include "ui/views/view.h"
 #include "ui/views/view_class_properties.h"
 #include "ui/views/widget/widget.h"
@@ -50,6 +53,7 @@
 constexpr gfx::Insets kPanelPadding = gfx::Insets(16);
 constexpr int kPanelChildSpacing = 8;
 constexpr int kHeaderRowSpacing = 8;
+constexpr float kScrollerViewCornerRadius = 16;
 
 }  // namespace
 
@@ -57,10 +61,12 @@
 END_METADATA
 
 MahiPanelView::MahiPanelView() {
-  SetOrientation(views::BoxLayout::Orientation::kVertical);
-  SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kStart);
-  SetInsideBorderInsets(kPanelPadding);
-  SetBetweenChildSpacing(kPanelChildSpacing);
+  SetOrientation(views::LayoutOrientation::kVertical);
+  SetMainAxisAlignment(views::LayoutAlignment::kStart);
+  SetInteriorMargin(kPanelPadding);
+  SetDefault(views::kMarginsKey, gfx::Insets::VH(kPanelChildSpacing, 0));
+  SetIgnoreDefaultMainAxisMargins(true);
+  SetCollapseMargins(true);
 
   SetBackground(views::CreateThemedRoundedRectBackground(
       cros_tokens::kCrosSysSystemBaseElevated, kPanelCornerRadius));
@@ -77,6 +83,7 @@
       views::HighlightBorder::Type::kHighlightBorderOnShadow,
       /*insets_type=*/views::HighlightBorder::InsetsType::kHalfInsets));
 
+  // Views constructions.
   auto header_row = std::make_unique<views::FlexLayoutView>();
   header_row->SetOrientation(views::LayoutOrientation::kHorizontal);
 
@@ -116,7 +123,34 @@
 
   AddChildView(std::move(header_row));
 
-  AddChildView(std::make_unique<SummaryOutlinesSection>());
+  // Scrollable contents, which should contain the summary outline section and
+  // the Q&A section.
+  auto scroll_view =
+      views::Builder<views::ScrollView>()
+          .SetBackgroundThemeColorId(cros_tokens::kCrosSysSystemOnBase)
+          .SetProperty(views::kFlexBehaviorKey,
+                       views::FlexSpecification(views::FlexSpecification(
+                           views::MinimumFlexSizeRule::kPreferred,
+                           views::MaximumFlexSizeRule::kUnbounded)))
+          .ClipHeightTo(/*min_height=*/0, /*max_height=*/INT_MAX)
+          .SetDrawOverflowIndicator(false)
+          .Build();
+
+  scroll_view->SetContents(
+      views::Builder<views::View>()
+          .SetUseDefaultFillLayout(true)
+          .AddChild(views::Builder<SummaryOutlinesSection>())
+          // TODO(b/319731486): Change this view to the Q&A section and
+          // show/hide it accordingly.
+          .AddChild(views::Builder<views::View>())
+          .Build());
+
+  // Add layer for rounded corners.
+  scroll_view->SetPaintToLayer();
+  scroll_view->layer()->SetRoundedCornerRadius(
+      gfx::RoundedCornersF{kScrollerViewCornerRadius});
+
+  AddChildView(std::move(scroll_view));
 
   auto feedback_view = std::make_unique<views::BoxLayoutView>();
   feedback_view->SetOrientation(views::BoxLayout::Orientation::kHorizontal);
diff --git a/ash/system/mahi/mahi_panel_view.h b/ash/system/mahi/mahi_panel_view.h
index 54e412c81..69048c2 100644
--- a/ash/system/mahi/mahi_panel_view.h
+++ b/ash/system/mahi/mahi_panel_view.h
@@ -9,7 +9,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "ui/base/metadata/metadata_header_macros.h"
-#include "ui/views/layout/box_layout_view.h"
+#include "ui/views/layout/flex_layout_view.h"
 
 namespace ui {
 class Event;
@@ -19,8 +19,8 @@
 
 // The code for Mahi main panel view. This view is placed within
 // `MahiPanelWidget`.
-class ASH_EXPORT MahiPanelView : public views::BoxLayoutView {
-  METADATA_HEADER(MahiPanelView, views::BoxLayoutView)
+class ASH_EXPORT MahiPanelView : public views::FlexLayoutView {
+  METADATA_HEADER(MahiPanelView, views::FlexLayoutView)
 
  public:
   MahiPanelView();
diff --git a/ash/system/mahi/summary_outlines_section.cc b/ash/system/mahi/summary_outlines_section.cc
index 468daacc..231c856 100644
--- a/ash/system/mahi/summary_outlines_section.cc
+++ b/ash/system/mahi/summary_outlines_section.cc
@@ -19,7 +19,6 @@
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/gfx/text_constants.h"
 #include "ui/gfx/vector_icon_types.h"
-#include "ui/views/background.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
@@ -34,7 +33,6 @@
 constexpr int64_t kSectionHeaderIconSize = 20;
 constexpr gfx::Insets kSectionPadding = gfx::Insets::TLBR(8, 8, 16, 8);
 constexpr int64_t kSectionChildSpacing = 8;
-constexpr int64_t kSectionCornerRadius = 16;
 
 std::unique_ptr<views::View> CreateSectionHeader(const gfx::VectorIcon& icon,
                                                  int name_id) {
@@ -62,9 +60,6 @@
   SetInsideBorderInsets(kSectionPadding);
   SetBetweenChildSpacing(kSectionChildSpacing);
 
-  SetBackground(views::CreateThemedRoundedRectBackground(
-      cros_tokens::kCrosSysSystemOnBase, kSectionCornerRadius));
-
   AddChildView(CreateSectionHeader(chromeos::kMahiSummarizeIcon,
                                    IDS_MAHI_PANEL_SUMMARY_SECTION_NAME));
 
diff --git a/ash/system/mahi/summary_outlines_section.h b/ash/system/mahi/summary_outlines_section.h
index 70f32a2..cd82052 100644
--- a/ash/system/mahi/summary_outlines_section.h
+++ b/ash/system/mahi/summary_outlines_section.h
@@ -10,6 +10,7 @@
 #include "base/memory/weak_ptr.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/layout/box_layout_view.h"
+#include "ui/views/metadata/view_factory.h"
 
 namespace ash {
 
@@ -27,6 +28,11 @@
   base::WeakPtrFactory<SummaryOutlinesSection> weak_ptr_factory_{this};
 };
 
+BEGIN_VIEW_BUILDER(ASH_EXPORT, SummaryOutlinesSection, views::BoxLayoutView)
+END_VIEW_BUILDER
+
 }  // namespace ash
 
+DEFINE_VIEW_BUILDER(ASH_EXPORT, ash::SummaryOutlinesSection)
+
 #endif  // ASH_SYSTEM_MAHI_SUMMARY_OUTLINES_SECTION_H_
diff --git a/ash/system/media/unified_media_controls_controller.h b/ash/system/media/unified_media_controls_controller.h
index 837ddda..0528e28 100644
--- a/ash/system/media/unified_media_controls_controller.h
+++ b/ash/system/media/unified_media_controls_controller.h
@@ -54,6 +54,9 @@
   void MediaControllerImageChanged(
       media_session::mojom::MediaSessionImageType type,
       const SkBitmap& bitmap) override;
+  // This view will be deprecated after `kBackgroundListening` is enabled. So we
+  // don't need to implement this method since there's no chapter images in this
+  // view.
   void MediaControllerChapterImageChanged(int chapter_index,
                                           const SkBitmap& bitmap) override {}
 
diff --git a/ash/webui/print_preview_cros/resources/js/data/print_ticket_manager.ts b/ash/webui/print_preview_cros/resources/js/data/print_ticket_manager.ts
index 0e38a7e..9d12832 100644
--- a/ash/webui/print_preview_cros/resources/js/data/print_ticket_manager.ts
+++ b/ash/webui/print_preview_cros/resources/js/data/print_ticket_manager.ts
@@ -13,6 +13,11 @@
  * signaling updates to subscribed listeners.
  */
 
+export const PRINT_REQUEST_STARTED_EVENT =
+    'print-ticket-manager.print-request-started';
+export const PRINT_REQUEST_FINISHED_EVENT =
+    'print-ticket-manager.print-request-finished';
+
 export class PrintTicketManager extends EventTarget {
   private static instance: PrintTicketManager|null = null;
 
@@ -30,6 +35,7 @@
 
   // Non-static properties:
   private printPreviewPageHandler: PrintPreviewPageHandler|null;
+  private printRequestInProgress = false;
 
   // Prevent additional initialization.
   private constructor() {
@@ -39,15 +45,32 @@
     this.printPreviewPageHandler = getPrintPreviewPageHandler();
   }
 
+  // Custom event dispatch helper.
+  private dispatch(eventName: string): void {
+    this.dispatchEvent(
+        new CustomEvent(eventName, {bubbles: true, composed: true}));
+  }
+
+  // Handles notifying start and finish print request.
   // TODO(b/323421684): Takes current print ticket uses PrintPreviewPageHandler
-  // to initiate actual print request. Also handles print request start and
-  // finish events.
+  // to initiate actual print request.
   sendPrintRequest(): void {
     assert(this.printPreviewPageHandler);
 
+    if (this.printRequestInProgress) {
+      // Print is already in progress, wait for request to resolve before
+      // allowing a second attempt.
+      return;
+    }
+    this.printRequestInProgress = true;
+    this.dispatch(PRINT_REQUEST_STARTED_EVENT);
+
     // TODO(b/323421684): Handle result from page handler and update UI if error
     // occurred.
-    this.printPreviewPageHandler!.print();
+    this.printPreviewPageHandler!.print().finally(() => {
+      this.printRequestInProgress = false;
+      this.dispatch(PRINT_REQUEST_FINISHED_EVENT);
+    });
   }
 
   // Does cleanup for print request.
@@ -55,4 +78,15 @@
     assert(this.printPreviewPageHandler);
     this.printPreviewPageHandler!.cancel();
   }
+
+  isPrintRequestInProgress(): boolean {
+    return this.printRequestInProgress;
+  }
+}
+
+declare global {
+  interface HTMLElementEventMap {
+    [PRINT_REQUEST_FINISHED_EVENT]: CustomEvent<void>;
+    [PRINT_REQUEST_STARTED_EVENT]: CustomEvent<void>;
+  }
 }
diff --git a/ash/webui/print_preview_cros/resources/js/fakes/fake_print_preview_page_handler.ts b/ash/webui/print_preview_cros/resources/js/fakes/fake_print_preview_page_handler.ts
index faa3414..01025ab9 100644
--- a/ash/webui/print_preview_cros/resources/js/fakes/fake_print_preview_page_handler.ts
+++ b/ash/webui/print_preview_cros/resources/js/fakes/fake_print_preview_page_handler.ts
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import {FakeMethodResolver} from 'chrome://resources/ash/common/fake_method_resolver.js';
+import {assert} from 'chrome://resources/js/assert.js';
 
 import {type PrintPreviewPageHandler, type PrintRequestOutcome} from '../utils/print_preview_cros_app_types.js';
 
@@ -29,6 +30,7 @@
 export class FakePrintPreviewPageHandler implements PrintPreviewPageHandler {
   private methods: FakeMethodResolver = new FakeMethodResolver();
   private callCount: Map<string, number> = new Map<string, number>();
+  private testDelayMs = 0;
   constructor() {
     this.registerMethods();
   }
@@ -46,6 +48,7 @@
     this.callCount.clear();
     this.methods = new FakeMethodResolver();
     this.registerMethods();
+    this.testDelayMs = 0;
   }
 
   setPrintResult(result: PrintRequestOutcome) {
@@ -56,7 +59,7 @@
   print(): Promise<PrintRequestOutcome> {
     const prevCallCount = this.callCount.get(PRINT_METHOD) ?? 0;
     this.callCount.set(PRINT_METHOD, prevCallCount + 1);
-    return this.methods.resolveMethod(PRINT_METHOD);
+    return this.methods.resolveMethodWithDelay(PRINT_METHOD, this.testDelayMs);
   }
 
   getCallCount(method: string): number {
@@ -68,4 +71,13 @@
     const prevCallCount = this.callCount.get(CANCEL_METHOD) ?? 0;
     this.callCount.set(CANCEL_METHOD, prevCallCount + 1);
   }
+
+  useTestDelay(delay: number): void {
+    assert(delay >= 0);
+    this.testDelayMs = delay;
+  }
+
+  getMethodsForTesting(): FakeMethodResolver {
+    return this.methods;
+  }
 }
diff --git a/ash/webui/print_preview_cros/resources/js/summary_panel.html b/ash/webui/print_preview_cros/resources/js/summary_panel.html
index 1987bc7..5bd2948 100644
--- a/ash/webui/print_preview_cros/resources/js/summary_panel.html
+++ b/ash/webui/print_preview_cros/resources/js/summary_panel.html
@@ -23,6 +23,7 @@
   </cros-button>
   <!-- TODO(b/323585997): Replace label localized string. -->
   <cros-button id="print" label="Print" button-style="primary"
-      on-click="onPrintClicked">
+      on-click="onPrintClicked"
+      disabled="[[printButtonDisabled]]">
   </cros-button>
 </div>
\ No newline at end of file
diff --git a/ash/webui/print_preview_cros/resources/js/summary_panel.ts b/ash/webui/print_preview_cros/resources/js/summary_panel.ts
index 6833507..df656497 100644
--- a/ash/webui/print_preview_cros/resources/js/summary_panel.ts
+++ b/ash/webui/print_preview_cros/resources/js/summary_panel.ts
@@ -7,7 +7,7 @@
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getTemplate} from './summary_panel.html.js';
-import {SHEETS_USED_CHANGED_EVENT, SummaryPanelController} from './summary_panel_controller.js';
+import {PRINT_BUTTON_DISABLED_CHANGED_EVENT, SHEETS_USED_CHANGED_EVENT, SummaryPanelController} from './summary_panel_controller.js';
 
 /**
  * @fileoverview
@@ -27,26 +27,32 @@
   static get properties() {
     return {
       sheetsUsedText: String,
+      printButtonDisabled: Boolean,
     };
   }
 
   private controller: SummaryPanelController = new SummaryPanelController();
   private sheetsUsedText: string;
+  private printButtonDisabled: boolean;
 
   override connectedCallback(): void {
     super.connectedCallback();
     this.controller.addEventListener(
+        PRINT_BUTTON_DISABLED_CHANGED_EVENT,
+        (e: Event) => this.onPrintButtonDisabledChanged(e));
+    this.controller.addEventListener(
         SHEETS_USED_CHANGED_EVENT, (e: Event) => this.onSheetsUsedChanged(e));
 
     // Initialize properties using controller.
     this.sheetsUsedText = this.controller.getSheetsUsedText();
+    this.printButtonDisabled = this.controller.shouldDisablePrintButton();
   }
 
-  getControllerForTesting() {
+  getControllerForTesting(): SummaryPanelController {
     return this.controller;
   }
 
-  private onSheetsUsedChanged(_event: Event) {
+  private onSheetsUsedChanged(_event: Event): void {
     this.sheetsUsedText = this.controller.getSheetsUsedText();
   }
 
@@ -59,6 +65,12 @@
   protected onCancelClicked(_event: Event): void {
     this.controller.handleCancelClicked();
   }
+
+  // Ensure `#print` disabled state updates based on controller's
+  // shouldDisablePrintButton method on `PRINT_BUTTON_DISABLED_CHANGED_EVENT`.
+  private onPrintButtonDisabledChanged(_event: Event): void {
+    this.printButtonDisabled = this.controller.shouldDisablePrintButton();
+  }
 }
 
 declare global {
diff --git a/ash/webui/print_preview_cros/resources/js/summary_panel_controller.ts b/ash/webui/print_preview_cros/resources/js/summary_panel_controller.ts
index afa2a75..ade8779 100644
--- a/ash/webui/print_preview_cros/resources/js/summary_panel_controller.ts
+++ b/ash/webui/print_preview_cros/resources/js/summary_panel_controller.ts
@@ -4,7 +4,7 @@
 
 import {assert} from 'chrome://resources/js/assert.js';
 
-import {PrintTicketManager} from './data/print_ticket_manager.js';
+import {PRINT_REQUEST_FINISHED_EVENT, PRINT_REQUEST_STARTED_EVENT, PrintTicketManager} from './data/print_ticket_manager.js';
 
 /**
  * @fileoverview
@@ -13,6 +13,8 @@
  * to update.
  */
 
+export const PRINT_BUTTON_DISABLED_CHANGED_EVENT =
+    'summary-panel-controller.print-button-disabled-changed';
 export const SHEETS_USED_CHANGED_EVENT =
     'summary-panel-controller.sheets-used-changed';
 
@@ -22,6 +24,16 @@
   private sheetsUsed = 0;
   private printTicketManger = PrintTicketManager.getInstance();
 
+  constructor() {
+    super();
+    this.printTicketManger.addEventListener(
+        PRINT_REQUEST_STARTED_EVENT,
+        (e: Event) => this.onPrintRequestStarted(e));
+    this.printTicketManger.addEventListener(
+        PRINT_REQUEST_FINISHED_EVENT,
+        (e: Event) => this.onPrintRequestFinished(e));
+  }
+
   // Returns localized string based on current number of sheets in document and
   // whether document is being saved to a digital destination or printed to a
   // physical location.
@@ -38,8 +50,7 @@
   setSheetsUsedForTesting(sheetsUsed: number): void {
     assert(sheetsUsed >= 0);
     this.sheetsUsed = sheetsUsed;
-    this.dispatchEvent(new CustomEvent<void>(
-        SHEETS_USED_CHANGED_EVENT, {bubbles: true, composed: true}));
+    this.dispatch(SHEETS_USED_CHANGED_EVENT);
   }
 
   // Handles behavior for when the print button is clicked.
@@ -52,6 +63,27 @@
   handleCancelClicked(): void {
     this.printTicketManger.cancelPrintRequest();
   }
+
+  // CustomEvent dispatch helper.
+  private dispatch(eventName: string): void {
+    this.dispatchEvent(
+        new CustomEvent<void>(eventName, {bubbles: true, composed: true}));
+  }
+
+  // Handles notifying UI to update state when print request starts.
+  private onPrintRequestStarted(_e: Event): void {
+    this.dispatch(PRINT_BUTTON_DISABLED_CHANGED_EVENT);
+  }
+
+  // Handles notifying UI to update state when print request finishes.
+  private onPrintRequestFinished(_e: Event): void {
+    this.dispatch(PRINT_BUTTON_DISABLED_CHANGED_EVENT);
+  }
+
+  // Whether the print button should be enabled for the current state.
+  shouldDisablePrintButton(): boolean {
+    return this.printTicketManger.isPrintRequestInProgress();
+  }
 }
 
 declare global {
diff --git a/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.ts b/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.ts
index 9a08d713..b16d2450 100644
--- a/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.ts
+++ b/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.ts
@@ -294,8 +294,9 @@
   }
 
   private handleKeyDown(e: CustomEvent): void {
-    // Announce the key pressed.
-    this.makeA11yAnnouncement(e.detail.keyEvent.keyDisplay);
+    // Announce the icon label or key pressed.
+    const keyOrIcon = e.detail.keyEvent.keyDisplay;
+    this.makeA11yAnnouncement(getKeyDisplay(keyOrIcon));
     const rewrittenKeyEvent = e.detail.keyEvent;
     const pendingAccelerator = keyEventToAccelerator(rewrittenKeyEvent);
     if (this.hasError) {
diff --git a/ash/webui/shortcut_customization_ui/resources/js/shortcut_utils.ts b/ash/webui/shortcut_customization_ui/resources/js/shortcut_utils.ts
index 60c57a6..80052ef 100644
--- a/ash/webui/shortcut_customization_ui/resources/js/shortcut_utils.ts
+++ b/ash/webui/shortcut_customization_ui/resources/js/shortcut_utils.ts
@@ -375,12 +375,12 @@
 /**
  *
  * @param keyOrIcon the text for an individual accelerator key.
- * @returns the associated icon name for the given `keyOrIcon` text if it
+ * @returns the associated icon label for the given `keyOrIcon` text if it
  *     exists, otherwise returns `keyOrIcon` itself.
  */
 export const getKeyDisplay = (keyOrIcon: string): string => {
   const iconName = keyToIconNameMap[keyOrIcon];
-  return iconName ? iconName : keyOrIcon;
+  return iconName ? loadTimeData.getString(`iconLabel${keyOrIcon}`) : keyOrIcon;
 };
 
 /**
diff --git a/ash/wm/lock_state_controller.cc b/ash/wm/lock_state_controller.cc
index 0bfcf6e..7e774c1 100644
--- a/ash/wm/lock_state_controller.cc
+++ b/ash/wm/lock_state_controller.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "ash/accessibility/accessibility_controller.h"
+#include "ash/app_list/app_list_controller_impl.h"
 #include "ash/cancel_mode.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
@@ -23,6 +24,7 @@
 #include "ash/wallpaper/views/wallpaper_widget_controller.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
 #include "ash/wm/desks/desks_util.h"
+#include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/session_state_animator_impl.h"
 #include "ash/wm/window_restore/window_restore_util.h"
 #include "base/command_line.h"
@@ -134,6 +136,23 @@
   }
 }
 
+// TODO(minch): Check whether the screenshot should be taken in kiosk mode or
+// locked mode.
+// Returns true if the pine screenshot should be taken on shutdown.
+bool ShouldTakePineScreeshot(aura::Window* active_desk) {
+  auto* shell = Shell::Get();
+  // Do not take the pine screenshot if it is in overview mode, lock screen or
+  // in the home launcher page.
+  if (shell->overview_controller()->InOverviewSession() ||
+      shell->session_controller()->IsScreenLocked() ||
+      shell->app_list_controller()->IsHomeScreenVisible()) {
+    return false;
+  }
+
+  // Do not take the pine screenshot if the active desk has no windows.
+  return !active_desk->children().empty();
+}
+
 }  // namespace
 
 // static
@@ -703,10 +722,9 @@
   CHECK(active_desk);
   const base::FilePath file_path = GetShutdownPineImagePath();
 
-  if (active_desk->children().empty()) {
-    // If there are no windows in the desk container, taking the pine image will
-    // fail. Delete any existing pine image so on next startup no pine image
-    // preview will be shown.
+  if (!ShouldTakePineScreeshot(active_desk)) {
+    // Delete any existing pine image if we should not take the screenshot on
+    // this shutdown, then no stale screenshot will be shown on next startup.
     auto delete_image_cb =
         base::BindOnce(base::IgnoreResult(&base::DeleteFile), file_path);
     MaybeAppendTestCallback(delete_image_cb, pine_image_callback_for_test_);
diff --git a/ash/wm/lock_state_controller_unittest.cc b/ash/wm/lock_state_controller_unittest.cc
index cc5bdc62..070fc2a0 100644
--- a/ash/wm/lock_state_controller_unittest.cc
+++ b/ash/wm/lock_state_controller_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "ash/app_list/app_list_controller_impl.h"
 #include "ash/constants/ash_pref_names.h"
 #include "ash/constants/ash_switches.h"
 #include "ash/public/cpp/shutdown_controller.h"
@@ -24,6 +25,7 @@
 #include "ash/wm/lock_state_controller_test_api.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/session_state_animator.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
 #include "ash/wm/test/test_session_state_animator.h"
 #include "ash/wm/window_restore/window_restore_util.h"
 #include "base/barrier_closure.h"
@@ -1051,6 +1053,7 @@
     CHECK(temp_dir_.CreateUniqueTempDir());
     file_path_ = temp_dir_.GetPath().AppendASCII("test_pine.png");
     SetPineImagePathForTest(file_path_);
+    Initialize(ButtonType::NORMAL, LoginStatus::USER);
   }
 
   void TearDown() override {
@@ -1069,7 +1072,6 @@
 
 // Tests that a pine image is taken when there are windows open.
 TEST_F(LockStateControllerPineTest, ShutdownWithWindows) {
-  Initialize(ButtonType::NORMAL, LoginStatus::USER);
   std::unique_ptr<aura::Window> window = CreateTestWindow();
 
   base::RunLoop run_loop;
@@ -1097,8 +1099,6 @@
 // Tests that no pine image is taken when there are no windows opened and the
 // existing pine image should be deleted.
 TEST_F(LockStateControllerPineTest, ShutdownWithoutWindows) {
-  Initialize(ButtonType::NORMAL, LoginStatus::USER);
-
   // Create an empty file to simulate an old pine image.
   ASSERT_TRUE(base::WriteFile(file_path(), ""));
 
@@ -1112,4 +1112,67 @@
   EXPECT_FALSE(base::PathExists(file_path()));
 }
 
+TEST_F(LockStateControllerPineTest, ShutdownInOverview) {
+  // Create an empty file to simulate an old pine image.
+  ASSERT_TRUE(base::WriteFile(file_path(), ""));
+
+  // Create a window and enter the overview before requesting shutdown.
+  CreateTestWindow();
+  EnterOverview();
+
+  base::RunLoop run_loop;
+  lock_state_test_api_->set_pine_image_callback(run_loop.QuitClosure());
+  lock_state_controller_->RequestShutdown(
+      ShutdownReason::TRAY_SHUT_DOWN_BUTTON);
+  run_loop.Run();
+
+  // The pine image should not be taken if it is in overview when shutting down.
+  // The existing pine image should be deleted as well.
+  EXPECT_FALSE(base::PathExists(file_path()));
+}
+
+TEST_F(LockStateControllerPineTest, ShutdownInLockScreen) {
+  // Create an empty file to simulate an old pine image.
+  ASSERT_TRUE(base::WriteFile(file_path(), ""));
+
+  // Create a window and go the lock screen before requesting shutdown.
+  CreateTestWindowInShellWithId(0);
+  GetSessionControllerClient()->LockScreen();
+  EXPECT_TRUE(Shell::Get()->session_controller()->IsScreenLocked());
+
+  base::RunLoop run_loop;
+  lock_state_test_api_->set_pine_image_callback(run_loop.QuitClosure());
+  lock_state_controller_->RequestShutdown(
+      ShutdownReason::TRAY_SHUT_DOWN_BUTTON);
+  run_loop.Run();
+
+  // The pine image should not be taken if it is in the lock screen. The
+  // existing pine image should be deleted as well.
+  EXPECT_FALSE(base::PathExists(file_path()));
+}
+
+TEST_F(LockStateControllerPineTest, ShutdownInHomeLauncher) {
+  // Create an empty file to simulate an old pine image.
+  ASSERT_TRUE(base::WriteFile(file_path(), ""));
+
+  // Create a window and go to the home launcher page before requesting
+  // shutdown.
+  std::unique_ptr<aura::Window> window(CreateTestWindow());
+  TabletModeControllerTestApi().EnterTabletMode();
+  auto* app_list_controller = Shell::Get()->app_list_controller();
+  app_list_controller->GoHome(GetPrimaryDisplay().id());
+  ASSERT_TRUE(app_list_controller->IsHomeScreenVisible());
+  EXPECT_TRUE(WindowState::Get(window.get())->IsMinimized());
+
+  base::RunLoop run_loop;
+  lock_state_test_api_->set_pine_image_callback(run_loop.QuitClosure());
+  lock_state_controller_->RequestShutdown(
+      ShutdownReason::TRAY_SHUT_DOWN_BUTTON);
+  run_loop.Run();
+
+  // The pine image should not be taken if it is in the home launcher page when
+  // shutting down. The existing image should be deleted as well.
+  EXPECT_FALSE(base::PathExists(file_path()));
+}
+
 }  // namespace ash
diff --git a/ash/wm/overview/overview_constants.h b/ash/wm/overview/overview_constants.h
index 897c240..28ec7ca 100644
--- a/ash/wm/overview/overview_constants.h
+++ b/ash/wm/overview/overview_constants.h
@@ -35,6 +35,9 @@
 constexpr SystemShadow::Type kDraggedShadowType =
     SystemShadow::Type::kElevation24;
 
+// Rounded corner radii applied on the wallpaper clip rect.
+constexpr gfx::RoundedCornersF kWallpaperClipRoundedCornerRadii(20.f);
+
 }  // namespace ash
 
 #endif  // ASH_WM_OVERVIEW_OVERVIEW_CONSTANTS_H_
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index 52556cc..e754d315 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -28,6 +28,8 @@
 #include "ash/style/ash_color_id.h"
 #include "ash/style/typography.h"
 #include "ash/system/toast/toast_manager_impl.h"
+#include "ash/wallpaper/views/wallpaper_view.h"
+#include "ash/wallpaper/views/wallpaper_widget_controller.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
 #include "ash/wm/desks/default_desk_button.h"
 #include "ash/wm/desks/desk_bar_view_base.h"
@@ -88,12 +90,16 @@
 #include "components/app_restore/full_restore_utils.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/compositor/compositor_observer.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animator.h"
+#include "ui/compositor/layer_type.h"
 #include "ui/compositor/presentation_time_recorder.h"
 #include "ui/compositor/throughput_tracker.h"
 #include "ui/display/screen.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rounded_corners_f.h"
 #include "ui/gfx/geometry/size_f.h"
 #include "ui/gfx/geometry/transform.h"
 #include "ui/gfx/geometry/transform_util.h"
@@ -157,6 +163,10 @@
 // visible.
 constexpr int kFeedbackGridMinHeight = 100;
 
+// Vertical spacing between the desk bar widget's bottom edge and the clipped
+// wallpaper's top edge.
+const int kSpaceBetweenBottomOfDeskBarAndClipWallpaper = 16;
+
 // The bottom padding applied to the bottom of the birch bar.
 constexpr int kBirchBarBottomPadding = 16;
 
@@ -572,6 +582,7 @@
     animator->RemoveObserver(this);
   }
 
+  RefreshClipWallpaper();
   Shell::Get()->wallpaper_controller()->RemoveObserver(this);
   grid_event_handler_.reset();
 
@@ -643,6 +654,8 @@
 
   MaybeInitBirchBarWidget();
 
+  RefreshClipWallpaper();
+
   if (root_window_ == Shell::GetPrimaryRootWindow() &&
       overview_session_->enter_exit_overview_type() ==
           OverviewEnterExitType::kPine) {
@@ -1047,6 +1060,7 @@
   bounds_ = bounds_in_screen;
   MaybeUpdateDesksWidgetBounds();
   MaybeUpdateBirchBarWidgetBounds();
+  RefreshClipWallpaper();
   PositionWindows(animate, ignored_items);
 
   if (bounds_updated && saved_desk_library_widget_)
@@ -1091,6 +1105,61 @@
   split_view_drag_indicators_->SetWindowDraggingState(window_dragging_state);
 }
 
+void OverviewGrid::RefreshClipWallpaper() {
+  if (!features::IsForestFeatureEnabled()) {
+    return;
+  }
+
+  WallpaperWidgetController* wallpaper_widget_controller =
+      RootWindowController::ForWindow(root_window_)
+          ->wallpaper_widget_controller();
+  auto* wallpaper_view_layer =
+      wallpaper_widget_controller->wallpaper_view()->layer();
+  auto* wallpaper_view_layer_parent = wallpaper_view_layer->parent();
+
+  // Reset the clip wallpaper visuals on overview session shutting down.
+  // TODO(http://b/327663425): Use scoped object to ensure wallpaper will be
+  // restored to its original state on overview exit.
+  if (overview_session_->is_shutting_down()) {
+    if (wallpaper_underlay_layer_) {
+      CHECK_EQ(wallpaper_underlay_layer_->parent(),
+               wallpaper_view_layer_parent);
+      wallpaper_view_layer_parent->Remove(wallpaper_underlay_layer_.get());
+      wallpaper_underlay_layer_.reset();
+      wallpaper_view_layer->SetClipRect(gfx::Rect());
+      wallpaper_view_layer->SetBounds(
+          display::Screen::GetScreen()
+              ->GetDisplayNearestWindow(root_window_)
+              .bounds());
+      wallpaper_view_layer->SetRoundedCornerRadius(gfx::RoundedCornersF());
+    }
+    return;
+  }
+
+  const gfx::Rect current_grid_bounds = GetGridBoundsInScreen(root_window_);
+  const gfx::Rect effective_grid_bounds = GetGridEffectiveBounds();
+  if (wallpaper_underlay_layer_) {
+    wallpaper_underlay_layer_->SetBounds(current_grid_bounds);
+    wallpaper_view_layer->SetClipRect(effective_grid_bounds);
+  } else {
+    wallpaper_underlay_layer_ =
+        std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR);
+    wallpaper_underlay_layer_->SetBounds(current_grid_bounds);
+    // TODO(http://b/327663905): Implement on theme change for the
+    // `wallpaper_underlay_layer_`.
+    wallpaper_underlay_layer_->SetColor(
+        wallpaper_widget_controller->GetWidget()->GetColorProvider()->GetColor(
+            cros_tokens::kCrosSysSystemBase));
+    wallpaper_view_layer->SetRoundedCornerRadius(
+        kWallpaperClipRoundedCornerRadii);
+    wallpaper_view_layer->SetClipRect(effective_grid_bounds);
+    wallpaper_view_layer_parent->Add(wallpaper_underlay_layer_.get());
+    wallpaper_view_layer_parent->StackBelow(wallpaper_underlay_layer_.get(),
+                                            wallpaper_view_layer);
+    // TODO(http://b/327515857): Apply animation on the `wallpaper_view_layer`.
+  }
+}
+
 bool OverviewGrid::MaybeUpdateDesksWidgetBounds() {
   if (!desks_widget_)
     return false;
@@ -1646,7 +1715,11 @@
 
   // TODO(http://b/326087216): extend the expanded desk bar height by 16px for
   // Forest feature.
-  vertical_paddings.set_top(has_desk_bar ? GetDesksBarHeight() : 0);
+  const int desk_bar_padding_with_clip_wallpaper =
+      forest_enabled ? kSpaceBetweenBottomOfDeskBarAndClipWallpaper : 0;
+  vertical_paddings.set_top(
+      has_desk_bar ? GetDesksBarHeight() + desk_bar_padding_with_clip_wallpaper
+                   : 0);
 
   // TODO(http://b/325963519): implement the paddings in tablet mode when the
   // design is finalized.
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h
index d4a1e31..e6e56d8e 100644
--- a/ash/wm/overview/overview_grid.h
+++ b/ash/wm/overview/overview_grid.h
@@ -202,6 +202,12 @@
   void SetSplitViewDragIndicatorsWindowDraggingState(
       SplitViewDragIndicators::WindowDraggingState window_dragging_state);
 
+  // Clips wallpaper and adds `wallpaper_mask_layer_` upon overview entry.
+  // Updates the bounds of clip rect and `wallpaper_mask_layer_` when grid
+  // bounds change. Restores the wallpaper to its original state upon overview
+  // exit.
+  void RefreshClipWallpaper();
+
   // Updates the desks bar widget bounds if necessary.
   // Returns true if the desks widget's bounds have been updated.
   bool MaybeUpdateDesksWidgetBounds();
@@ -659,6 +665,9 @@
   // if split view is unsupported (see |ShouldAllowSplitView|).
   std::unique_ptr<SplitViewDragIndicators> split_view_drag_indicators_;
 
+  // A solid-color layer stacked below the clipped wallpaper.
+  std::unique_ptr<ui::Layer> wallpaper_underlay_layer_;
+
   // Widget that contains the DeskBarView contents when the Virtual Desks
   // feature is enabled.
   std::unique_ptr<views::Widget> desks_widget_;
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index 1e3c057..1ad2dd6 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -20,6 +20,7 @@
 #include "ash/constants/app_types.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
+#include "ash/constants/ash_switches.h"
 #include "ash/display/screen_orientation_controller.h"
 #include "ash/display/screen_orientation_controller_test_api.h"
 #include "ash/frame_throttler/frame_throttling_controller.h"
@@ -39,6 +40,8 @@
 #include "ash/test/ash_test_base.h"
 #include "ash/test/raster_scale_change_tracker.h"
 #include "ash/test/test_window_builder.h"
+#include "ash/wallpaper/views/wallpaper_view.h"
+#include "ash/wallpaper/views/wallpaper_widget_controller.h"
 #include "ash/wm/desks/desk.h"
 #include "ash/wm/desks/desk_action_button.h"
 #include "ash/wm/desks/desk_action_view.h"
@@ -86,6 +89,7 @@
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_constants.h"
 #include "ash/wm/wm_event.h"
+#include "ash/wm/wm_metrics.h"
 #include "ash/wm/workspace/workspace_window_resizer.h"
 #include "base/containers/contains.h"
 #include "base/containers/to_vector.h"
@@ -121,6 +125,7 @@
 #include "ui/events/gesture_detection/gesture_configuration.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/rounded_corners_f.h"
 #include "ui/gfx/geometry/transform.h"
 #include "ui/gfx/geometry/transform_util.h"
 #include "ui/gfx/geometry/vector2d.h"
@@ -10745,4 +10750,130 @@
   EXPECT_FALSE(SplitViewController::Get(root_windows[1])->InSplitViewMode());
 }
 
+// -----------------------------------------------------------------------------
+// OverviewWallpaperClipTest:
+
+// Test fixture to validate wallpaper clipping behavior during overview
+// transitions.
+class OverviewWallpaperClipTest : public OverviewTestBase {
+ public:
+  OverviewWallpaperClipTest() {
+    scoped_feature_list_.InitWithFeatures(
+        /*enabled_features=*/{features::kForestFeature,
+                              features::kFasterSplitScreenSetup,
+                              features::kOsSettingsRevampWayfinding},
+        /*disabled_features=*/{});
+    switches::SetIgnoreForestSecretKeyForTest(true);
+  }
+  OverviewWallpaperClipTest(const OverviewWallpaperClipTest&) = delete;
+  OverviewWallpaperClipTest& operator=(const OverviewWallpaperClipTest&) =
+      delete;
+  ~OverviewWallpaperClipTest() override {
+    switches::SetIgnoreForestSecretKeyForTest(false);
+  }
+
+  void SnapOneTestWindow(aura::Window* window,
+                         WindowStateType state_type,
+                         float snap_ratio,
+                         WindowSnapActionSource snap_action_source) {
+    WindowState* window_state = WindowState::Get(window);
+    const WindowSnapWMEvent snap_event(
+        state_type == WindowStateType::kPrimarySnapped
+            ? WM_EVENT_SNAP_PRIMARY
+            : WM_EVENT_SNAP_SECONDARY,
+        snap_ratio, snap_action_source);
+    window_state->OnWMEvent(&snap_event);
+    EXPECT_EQ(state_type, window_state->GetStateType());
+  }
+
+  gfx::Rect GetDisplayBoundsForRootWindow(aura::Window* root_window) {
+    return display::Screen::GetScreen()
+        ->GetDisplayNearestWindow(root_window)
+        .bounds();
+  }
+
+  ui::Layer* GetWallpaperViewLayer() {
+    return Shell::GetPrimaryRootWindowController()
+        ->wallpaper_widget_controller()
+        ->wallpaper_view()
+        ->layer();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Tests that the wallpaper layer is correctly clipped with rounded corners
+// during overview sessions, and fully restored upon exiting overview.
+TEST_F(OverviewWallpaperClipTest, WallpaperClipRectAndRoundedCorners) {
+  const gfx::Rect display_bounds(
+      GetDisplayBoundsForRootWindow(Shell::GetPrimaryRootWindow()));
+  auto* wallpaper_view_layer = GetWallpaperViewLayer();
+  // Ensure the wallpaper begins with its original dimensions (matching the
+  // active display) and has square corners.
+  EXPECT_EQ(display_bounds, wallpaper_view_layer->bounds());
+  EXPECT_TRUE(wallpaper_view_layer->clip_rect().IsEmpty());
+  EXPECT_TRUE(wallpaper_view_layer->rounded_corner_radii().IsEmpty());
+
+  // Enter overview mode and verify that the wallpaper is clipped with rounded
+  // corners.
+  ToggleOverview();
+  OverviewGrid* overview_grid = GetOverviewSession()->grid_list()[0].get();
+  EXPECT_EQ(overview_grid->GetGridEffectiveBounds(),
+            wallpaper_view_layer->clip_rect());
+  EXPECT_EQ(kWallpaperClipRoundedCornerRadii,
+            wallpaper_view_layer->rounded_corner_radii());
+
+  // Exit overview. Check that the wallpaper has been fully restored..
+  ToggleOverview();
+  EXPECT_EQ(display_bounds, wallpaper_view_layer->bounds());
+  EXPECT_TRUE(wallpaper_view_layer->clip_rect().IsEmpty());
+  EXPECT_TRUE(wallpaper_view_layer->rounded_corner_radii().IsEmpty());
+}
+
+// Tests that the wallpaper is clipped in partial overview mode and adjusts
+// correctly when the snapped window is resized.
+TEST_F(OverviewWallpaperClipTest, PartialOverviewVisualsAndResize) {
+  const gfx::Rect display_bounds(
+      GetDisplayBoundsForRootWindow(Shell::GetPrimaryRootWindow()));
+  auto* wallpaper_view_layer = GetWallpaperViewLayer();
+  std::unique_ptr<aura::Window> win1(
+      CreateAppWindow(gfx::Rect(10, 10, 100, 100)));
+  std::unique_ptr<aura::Window> win2(
+      CreateAppWindow(gfx::Rect(500, 10, 200, 200)));
+  // Check the wallpaper's original state before initiating partial overview.
+  EXPECT_EQ(display_bounds, wallpaper_view_layer->bounds());
+  EXPECT_TRUE(wallpaper_view_layer->clip_rect().IsEmpty());
+  EXPECT_TRUE(wallpaper_view_layer->rounded_corner_radii().IsEmpty());
+
+  // Snap one test window to start partial overview.
+  SnapOneTestWindow(win1.get(), chromeos::WindowStateType::kPrimarySnapped,
+                    chromeos::kDefaultSnapRatio,
+                    WindowSnapActionSource::kSnapByWindowLayoutMenu);
+  ASSERT_TRUE(IsInOverviewSession());
+  OverviewGrid* overview_grid = GetOverviewSession()->grid_list()[0].get();
+  // Verify that wallpaper is clipped properly with rounded corners applied in
+  // partial overview.
+  EXPECT_EQ(overview_grid->GetGridEffectiveBounds(),
+            wallpaper_view_layer->clip_rect());
+  EXPECT_EQ(kWallpaperClipRoundedCornerRadii,
+            wallpaper_view_layer->rounded_corner_radii());
+
+  // Verify that the wallpaper's clip rect updates responsively when the snapped
+  // window is dragged in partial overview.
+  auto* event_generator = GetEventGenerator();
+  const gfx::Point drag_starting_point =
+      win1.get()->GetBoundsInScreen().right_center();
+  event_generator->set_current_screen_location(drag_starting_point);
+  event_generator->PressLeftButton();
+  event_generator->MoveMouseBy(-10, 0);
+  ASSERT_TRUE(IsInOverviewSession());
+  EXPECT_TRUE(WindowState::Get(win1.get())->is_dragged());
+  EXPECT_EQ(overview_grid->GetGridEffectiveBounds(),
+            wallpaper_view_layer->clip_rect());
+  EXPECT_EQ(kWallpaperClipRoundedCornerRadii,
+            wallpaper_view_layer->rounded_corner_radii());
+  event_generator->ReleaseLeftButton();
+}
+
 }  // namespace ash
diff --git a/ash/wm/overview/overview_test_base.cc b/ash/wm/overview/overview_test_base.cc
index 97876e8..a3fe3fd 100644
--- a/ash/wm/overview/overview_test_base.cc
+++ b/ash/wm/overview/overview_test_base.cc
@@ -69,7 +69,7 @@
 }
 
 OverviewController* OverviewTestBase::GetOverviewController() {
-  return Shell::Get()->overview_controller();
+  return OverviewController::Get();
 }
 
 OverviewSession* OverviewTestBase::GetOverviewSession() {
diff --git a/ash/wm/window_restore/pine_controller.cc b/ash/wm/window_restore/pine_controller.cc
index cb4ad12..bb413e2 100644
--- a/ash/wm/window_restore/pine_controller.cc
+++ b/ash/wm/window_restore/pine_controller.cc
@@ -128,8 +128,15 @@
     LOG(WARNING) << "Forcing Birch data fetch";
     Shell::Get()->birch_model()->RequestBirchDataFetch(base::BindOnce([]() {
       // Dump the items that were fetched.
-      auto items = Shell::Get()->birch_model()->GetAllItems();
-      for (const auto& item : items) {
+      LOG(WARNING) << "All items:";
+      auto all_items = Shell::Get()->birch_model()->GetAllItems();
+      for (const auto& item : all_items) {
+        LOG(WARNING) << item->ToString();
+      }
+      // Dump the items for display.
+      LOG(WARNING) << "Items for display:";
+      auto display_items = Shell::Get()->birch_model()->GetItemsForDisplay();
+      for (const auto& item : display_items) {
         LOG(WARNING) << item->ToString();
       }
     }));
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 8ffd60e..c72848e7 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -3166,6 +3166,7 @@
     "command_line_unittest.cc",
     "component_export_unittest.cc",
     "containers/adapters_unittest.cc",
+    "containers/buffer_iterator_unittest.cc",
     "containers/checked_iterators_unittest.cc",
     "containers/circular_deque_unittest.cc",
     "containers/contains_unittest.cc",
@@ -3508,6 +3509,7 @@
     "types/token_type_unittest.cc",
     "types/variant_util_unittest.cc",
     "unguessable_token_unittest.cc",
+    "unsafe_buffers_unittest.cc",
     "uuid_unittest.cc",
     "value_iterators_unittest.cc",
     "values_unittest.cc",
@@ -3568,9 +3570,6 @@
     "//third_party/icu",
     "//third_party/modp_b64",
   ]
-  if (is_clang) {
-    deps += [ ":base_unsafe_buffers_unittest_sources" ]
-  }
 
   data_deps = [
     "//base/test:immediate_crash_test_helper",
@@ -4167,26 +4166,9 @@
 
   if (enable_nocompile_tests) {
     deps += [ ":base_nocompile_tests" ]
-    if (is_clang) {
-      deps += [ ":base_unsafe_buffers_nocompile_tests" ]
-    }
   }
 }
 
-source_set("base_unsafe_buffers_unittest_sources") {
-  testonly = true
-  visibility = [ ":*" ]
-  configs += [ "//build/config/compiler:unsafe_buffer_warning" ]
-  sources = [
-    "containers/buffer_iterator_unittest.cc",
-    "unsafe_buffers_unittest.cc",
-  ]
-  deps = [
-    "//base",
-    "//testing/gtest",
-  ]
-}
-
 # Test that CFG is enabled in Rust code.
 if (is_win && toolchain_has_rust) {
   source_set("rust_cfg_win_test") {
@@ -4218,6 +4200,7 @@
       "allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_nocompile.nc",
       "allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_nocompile.nc",
       "callback_list_nocompile.nc",
+      "containers/buffer_iterator_nocompile.nc",
       "containers/checked_iterators_nocompile.nc",
       "containers/contains_nocompile.nc",
       "containers/enum_set_nocompile.nc",
@@ -4247,18 +4230,13 @@
       "traits_bag_nocompile.nc",
       "types/pass_key_nocompile.nc",
       "types/variant_util_nocompile.nc",
+      "unsafe_buffers_nocompile.nc",
       "values_nocompile.nc",
     ]
-    deps = [ ":base" ]
-  }
-
-  nocompile_source_set("base_unsafe_buffers_nocompile_tests") {
-    configs = [ "//build/config/compiler:unsafe_buffer_warning" ]
-    sources = [
-      "containers/buffer_iterator_nocompile.nc",
-      "unsafe_buffers_nocompile.nc",
+    deps = [
+      ":base",
+      "//build/config/clang:unsafe_buffers_buildflags",
     ]
-    deps = [ ":base" ]
   }
 }
 
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index c7dd9ab..17ba104 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -502,13 +502,6 @@
 // explanation requires cooperation of code that is not fully encapsulated close
 // to the UNSAFE_BUFFERS() usage, it should be rejected and replaced with safer
 // coding patterns or stronger guarantees.
-//
-// UNSAFE_BUFFERS_INCLUDE_BEGIN / UNSAFE_BUFFERS_INCLUDE_END can be used to
-// wrap an `#include` statement for a header which has not been made clean for
-// the -Wunsafe-buffer-usage warning. As these disable warnings for the entire
-// header, and its transitive dependencies, it's clear these should be temporary
-// and the header converted to use safe operations via `span` (or use
-// UNSAFE_BUFFERS() explicitly in rare cases).
 #if defined(__clang__)
 // clang-format off
 // Formatting is off so that we can put each _Pragma on its own line, as
@@ -518,12 +511,8 @@
   __VA_ARGS__                                \
   _Pragma("clang unsafe_buffer_usage end")
 // clang-format on
-#define UNSAFE_BUFFERS_INCLUDE_BEGIN _Pragma("clang unsafe_buffer_usage begin")
-#define UNSAFE_BUFFERS_INCLUDE_END _Pragma("clang unsafe_buffer_usage end")
 #else
 #define UNSAFE_BUFFERS(...) __VA_ARGS__
-#define UNSAFE_BUFFERS_INCLUDE_BEGIN
-#define UNSAFE_BUFFERS_INCLUDE_END
 #endif
 
 #endif  // BASE_COMPILER_SPECIFIC_H_
diff --git a/base/containers/span.h b/base/containers/span.h
index 60bbb4c..b6d7967 100644
--- a/base/containers/span.h
+++ b/base/containers/span.h
@@ -20,11 +20,7 @@
 
 #include "base/check.h"
 #include "base/compiler_specific.h"
-// TODO(crbug.com/40284755): checked_iterators should use UNSAFE_BUFFERS()
-// internally.
-UNSAFE_BUFFERS_INCLUDE_BEGIN
 #include "base/containers/checked_iterators.h"
-UNSAFE_BUFFERS_INCLUDE_END
 #include "base/numerics/safe_conversions.h"
 #include "base/template_util.h"
 #include "base/types/to_address.h"
diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc
index ada4463..0f6076ff 100644
--- a/base/files/file_util_unittest.cc
+++ b/base/files/file_util_unittest.cc
@@ -45,6 +45,7 @@
 #include "base/threading/thread.h"
 #include "base/time/time.h"
 #include "base/uuid.h"
+#include "build/branding_buildflags.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/multiprocess_func_list.h"
@@ -4485,7 +4486,20 @@
   EXPECT_EQ(GetUniquePathNumber(some_file), -1);
 }
 
-TEST_F(FileUtilTest, PreReadFile_ExistingFile_NoSize) {
+#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) && \
+    defined(ARCH_CPU_32_BITS)
+// TODO(crbug.com/327582285): Re-enable these tests. They may be failing due to
+// prefetching failing under memory pressure.
+#define FLAKY_327582285 1
+#endif
+
+#if defined(FLAKY_327582285)
+#define MAYBE_PreReadFileExistingFileNoSize \
+  DISABLED_PreReadFileExistingFileNoSize
+#else
+#define MAYBE_PreReadFileExistingFileNoSize PreReadFileExistingFileNoSize
+#endif
+TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileNoSize) {
   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
   CreateTextFile(text_file, bogus_content);
 
@@ -4493,7 +4507,13 @@
       PreReadFile(text_file, /*is_executable=*/false, /*sequential=*/false));
 }
 
-TEST_F(FileUtilTest, PreReadFile_ExistingFile_ExactSize) {
+#if defined(FLAKY_327582285)
+#define MAYBE_PreReadFileExistingFileExactSize \
+  DISABLED_PreReadFileExistingFileExactSize
+#else
+#define MAYBE_PreReadFileExistingFileExactSize PreReadFileExistingFileExactSize
+#endif
+TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileExactSize) {
   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
   CreateTextFile(text_file, bogus_content);
 
@@ -4501,7 +4521,13 @@
                           /*sequential=*/false, std::size(bogus_content)));
 }
 
-TEST_F(FileUtilTest, PreReadFile_ExistingFile_OverSized) {
+#if defined(FLAKY_327582285)
+#define MAYBE_PreReadFileExistingFileOverSized \
+  DISABLED_PreReadFileExistingFileOverSized
+#else
+#define MAYBE_PreReadFileExistingFileOverSized PreReadFileExistingFileOverSized
+#endif
+TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileOverSized) {
   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
   CreateTextFile(text_file, bogus_content);
 
@@ -4509,7 +4535,14 @@
                           /*sequential=*/false, std::size(bogus_content) * 2));
 }
 
-TEST_F(FileUtilTest, PreReadFile_ExistingFile_UnderSized) {
+#if defined(FLAKY_327582285)
+#define MAYBE_PreReadFileExistingFileUnderSized \
+  DISABLED_PreReadFileExistingFileUnderSized
+#else
+#define MAYBE_PreReadFileExistingFileUnderSized \
+  PreReadFileExistingFileUnderSized
+#endif
+TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileUnderSized) {
   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
   CreateTextFile(text_file, bogus_content);
 
@@ -4517,7 +4550,7 @@
                           /*sequential=*/false, std::size(bogus_content) / 2));
 }
 
-TEST_F(FileUtilTest, PreReadFile_ExistingFile_ZeroSize) {
+TEST_F(FileUtilTest, PreReadFileExistingFileZeroSize) {
   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
   CreateTextFile(text_file, bogus_content);
 
@@ -4525,7 +4558,7 @@
                           /*sequential=*/false, /*max_bytes=*/0));
 }
 
-TEST_F(FileUtilTest, PreReadFile_ExistingEmptyFile_NoSize) {
+TEST_F(FileUtilTest, PreReadFileExistingEmptyFileNoSize) {
   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
   CreateTextFile(text_file, L"");
   // The test just asserts that this doesn't crash. The Windows implementation
@@ -4534,20 +4567,25 @@
   PreReadFile(text_file, /*is_executable=*/false, /*sequential=*/false);
 }
 
-TEST_F(FileUtilTest, PreReadFile_ExistingEmptyFile_ZeroSize) {
+TEST_F(FileUtilTest, PreReadFileExistingEmptyFileZeroSize) {
   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
   CreateTextFile(text_file, L"");
   EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false,
                           /*sequential=*/false, /*max_bytes=*/0));
 }
 
-TEST_F(FileUtilTest, PreReadFile_InexistentFile) {
+TEST_F(FileUtilTest, PreReadFileInexistentFile) {
   FilePath inexistent_file = temp_dir_.GetPath().Append(FPL("inexistent_file"));
   EXPECT_FALSE(PreReadFile(inexistent_file, /*is_executable=*/false,
                            /*sequential=*/false));
 }
 
-TEST_F(FileUtilTest, PreReadFile_Executable) {
+#if defined(FLAKY_327582285)
+#define MAYBE_PreReadFileExecutable DISABLED_PreReadFileExecutable
+#else
+#define MAYBE_PreReadFileExecutable PreReadFileExecutable
+#endif
+TEST_F(FileUtilTest, MAYBE_PreReadFileExecutable) {
   FilePath exe_data_dir;
   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &exe_data_dir));
   exe_data_dir = exe_data_dir.Append(FPL("pe_image_reader"));
@@ -4561,7 +4599,13 @@
       PreReadFile(test_exe, /*is_executable=*/true, /*sequential=*/false));
 }
 
-TEST_F(FileUtilTest, PreReadFileWithSequentialAccess) {
+#if defined(FLAKY_327582285)
+#define MAYBE_PreReadFileWithSequentialAccess \
+  DISABLED_PreReadFileWithSequentialAccess
+#else
+#define MAYBE_PreReadFileWithSequentialAccess PreReadFileWithSequentialAccess
+#endif
+TEST_F(FileUtilTest, MAYBE_PreReadFileWithSequentialAccess) {
   FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
   CreateTextFile(text_file, bogus_content);
 
@@ -4569,6 +4613,8 @@
       PreReadFile(text_file, /*is_executable=*/false, /*sequential=*/true));
 }
 
+#undef FLAKY_327582285
+
 // Test that temp files obtained racily are all unique (no interference between
 // threads). Mimics file operations in DoLaunchChildTestProcess() to rule out
 // thread-safety issues @ https://crbug.com/826408#c17.
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h
index 9bd2aba..0d81133 100644
--- a/base/memory/raw_ptr.h
+++ b/base/memory/raw_ptr.h
@@ -7,12 +7,9 @@
 
 #include "base/compiler_specific.h"
 
-// TODO(crbug.com/40284755): raw_ptr should use UNSAFE_BUFFERS() internally.
-UNSAFE_BUFFERS_INCLUDE_BEGIN
 // Although `raw_ptr` is part of the standalone PA distribution, it is
 // easier to use the shorter path in `//base/memory`. We retain this
 // facade header for ease of typing.
 #include "base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h"  // IWYU pragma: export
-UNSAFE_BUFFERS_INCLUDE_END
 
 #endif  // BASE_MEMORY_RAW_PTR_H_
diff --git a/base/memory/raw_ref.h b/base/memory/raw_ref.h
index 4faa6ed..3aa2798 100644
--- a/base/memory/raw_ref.h
+++ b/base/memory/raw_ref.h
@@ -7,12 +7,9 @@
 
 #include "base/compiler_specific.h"
 
-// TODO(crbug.com/40284755): raw_ref should use UNSAFE_BUFFERS() internally.
-UNSAFE_BUFFERS_INCLUDE_BEGIN
 // Although `raw_ref` is part of the standalone PA distribution, it is
 // easier to use the shorter path in `//base/memory`. We retain this
 // facade header for ease of typing.
 #include "base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref.h"  // IWYU pragma: export
-UNSAFE_BUFFERS_INCLUDE_END
 
 #endif  // BASE_MEMORY_RAW_REF_H_
diff --git a/base/unsafe_buffers_nocompile.nc b/base/unsafe_buffers_nocompile.nc
index f0e245b..f58e025b 100644
--- a/base/unsafe_buffers_nocompile.nc
+++ b/base/unsafe_buffers_nocompile.nc
@@ -6,6 +6,7 @@
 // http://dev.chromium.org/developers/testing/no-compile-tests
 
 #include "base/compiler_specific.h"
+#include "build/config/clang/unsafe_buffers_buildflags.h"
 
 namespace base {
 
@@ -15,7 +16,11 @@
 
 void CallToUnsafeBufferFunctionDisallowed() {
   int arr[] = {1, 2};
+#if BUILDFLAG(UNSAFE_BUFFERS_WARNING_ENABLED)
   uses_pointer_as_array(arr);  // expected-error {{function introduces unsafe buffer manipulation}}
+#else
+  uses_pointer_as_array(arr);  // expected-no-diagnostics: No error when not enabled.
+#endif
 }
 
 }  // namespace base
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 2694fe99..223693d 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -386,8 +386,9 @@
 
 if (is_clang && !is_nacl) {
   default_compiler_configs += [
-    "//build/config/clang:find_bad_constructs",
     "//build/config/clang:extra_warnings",
+    "//build/config/clang:find_bad_constructs",
+    "//build/config/clang:unsafe_buffers",
   ]
 }
 
@@ -517,6 +518,29 @@
   "visibility",
 ]
 
+# Sets default dependencies for static_library and source_set targets.
+foreach(_target_type,
+        [
+          "static_library",
+          "source_set",
+        ]) {
+  template(_target_type) {
+    target(_target_type, target_name) {
+      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
+      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
+      if (!defined(inputs)) {
+        inputs = []
+      }
+
+      # Consumed by the unsafe-buffers plugin during compile.
+      #
+      # TODO(crbug.com/326584510): Reclient doesn't respect this variable, see
+      # rbe_bug_326584510_missing_inputs in //build/config/rbe.gni.
+      inputs += [ "//build/config/unsafe_buffers_paths.txt" ]
+    }
+  }
+}
+
 # Sets default dependencies for executable and shared_library targets.
 #
 # Variables
@@ -538,6 +562,15 @@
                              "*",
                              TESTONLY_AND_VISIBILITY + [ "no_default_deps" ])
       forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
+      if (!defined(inputs)) {
+        inputs = []
+      }
+
+      # Consumed by the unsafe-buffers plugin during compile.
+      #
+      # TODO(crbug.com/326584510): Reclient doesn't respect this variable, see
+      # rbe_bug_326584510_missing_inputs in //build/config/rbe.gni.
+      inputs += [ "//build/config/unsafe_buffers_paths.txt" ]
       if (!defined(deps)) {
         deps = []
       }
diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn
index 6ff3521..e639905 100644
--- a/build/config/clang/BUILD.gn
+++ b/build/config/clang/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/buildflag_header.gni")
 import("//build/config/rust.gni")
 import("clang.gni")
 
@@ -84,6 +85,28 @@
   }
 }
 
+# A plugin for incrementally applying the -Wunsafe-buffer-usage warning.
+config("unsafe_buffers") {
+  if (clang_use_chrome_plugins) {
+    cflags = [
+      "-Xclang",
+      "-add-plugin",
+      "-Xclang",
+      "unsafe-buffers",
+
+      "-Xclang",
+      "-plugin-arg-unsafe-buffers",
+      "-Xclang",
+      rebase_path("//build/config/unsafe_buffers_paths.txt", root_build_dir),
+    ]
+  }
+}
+
+buildflag_header("unsafe_buffers_buildflags") {
+  header = "unsafe_buffers_buildflags.h"
+  flags = [ "UNSAFE_BUFFERS_WARNING_ENABLED=$clang_use_chrome_plugins" ]
+}
+
 # Enables some extra Clang-specific warnings. Some third-party code won't
 # compile with these so may want to remove this config.
 config("extra_warnings") {
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 62088a0..5312e68a 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1966,35 +1966,6 @@
   }
 }
 
-# unsafe_buffer_warning -------------------------------------------------------
-
-# Paths of third-party headers that violate Wunsafe-buffer-usage, but which we
-# have been unable to fix yet. We use this list to be able to make progress and
-# enable the warning on code that we do control/own.
-#
-# WARNING: This will disable all warnings in the files. ONLY USE THIS for
-# third-party code which we do not control/own. Fix the warnings instead in
-# our own code.
-if (is_clang) {
-  unsafe_buffer_warning_header_allowlist =
-      [ "third_party/googletest/src/googletest/include/gtest" ]
-}
-
-# Enables warnings on pointer arithmetic/indexing or calls to functions
-# annotated with `UNSAFE_BUFFER_USAGE`.
-config("unsafe_buffer_warning") {
-  if (is_clang) {
-    cflags = [ "-Wunsafe-buffer-usage" ]
-    foreach(h, unsafe_buffer_warning_header_allowlist) {
-      if (is_win) {
-        cflags += [ "/clang:--system-header-prefix=$h" ]
-      } else {
-        cflags += [ "--system-header-prefix=$h" ]
-      }
-    }
-  }
-}
-
 # chromium_code ---------------------------------------------------------------
 #
 # Toggles between higher and lower warnings for code that is (or isn't)
diff --git a/build/config/unsafe_buffers_paths.txt b/build/config/unsafe_buffers_paths.txt
new file mode 100644
index 0000000..329334a
--- /dev/null
+++ b/build/config/unsafe_buffers_paths.txt
@@ -0,0 +1,22 @@
+# Copyright 2024 The Chromium Project. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# The set of path prefixes that should be checked for unsafe buffer usage (see
+# -Wunsafe-buffer-usage in Clang).
+#
+# ***
+# Paths should be written as relative to the root of the source tree with
+# unix-style path separators. Directory prefixes should end with `/`, such
+# as `base/`.
+# ***
+#
+# Files in this set are known to not use pointer arithmetic/subscripting, and
+# make use of constructs like base::span or containers like std::vector instead.
+#
+# See `docs/unsafe_buffers.md`.
+
+base/containers/buffer_iterator_nocompile.nc
+base/containers/span.h
+base/unsafe_buffers_unittest.cc
+base/unsafe_buffers_nocompile.nc
diff --git a/build/toolchain/apple/toolchain.gni b/build/toolchain/apple/toolchain.gni
index 2d5ea81..2ad540c 100644
--- a/build/toolchain/apple/toolchain.gni
+++ b/build/toolchain/apple/toolchain.gni
@@ -171,7 +171,7 @@
       }
 
       # C/C++ (clang) rewrapper prefix to use when use_remoteexec is true.
-      compiler_prefix = "${rbe_bin_dir}/rewrapper -cfg=${toolchain_rbe_cc_cfg_file} -exec_root=${rbe_exec_root} "
+      compiler_prefix = "${rbe_bin_dir}/rewrapper -cfg=${toolchain_rbe_cc_cfg_file}${rbe_bug_326584510_missing_inputs} -exec_root=${rbe_exec_root} "
     } else if (toolchain_uses_goma) {
       assert(toolchain_cc_wrapper == "",
              "Goma and cc_wrapper can't be used together.")
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni
index 94592ec..a74a4ffb 100644
--- a/build/toolchain/gcc_toolchain.gni
+++ b/build/toolchain/gcc_toolchain.gni
@@ -214,7 +214,7 @@
       }
 
       # C/C++ (clang) rewrapper prefix to use when use_remoteexec is true.
-      compiler_prefix = "${rbe_bin_dir}/rewrapper -cfg=${toolchain_rbe_cc_cfg_file} -exec_root=${rbe_exec_root} "
+      compiler_prefix = "${rbe_bin_dir}/rewrapper -cfg=${toolchain_rbe_cc_cfg_file}${rbe_bug_326584510_missing_inputs} -exec_root=${rbe_exec_root} "
     } else if (toolchain_uses_goma &&
                (!defined(invoker.needs_gomacc_path_arg) ||
                 !invoker.needs_gomacc_path_arg)) {
diff --git a/build/toolchain/rbe.gni b/build/toolchain/rbe.gni
index 7975b49..5652700 100644
--- a/build/toolchain/rbe.gni
+++ b/build/toolchain/rbe.gni
@@ -1,3 +1,7 @@
+# Copyright 2024 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
 # Defines the configuration of Remote Build Execution (RBE).
 
 declare_args() {
@@ -73,3 +77,13 @@
     use_remoteexec_links = false
   }
 }
+
+# TODO(crbug.com/326584510): Reclient does not upload `inputs` from C/C++
+# targets. This file is added to `inputs` for all C targets in
+# //build/config/BUILDCONFIG.gn. We work around the bug in Reclient by
+# specifying the file here.
+#
+# This is a comma-delimited list of paths relative to the source tree root. The
+# leading space is important, if the string is non-empty. :)
+rbe_bug_326584510_missing_inputs =
+    " -inputs=build/config/unsafe_buffers_paths.txt"
diff --git a/build/toolchain/win/toolchain.gni b/build/toolchain/win/toolchain.gni
index 9a70191..de45c13e 100644
--- a/build/toolchain/win/toolchain.gni
+++ b/build/toolchain/win/toolchain.gni
@@ -81,7 +81,7 @@
 
     if (toolchain_uses_remoteexec) {
       if (toolchain_is_clang) {
-        cl_prefix = "${rbe_bin_dir}/rewrapper -cfg=${rbe_cc_cfg_file} -exec_root=${rbe_exec_root} -labels=type=compile,compiler=clang-cl,lang=cpp "
+        cl_prefix = "${rbe_bin_dir}/rewrapper -cfg=${rbe_cc_cfg_file}${rbe_bug_326584510_missing_inputs} -exec_root=${rbe_exec_root} -labels=type=compile,compiler=clang-cl,lang=cpp "
       } else {
         cl_prefix = ""
       }
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 4e81896a8..c12a671 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -993,8 +993,6 @@
   // DrawResult::kSuccess if the frame should be drawn.
   DrawResult CalculateRenderPasses(FrameData* frame);
 
-  void StartScrollbarFadeRecursive(LayerImpl* layer);
-
   // Once a resource is uploaded or deleted, it is no longer an evicted id, this
   // removes it from the evicted set, and updates if we're able to draw now that
   // all UIResources are valid.
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/SelectableTabListEditorTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/SelectableTabListEditorTest.java
index 590d262..5ee841b 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/SelectableTabListEditorTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/SelectableTabListEditorTest.java
@@ -156,7 +156,7 @@
         boolean isTabSwitcherReady =
                 TestThreadUtils.runOnUiThreadBlockingNoException(
                         () -> {
-                            return cta.getTabSwitcherForTesting() != null;
+                            return cta.getTabSwitcherSupplierForTesting().get() != null;
                         });
         if (!isTabSwitcherReady) {
             TabUiTestHelper.enterTabSwitcher(cta);
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherTabletTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherTabletTest.java
index 955769c..e3cc076 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherTabletTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherTabletTest.java
@@ -8,17 +8,19 @@
 import static androidx.test.espresso.assertion.ViewAssertions.matches;
 import static androidx.test.espresso.matcher.ViewMatchers.Visibility.GONE;
 import static androidx.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE;
+import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA;
 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static androidx.test.espresso.matcher.ViewMatchers.withParent;
 
 import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
 import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
 import android.graphics.Bitmap;
@@ -42,25 +44,24 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.CriteriaHelper;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Features.DisableFeatures;
-import org.chromium.base.test.util.Features.EnableFeatures;
 import org.chromium.base.test.util.RequiresRestart;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.compositor.layouts.Layout;
-import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl;
+import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome;
 import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager;
 import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutTab;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.browser.layouts.LayoutStateProvider;
-import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver;
+import org.chromium.chrome.browser.layouts.LayoutTestUtils;
 import org.chromium.chrome.browser.layouts.LayoutType;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabLaunchType;
+import org.chromium.chrome.browser.tabmodel.TabCreator;
 import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
-import org.chromium.chrome.features.start_surface.TabSwitcherAndStartSurfaceLayout;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.R;
@@ -69,15 +70,14 @@
 import org.chromium.chrome.test.util.TabStripUtils;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
+import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.ui.test.util.DisableAnimationsTestRule;
 import org.chromium.ui.test.util.UiRestriction;
 
 import java.lang.ref.WeakReference;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 /** Tests for the {@link TabSwitcher} on tablet */
@@ -86,7 +86,7 @@
     ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
     "force-fieldtrials=Study/Group"
 })
-@DisableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION})
+@DisableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION, ChromeFeatureList.ANDROID_HUB})
 @Restriction({
     Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE,
     UiRestriction.RESTRICTION_TYPE_TABLET
@@ -96,10 +96,6 @@
     private static final long CALLBACK_WAIT_TIMEOUT = 15L;
 
     @ClassRule
-    public static DisableAnimationsTestRule sEnableAnimationsRule =
-            new DisableAnimationsTestRule(false);
-
-    @ClassRule
     public static final ChromeTabbedActivityTestRule sActivityTestRule =
             new ChromeTabbedActivityTestRule();
 
@@ -107,102 +103,87 @@
     public final BlankCTATabInitialStateRule mInitialStateRule =
             new BlankCTATabInitialStateRule(sActivityTestRule, false);
 
-    private CallbackHelper mLayoutChangedCallbackHelper = new CallbackHelper();
-    private int mCurrentlyActiveLayout;
-    private Callback<LayoutManagerImpl> mLayoutManagerCallback;
-
     private Set<WeakReference<Bitmap>> mAllBitmaps = new HashSet<>();
     private TabSwitcher.TabListDelegate mTabListDelegate;
 
     @Before
     public void setUp() throws ExecutionException {
-        CriteriaHelper.pollUiThread(
-                sActivityTestRule.getActivity().getTabModelSelectorSupplier().get()
-                        ::isTabStateInitialized);
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
+        CriteriaHelper.pollUiThread(cta.getTabModelSelectorSupplier().get()::isTabStateInitialized);
 
-        LayoutStateObserver mLayoutObserver =
-                new LayoutStateProvider.LayoutStateObserver() {
-                    @Override
-                    public void onFinishedHiding(int layoutType) {
-                        mCurrentlyActiveLayout = layoutType;
-                        mLayoutChangedCallbackHelper.notifyCalled();
-                    }
-
-                    @Override
-                    public void onStartedShowing(int layoutType) {
-                        if (layoutType != LayoutType.TAB_SWITCHER) {
-                            return;
-                        }
-                        setupForThumbnailCheck();
-                    }
-                };
-        mLayoutManagerCallback = (manager) -> manager.addObserver(mLayoutObserver);
         TestThreadUtils.runOnUiThreadBlocking(
-                () ->
-                        sActivityTestRule
-                                .getActivity()
-                                .getLayoutManagerSupplier()
-                                .addObserver(mLayoutManagerCallback));
+                () -> {
+                    cta.getTabSwitcherSupplierForTesting()
+                            .onAvailable(this::setupForThumbnailCheck);
+                });
     }
 
     @After
     public void cleanup() throws TimeoutException {
-        final ChromeTabbedActivity activity = sActivityTestRule.getActivity();
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    activity.getLayoutManagerSupplier().removeObserver(mLayoutManagerCallback);
-                });
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
         if (mTabListDelegate != null) mTabListDelegate.resetBitmapFetchCountForTesting();
+
+        LayoutManagerChrome layoutManager = cta.getLayoutManager();
+        if (layoutManager.isLayoutVisible(LayoutType.TAB_SWITCHER)
+                && !layoutManager.isLayoutStartingToHide(LayoutType.TAB_SWITCHER)) {
+            TabModelSelector selector = cta.getTabModelSelectorSupplier().get();
+            if (selector.getModel(false).getCount() == 0) {
+                TestThreadUtils.runOnUiThreadBlockingNoException(
+                        () -> {
+                            TabCreator tabCreator = cta.getTabCreator(/* incognito= */ false);
+                            return tabCreator.createNewTab(
+                                    new LoadUrlParams("about:blank"),
+                                    TabLaunchType.FROM_CHROME_UI,
+                                    null,
+                                    0);
+                        });
+                LayoutTestUtils.waitForLayout(layoutManager, LayoutType.BROWSING);
+            } else {
+                if (selector.getCurrentModel().isIncognito()) {
+                    clickIncognitoToggleButton();
+                }
+                exitSwitcherWithTabClick(0);
+            }
+        } else {
+            LayoutTestUtils.waitForLayout(layoutManager, LayoutType.BROWSING);
+        }
     }
 
     @Test
     @MediumTest
     @RequiresRestart
-    @DisabledTest(message = "https://crbug.com/327457591")
     public void testEnterAndExitTabSwitcher() throws TimeoutException {
-        Layout layout = sActivityTestRule.getActivity().getLayoutManager().getOverviewLayout();
-        assertNull("StartSurface layout should not be initialized", layout);
-        ViewStub tabSwitcherStub =
-                (ViewStub)
-                        sActivityTestRule
-                                .getActivity()
-                                .findViewById(R.id.tab_switcher_view_holder_stub);
-        assertTrue(
-                "TabSwitcher view stub should not be inflated",
-                tabSwitcherStub.getParent() != null);
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
+        checkTabSwitcherLayout(cta, false);
+        checkTabSwitcherViewHolderStub(cta, true);
+        checkTabSwitcherViewHolder(cta, false);
 
         TabUiTestHelper.prepareTabsWithThumbnail(sActivityTestRule, 1, 0, null);
         enterGTSWithThumbnailChecking();
-        layout = sActivityTestRule.getActivity().getLayoutManager().getOverviewLayout();
-        assertTrue(
-                "OverviewLayout should be TabSwitcherAndStartSurfaceLayout layout",
-                layout instanceof TabSwitcherAndStartSurfaceLayout);
-        ViewGroup tabSwitcherViewHolder =
-                sActivityTestRule.getActivity().findViewById(R.id.tab_switcher_view_holder);
-        assertNotNull("TabSwitcher view should be inflated", tabSwitcherViewHolder);
+        ensureTabSwitcherLayout();
+
+        checkTabSwitcherLayout(cta, true);
+        checkTabSwitcherViewHolderStub(cta, false);
+        checkTabSwitcherViewHolder(cta, true);
 
         exitGTSAndVerifyThumbnailsAreReleased(1);
-        assertFalse(
-                sActivityTestRule
-                        .getActivity()
-                        .getLayoutManager()
-                        .isLayoutVisible(LayoutType.TAB_SWITCHER));
+        assertFalse(cta.getLayoutManager().isLayoutVisible(LayoutType.TAB_SWITCHER));
     }
 
     @Test
     @MediumTest
     public void testToggleIncognitoSwitcher() throws Exception {
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
         prepareTabs(1, 1);
-        TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
+        TabUiTestHelper.enterTabSwitcher(cta);
 
         // Start with incognito switcher.
-        assertTrue(
-                "Expected to be in Incognito model",
-                sActivityTestRule.getActivity().getCurrentTabModel().isIncognito());
+        assertTrue("Expected to be in Incognito model", cta.getCurrentTabModel().isIncognito());
+
         // Toggle to normal switcher.
         clickIncognitoToggleButton();
 
-        final Tab newTab = sActivityTestRule.getActivity().getCurrentTabModel().getTabAt(0);
+        final Tab newTab = cta.getCurrentTabModel().getTabAt(0);
         assertFalse(newTab.isIncognito());
 
         exitSwitcherWithTabClick(0);
@@ -211,20 +192,16 @@
     @Test
     @MediumTest
     public void testTabSwitcherScrim() throws TimeoutException {
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
         prepareTabs(1, 1);
-        TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
+        TabUiTestHelper.enterTabSwitcher(cta);
 
         ScrimCoordinator scrimCoordinator =
-                sActivityTestRule
-                        .getActivity()
-                        .getRootUiCoordinatorForTesting()
-                        .getScrimCoordinator();
+                cta.getRootUiCoordinatorForTesting().getScrimCoordinator();
         assertTrue(scrimCoordinator.isShowingScrim());
         assertEquals(
-                ChromeColors.getPrimaryBackgroundColor(sActivityTestRule.getActivity(), true),
-                sActivityTestRule
-                        .getActivity()
-                        .getRootUiCoordinatorForTesting()
+                ChromeColors.getPrimaryBackgroundColor(cta, true),
+                cta.getRootUiCoordinatorForTesting()
                         .getStatusBarColorController()
                         .getScrimColorForTesting());
 
@@ -234,13 +211,22 @@
 
     @Test
     @MediumTest
-    public void testGridTabSwitcherOnNoNextTab() throws ExecutionException {
+    public void testGridTabSwitcherOnNoNextTab_WithoutRestart() throws ExecutionException {
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
+        ensureTabSwitcherLayout();
+
+        checkTabSwitcherLayout(cta, /* isInitialized= */ true);
+        checkTabSwitcherViewHolderStub(cta, /* exists= */ false);
+        checkTabSwitcherViewHolder(cta, /* exists= */ true);
+
         // Assert the grid tab switcher is not yet showing.
         onView(withId(R.id.tab_switcher_view_holder)).check(matches(withEffectiveVisibility(GONE)));
 
         // Close the only tab through the tab strip.
         closeTab(false, sActivityTestRule.getActivity().getCurrentTabModel().getTabAt(0).getId());
 
+        LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.TAB_SWITCHER);
+
         // Assert the grid tab switcher is shown automatically, since there is no next tab.
         onView(withId(R.id.tab_switcher_view_holder))
                 .check(matches(withEffectiveVisibility(VISIBLE)));
@@ -248,14 +234,45 @@
 
     @Test
     @MediumTest
-    public void testGridTabSwitcherOnCloseAllTabs() throws ExecutionException {
+    @RequiresRestart
+    public void testGridTabSwitcherOnNoNextTab_WithRestart() throws ExecutionException {
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
+        checkTabSwitcherLayout(cta, /* isInitialized= */ false);
+        checkTabSwitcherViewHolderStub(cta, /* exists= */ true);
+        checkTabSwitcherViewHolder(cta, /* exists= */ false);
+
+        // Close the only tab through the tab strip.
+        closeTab(false, sActivityTestRule.getActivity().getCurrentTabModel().getTabAt(0).getId());
+
+        LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.TAB_SWITCHER);
+
+        // Assert the grid tab switcher is shown automatically, since there is no next tab.
+        onView(withId(R.id.tab_switcher_view_holder))
+                .check(matches(withEffectiveVisibility(VISIBLE)));
+
+        checkTabSwitcherLayout(cta, /* isInitialized= */ true);
+        checkTabSwitcherViewHolderStub(cta, /* exists= */ false);
+        checkTabSwitcherViewHolder(cta, /* exists= */ true);
+    }
+
+    @Test
+    @MediumTest
+    public void testGridTabSwitcherOnCloseAllTabs_WithoutRestart() throws ExecutionException {
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
+        ensureTabSwitcherLayout();
+
+        checkTabSwitcherLayout(cta, /* isInitialized= */ true);
+        checkTabSwitcherViewHolderStub(cta, /* exists= */ false);
+        checkTabSwitcherViewHolder(cta, /* exists= */ true);
+
         // Assert the grid tab switcher is not yet showing.
         onView(withId(R.id.tab_switcher_view_holder)).check(matches(withEffectiveVisibility(GONE)));
 
         // Close all tabs.
         ChromeTabUtils.closeAllTabs(
-                InstrumentationRegistry.getInstrumentation(),
-                sActivityTestRule.getActivity().getTabModelSelectorSupplier());
+                InstrumentationRegistry.getInstrumentation(), cta.getTabModelSelectorSupplier());
+
+        LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.TAB_SWITCHER);
 
         // Assert the grid tab switcher is shown automatically, since there is no next tab.
         onView(withId(R.id.tab_switcher_view_holder))
@@ -265,162 +282,112 @@
     @Test
     @MediumTest
     public void testGridTabSwitcherToggleIncognitoWithNoRegularTab() throws ExecutionException {
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
+        TabModel regularModel = cta.getTabModelSelectorSupplier().get().getModel(false);
+
+        // Open an incognito tab.
+        prepareTabs(1, 1);
+
         // Close all the regular tabs.
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> {
-                    sActivityTestRule
-                            .getActivity()
-                            .getCurrentTabModel()
-                            .closeTab(sActivityTestRule.getActivity().getActivityTab());
+                    regularModel.closeTab(regularModel.getTabAt(0));
                 });
-        assertEquals(
-                "Expected to be 0 tabs in regular model",
-                0,
-                sActivityTestRule
-                        .getActivity()
-                        .getTabModelSelectorSupplier()
-                        .get()
-                        .getModel(false)
-                        .getCount());
-        // Open an incognito tab.
-        prepareTabs(0, 1);
-        assertTrue(
-                "Expected to be in Incognito model",
-                sActivityTestRule.getActivity().getCurrentTabModel().isIncognito());
+        assertEquals("Expected to be 0 tabs in regular model", 0, regularModel.getCount());
+        assertTrue("Expected to be in Incognito model", cta.getCurrentTabModel().isIncognito());
+
         // Assert the grid tab switcher is not yet showing.
         onView(withId(R.id.tab_switcher_view_holder)).check(matches(withEffectiveVisibility(GONE)));
+
+        TabUiTestHelper.enterTabSwitcher(cta);
+
         // Toggle to normal switcher.
         clickIncognitoToggleButton();
-        // Assert the grid tab switcher is shown automatically, since there is no regular tab.
+
         onView(withId(R.id.tab_switcher_view_holder))
                 .check(matches(withEffectiveVisibility(VISIBLE)));
     }
 
-    @Test
-    @MediumTest
-    public void testGridTabSwitcher() throws ExecutionException {
-        prepareTabs(2, 0);
-        // Verifies that the dialog visibility supplier doesn't crash when closing a Tab without the
-        // grid tab switcher is inflated.
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    sActivityTestRule
-                            .getActivity()
-                            .getCurrentTabModel()
-                            .closeTab(sActivityTestRule.getActivity().getActivityTab());
-                });
-
-        Layout layout =
-                sActivityTestRule.getActivity().getLayoutManager().getTabSwitcherLayoutForTesting();
-        assertNull("StartSurface layout should not be initialized", layout);
-        ViewStub tabSwitcherStub =
-                (ViewStub)
-                        sActivityTestRule
-                                .getActivity()
-                                .findViewById(R.id.tab_switcher_view_holder_stub);
-        assertTrue(
-                "TabSwitcher view stub should not be inflated",
-                tabSwitcherStub.getParent() != null);
-
-        // Click tab switcher button
-        TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
-
-        layout =
-                sActivityTestRule.getActivity().getLayoutManager().getTabSwitcherLayoutForTesting();
-        assertTrue(
-                "OverviewLayout should be TabSwitcherAndStartSurfaceLayout layout",
-                layout instanceof TabSwitcherLayout);
-        ViewGroup tabSwitcherViewHolder =
-                sActivityTestRule.getActivity().findViewById(R.id.tab_switcher_view_holder);
-        assertNotNull("TabSwitcher view should be inflated", tabSwitcherViewHolder);
-    }
-
     // Regression test for crbug.com/1487114.
     @Test
     @MediumTest
-    @EnableFeatures({ChromeFeatureList.DEFER_TAB_SWITCHER_LAYOUT_CREATION})
+    @RequiresRestart
     public void testGridTabSwitcher_DeferredTabSwitcherLayoutCreation() throws ExecutionException {
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
         prepareTabs(2, 0);
         // Verifies that the dialog visibility supplier doesn't crash when closing a Tab without the
         // grid tab switcher is inflated.
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> {
-                    sActivityTestRule
-                            .getActivity()
-                            .getCurrentTabModel()
-                            .closeTab(sActivityTestRule.getActivity().getActivityTab());
+                    cta.getCurrentTabModel().closeTab(cta.getActivityTab());
                 });
 
-        Layout layout =
-                sActivityTestRule.getActivity().getLayoutManager().getTabSwitcherLayoutForTesting();
-        assertNull("StartSurface layout should not be initialized", layout);
-        ViewStub tabSwitcherStub =
-                (ViewStub)
-                        sActivityTestRule
-                                .getActivity()
-                                .findViewById(R.id.tab_switcher_view_holder_stub);
-        assertTrue(
-                "TabSwitcher view stub should not be inflated",
-                tabSwitcherStub.getParent() != null);
+        checkTabSwitcherLayout(cta, /* isInitialized= */ false);
+        checkTabSwitcherViewHolderStub(cta, /* exists= */ true);
+        checkTabSwitcherViewHolder(cta, /* exists= */ false);
 
         // Click tab switcher button
         TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
 
-        layout =
-                sActivityTestRule.getActivity().getLayoutManager().getTabSwitcherLayoutForTesting();
-        assertTrue(
-                "OverviewLayout should be TabSwitcherAndStartSurfaceLayout layout",
-                layout instanceof TabSwitcherLayout);
-        ViewGroup tabSwitcherViewHolder =
-                sActivityTestRule.getActivity().findViewById(R.id.tab_switcher_view_holder);
-        assertNotNull("TabSwitcher view should be inflated", tabSwitcherViewHolder);
+        checkTabSwitcherLayout(cta, /* isInitialized= */ true);
+        checkTabSwitcherViewHolderStub(cta, /* exists= */ false);
+        checkTabSwitcherViewHolder(cta, /* exists= */ true);
     }
 
     @Test
     @MediumTest
     public void testEmptyStateView() throws Exception {
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
         prepareTabs(1, 0);
-        TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
+        TabUiTestHelper.enterTabSwitcher(cta);
 
         // Close the last tab.
-        closeTab(false, sActivityTestRule.getActivity().getCurrentTabModel().getTabAt(0).getId());
+        closeTab(false, cta.getCurrentTabModel().getTabAt(0).getId());
+
+        LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.TAB_SWITCHER);
 
         // Check whether empty view show up.
         onView(
                         allOf(
                                 withId(R.id.empty_state_container),
-                                withParent(withId(R.id.tab_switcher_view_holder))))
+                                isDescendantOfA(withId(R.id.tab_switcher_view_holder))))
                 .check(matches(isDisplayed()));
     }
 
     @Test
     @MediumTest
     public void testEmptyStateView_ToggleIncognito() throws Exception {
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
         prepareTabs(1, 1);
         TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
 
         // Close the last normal tab.
-        closeTab(false, sActivityTestRule.getActivity().getCurrentTabModel().getTabAt(0).getId());
-
-        // Switch to incognito tab switcher.
-        clickIncognitoToggleButton();
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> {
+                    TabModel model = cta.getTabModelSelector().getModel(false);
+                    model.closeTab(model.getTabAt(0));
+                });
 
         // Check empty view should never show up in incognito tab switcher.
         onView(
                         allOf(
                                 withId(R.id.empty_state_container),
-                                withParent(withId(R.id.tab_switcher_view_holder))))
+                                isDescendantOfA(withId(R.id.tab_switcher_view_holder))))
                 .check(matches(not(isDisplayed())));
 
         // Close the last incognito tab.
-        closeTab(true, sActivityTestRule.getActivity().getCurrentTabModel().getTabAt(0).getId());
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> {
+                    TabModel model = cta.getTabModelSelector().getModel(true);
+                    model.closeTab(model.getTabAt(0));
+                });
 
         // Incognito tab switcher should exit to go to normal tab switcher and we should see empty
         // view.
         onView(
                         allOf(
                                 withId(R.id.empty_state_container),
-                                withParent(withId(R.id.tab_switcher_view_holder))))
+                                isDescendantOfA(withId(R.id.tab_switcher_view_holder))))
                 .check(matches(isDisplayed()));
     }
 
@@ -464,11 +431,12 @@
 
     private void exitSwitcherWithTabClick(int index) throws TimeoutException {
         TabUiTestHelper.clickNthCardFromTabSwitcher(sActivityTestRule.getActivity(), index);
-        mLayoutChangedCallbackHelper.waitForCallback(1, 1, CALLBACK_WAIT_TIMEOUT, TimeUnit.SECONDS);
-        assertTrue(mCurrentlyActiveLayout == LayoutType.TAB_SWITCHER);
+        LayoutTestUtils.waitForLayout(
+                sActivityTestRule.getActivity().getLayoutManager(), LayoutType.BROWSING);
     }
 
     private void enterGTSWithThumbnailChecking() {
+        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
         Tab currentTab = sActivityTestRule.getActivity().getTabModelSelector().getCurrentTab();
         // Native tabs need to be invalidated first to trigger thumbnail taking, so skip them.
         boolean checkThumbnail = !currentTab.isNativePage();
@@ -476,16 +444,12 @@
         if (checkThumbnail) {
             TestThreadUtils.runOnUiThreadBlocking(
                     () -> {
-                        sActivityTestRule
-                                .getActivity()
-                                .getTabContentManager()
-                                .removeTabThumbnail(currentTab.getId());
+                        cta.getTabContentManager().removeTabThumbnail(currentTab.getId());
                     });
         }
-        TabUiTestHelper.enterTabSwitcher(sActivityTestRule.getActivity());
+        TabUiTestHelper.enterTabSwitcher(cta);
 
-        TabUiTestHelper.verifyAllTabsHaveThumbnail(
-                sActivityTestRule.getActivity().getCurrentTabModel());
+        TabUiTestHelper.verifyAllTabsHaveThumbnail(cta.getCurrentTabModel());
     }
 
     private void closeTab(final boolean incognito, final int id) {
@@ -503,35 +467,29 @@
                 });
     }
 
-    private void retrieveTabListDelegate() {
-        Layout overviewLayout =
-                sActivityTestRule.getActivity().getLayoutManager().getOverviewLayout();
-
-        if (overviewLayout == null) {
-            Layout tabSwitcherLayout =
-                sActivityTestRule.getActivity().getLayoutManager().getTabSwitcherLayoutForTesting();
-            assertTrue("Layout not instance of TabSwitcherLayout -" + tabSwitcherLayout,
-                tabSwitcherLayout instanceof TabSwitcherLayout);
-            mTabListDelegate =
-                ((TabSwitcherLayout) tabSwitcherLayout)
-                    .getTabSwitcherForTesting()
-                    .getTabListDelegate();
-            return;
+    private TabSwitcherLayout ensureTabSwitcherLayout() {
+        LayoutManagerChrome layoutManager = sActivityTestRule.getActivity().getLayoutManager();
+        Layout tabSwitcherLayout = layoutManager.getTabSwitcherLayoutForTesting();
+        if (tabSwitcherLayout == null) {
+            TestThreadUtils.runOnUiThreadBlocking(layoutManager::initTabSwitcherLayoutForTesting);
+            tabSwitcherLayout = layoutManager.getTabSwitcherLayoutForTesting();
         }
-
-        assertTrue("Layout not instance of TabSwitcherAndStartSurfaceLayout" + overviewLayout,
-            overviewLayout instanceof TabSwitcherAndStartSurfaceLayout);
-
-        mTabListDelegate =
-            ((TabSwitcherAndStartSurfaceLayout) overviewLayout)
-                        .getStartSurfaceForTesting()
-                        .getGridTabListDelegate();
+        assertTrue(
+                "Layout not instance of TabSwitcherLayout -" + tabSwitcherLayout,
+                tabSwitcherLayout instanceof TabSwitcherLayout);
+        return (TabSwitcherLayout) tabSwitcherLayout;
     }
 
-    private void setupForThumbnailCheck() {
-        retrieveTabListDelegate();
+    private void retrieveTabListDelegate() {
+        TabSwitcherLayout tabSwitcherLayout = ensureTabSwitcherLayout();
+        mTabListDelegate = tabSwitcherLayout.getTabSwitcherForTesting().getTabListDelegate();
+    }
+
+    private void setupForThumbnailCheck(TabSwitcher tabSwitcher) {
+        mTabListDelegate = tabSwitcher.getTabListDelegate();
         Callback<Bitmap> mBitmapListener = (bitmap) -> mAllBitmaps.add(new WeakReference<>(bitmap));
         mTabListDelegate.setBitmapCallbackForTesting(mBitmapListener);
+        mTabListDelegate.resetBitmapFetchCountForTesting();
         assertEquals(0, mTabListDelegate.getBitmapFetchCountForTesting());
     }
 
@@ -545,7 +503,7 @@
 
         if (mTabListDelegate == null) retrieveTabListDelegate();
         assertTrue(mTabListDelegate.getBitmapFetchCountForTesting() > 0);
-        assertEquals(tabsWithThumbnail, mAllBitmaps.size());
+        assertThat(mAllBitmaps.size(), greaterThanOrEqualTo(tabsWithThumbnail));
 
         final int index = sActivityTestRule.getActivity().getCurrentTabModel().index();
         exitSwitcherWithTabClick(index);
@@ -563,4 +521,35 @@
                     return true;
                 });
     }
+
+    private void checkTabSwitcherLayout(ChromeTabbedActivity cta, boolean isInitialized) {
+        Layout layout = cta.getLayoutManager().getTabSwitcherLayoutForTesting();
+        if (isInitialized) {
+            assertNotNull("TabSwitcherLayout should be initialized", layout);
+        } else {
+            assertNull("TabSwitcherLayout should not be initialized", layout);
+        }
+    }
+
+    private void checkTabSwitcherViewHolderStub(ChromeTabbedActivity cta, boolean exists) {
+        ViewStub tabSwitcherStub = (ViewStub) cta.findViewById(R.id.tab_switcher_view_holder_stub);
+        if (exists) {
+            assertTrue(
+                    "TabSwitcher view stub should not be inflated",
+                    tabSwitcherStub != null && tabSwitcherStub.getParent() != null);
+        } else {
+            assertTrue(
+                    "TabSwitcher view stub should have been inflated",
+                    tabSwitcherStub == null || tabSwitcherStub.getParent() == null);
+        }
+    }
+
+    private void checkTabSwitcherViewHolder(ChromeTabbedActivity cta, boolean exists) {
+        ViewGroup tabSwitcherViewHolder = cta.findViewById(R.id.tab_switcher_view_holder);
+        if (exists) {
+            assertNotNull("TabSwitcher view should be inflated", tabSwitcherViewHolder);
+        } else {
+            assertNull("TabSwitcher view should not be inflated", tabSwitcherViewHolder);
+        }
+    }
 }
diff --git a/chrome/android/features/tab_ui/public/BUILD.gn b/chrome/android/features/tab_ui/public/BUILD.gn
index ec1b9f61..02feadfa 100644
--- a/chrome/android/features/tab_ui/public/BUILD.gn
+++ b/chrome/android/features/tab_ui/public/BUILD.gn
@@ -31,6 +31,7 @@
 
   deps = [
     ":ui_java_resources",
+    "//base:base_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/ui/android/theme:java",
     "//components/browser_ui/styles/android:java",
diff --git a/chrome/android/features/tab_ui/public/android/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeUtil.java b/chrome/android/features/tab_ui/public/android/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeUtil.java
index d0fa0cc..60196df5 100644
--- a/chrome/android/features/tab_ui/public/android/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeUtil.java
+++ b/chrome/android/features/tab_ui/public/android/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeUtil.java
@@ -7,9 +7,12 @@
 import android.content.Context;
 
 import androidx.annotation.ColorInt;
+import androidx.annotation.ColorRes;
 import androidx.annotation.DrawableRes;
+import androidx.annotation.Px;
 import androidx.core.content.res.ResourcesCompat;
 
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.ui.theme.ChromeSemanticColorUtils;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.ui.util.ColorUtils;
@@ -26,19 +29,42 @@
      *
      * @param context {@link Context} used to retrieve color.
      * @param isIncognito Whether the color is used for incognito mode.
-     * @return The {@link ColorInt} for tab strip redesign background.
+     * @param isActivityFocused Whether the activity containing the tab strip is focused.
+     * @return The {@link ColorInt} for the tab strip background.
      */
-    public static @ColorInt int getTabStripBackgroundColor(Context context, boolean isIncognito) {
-        // Use black color for incognito and night mode for folio.
+    public static @ColorInt int getTabStripBackgroundColor(
+            Context context, boolean isIncognito, boolean isActivityFocused) {
+        // Default specs for incognito, dark and light themes, used when
+        // TAB_STRIP_LAYOUT_OPTIMIZATION is disabled or when the activity is focused when this
+        // feature is enabled.
+        @ColorRes int incognitoColor = R.color.default_bg_color_dark_elev_2_baseline;
+        @Px
+        float darkThemeElevation =
+                context.getResources().getDimensionPixelSize(R.dimen.default_elevation_2);
+        @Px
+        float lightThemeElevation =
+                context.getResources().getDimensionPixelSize(R.dimen.default_elevation_3);
+
+        // Specs for when the activity containing the tab strip is not focused.
+        // TODO (crbug.com/326290073): Use another boolean to allow using the default spec even when
+        // the activity is not in focus, when this feature is enabled.
+        // TODO (crbug.com/326290073): Update this to use the helper method from
+        // TabUiFeatureUtilities.
+        if (ChromeFeatureList.sTabStripLayoutOptimization.isEnabled() && !isActivityFocused) {
+            incognitoColor = R.color.default_bg_color_dark_elev_1_baseline;
+            darkThemeElevation =
+                    context.getResources().getDimensionPixelSize(R.dimen.default_elevation_1);
+            lightThemeElevation =
+                    context.getResources().getDimensionPixelSize(R.dimen.default_elevation_2);
+        }
+
         if (isIncognito) {
-            return context.getColor(R.color.default_bg_color_dark_elev_2_baseline);
+            return context.getColor(incognitoColor);
         }
 
-        if (ColorUtils.inNightMode(context)) {
-            return ChromeColors.getSurfaceColor(context, R.dimen.default_elevation_2);
-        }
-
-        return ChromeColors.getSurfaceColor(context, R.dimen.default_elevation_3);
+        return ChromeColors.getSurfaceColor(
+                context,
+                ColorUtils.inNightMode(context) ? darkThemeElevation : lightThemeElevation);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index b1d5548..0a4c00b8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -3744,8 +3744,8 @@
         return mStartSurfaceSupplier.get();
     }
 
-    public TabSwitcher getTabSwitcherForTesting() {
-        return mTabSwitcherSupplier.get();
+    public OneshotSupplier<TabSwitcher> getTabSwitcherSupplierForTesting() {
+        return mTabSwitcherSupplier;
     }
 
     private ComposedBrowserControlsVisibilityDelegate getAppBrowserControlsVisibilityDelegate() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
index 51746fb..402c071 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
@@ -48,6 +48,7 @@
 import org.chromium.chrome.browser.layouts.scene_layer.SceneOverlayLayer;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver;
+import org.chromium.chrome.browser.lifecycle.TopResumedActivityChangedObserver;
 import org.chromium.chrome.browser.multiwindow.MultiInstanceManager;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.Tab.LoadUrlResult;
@@ -89,7 +90,10 @@
  * all input and model events to the proper destination.
  */
 public class StripLayoutHelperManager
-        implements SceneOverlay, PauseResumeWithNativeObserver, TabStripHeightObserver {
+        implements SceneOverlay,
+                PauseResumeWithNativeObserver,
+                TabStripHeightObserver,
+                TopResumedActivityChangedObserver {
 
     /**
      * POD type that contains the necessary tab model info on startup. Used in the startup flicker
@@ -172,6 +176,8 @@
     private final ViewStub mTabHoverCardViewStub;
     private float mModelSelectorWidth;
 
+    private boolean mIsTopResumedActivity;
+
     // 3-dots menu button with tab strip end padding
     private float mStripEndPadding;
     private TabModelSelectorTabModelObserver mTabModelSelectorTabModelObserver;
@@ -497,6 +503,10 @@
             }
         }
 
+        // TODO (crbug.com/326290073): Update this to check the actual activity resumption state
+        // because it is technically possible for the current activity to lose the top resumed
+        // activity status before the StripLayoutHelperManager instance is instantiated.
+        mIsTopResumedActivity = true;
         onContextChanged(context);
     }
 
@@ -741,6 +751,15 @@
         return mStripTransitionScrimOpacity;
     }
 
+    @Override
+    public void onTopResumedActivityChanged(boolean isTopResumedActivity) {
+        // TODO (crbug.com/326290073): Update this to use the helper method from
+        // TabUiFeatureUtilities.
+        if (!ChromeFeatureList.sTabStripLayoutOptimization.isEnabled()) return;
+        mIsTopResumedActivity = isTopResumedActivity;
+        mUpdateHost.requestUpdate();
+    }
+
     private float getModelSelectorButtonWidthWithEndPadding() {
         return mModelSelectorWidth + mStripEndPadding;
     }
@@ -1096,7 +1115,8 @@
     }
 
     public @ColorInt int getBackgroundColor() {
-        return TabUiThemeUtil.getTabStripBackgroundColor(mContext, mIsIncognito);
+        return TabUiThemeUtil.getTabStripBackgroundColor(
+                mContext, mIsIncognito, mIsTopResumedActivity);
     }
 
     /**
@@ -1204,4 +1224,8 @@
     public TabDragSource getTabDragSourceForTesting() {
         return mTabDragSource;
     }
+
+    public void setIsIncognitoForTesting(boolean isIncognito) {
+        mIsIncognito = isIncognito;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcherImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcherImpl.java
index b1ccb087..87a9781 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcherImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcherImpl.java
@@ -24,6 +24,7 @@
 import org.chromium.chrome.browser.lifecycle.RecreateObserver;
 import org.chromium.chrome.browser.lifecycle.SaveInstanceStateObserver;
 import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
+import org.chromium.chrome.browser.lifecycle.TopResumedActivityChangedObserver;
 import org.chromium.chrome.browser.lifecycle.WindowFocusChangedObserver;
 
 /**
@@ -51,6 +52,8 @@
     private final ObserverList<RecreateObserver> mRecreateObservers = new ObserverList<>();
     private final ObserverList<OnUserLeaveHintObserver> mOnUserLeaveHintObservers =
             new ObserverList<>();
+    private final ObserverList<TopResumedActivityChangedObserver>
+            mTopResumedActivityChangedObservers = new ObserverList<>();
 
     private final Activity mActivity;
 
@@ -98,6 +101,10 @@
         if (observer instanceof OnUserLeaveHintObserver) {
             mOnUserLeaveHintObservers.addObserver((OnUserLeaveHintObserver) observer);
         }
+        if (observer instanceof TopResumedActivityChangedObserver) {
+            mTopResumedActivityChangedObservers.addObserver(
+                    (TopResumedActivityChangedObserver) observer);
+        }
     }
 
     @Override
@@ -136,6 +143,10 @@
         if (observer instanceof OnUserLeaveHintObserver) {
             mOnUserLeaveHintObservers.removeObserver((OnUserLeaveHintObserver) observer);
         }
+        if (observer instanceof TopResumedActivityChangedObserver) {
+            mTopResumedActivityChangedObservers.removeObserver(
+                    (TopResumedActivityChangedObserver) observer);
+        }
     }
 
     @Override
@@ -236,6 +247,7 @@
         mConfigurationChangedListeners.clear();
         mDestroyables.clear();
         mRecreateObservers.clear();
+        mTopResumedActivityChangedObservers.clear();
     }
 
     void dispatchOnSaveInstanceState(Bundle outBundle) {
@@ -273,4 +285,10 @@
             observer.onUserLeaveHint();
         }
     }
+
+    void dispatchOnTopResumedActivityChanged(boolean isTopResumedActivity) {
+        for (TopResumedActivityChangedObserver observer : mTopResumedActivityChangedObservers) {
+            observer.onTopResumedActivityChanged(isTopResumedActivity);
+        }
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
index 061c25c..b9762a0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
@@ -776,6 +776,14 @@
         Thread.dumpStack();
     }
 
+    @CallSuper
+    @Override
+    public void onTopResumedActivityChanged(boolean isTopResumedActivity) {
+        super.onTopResumedActivityChanged(isTopResumedActivity);
+
+        mLifecycleDispatcher.dispatchOnTopResumedActivityChanged(isTopResumedActivity);
+    }
+
     /**
      * @return Whether the activity is running in tablet mode.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index d7c4376..1cba20d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -148,7 +148,6 @@
 import org.chromium.chrome.browser.ui.appmenu.AppMenuCoordinator;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuDelegate;
 import org.chromium.chrome.browser.ui.appmenu.MenuButtonDelegate;
-import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeController;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.ui.native_page.NativePage;
 import org.chromium.chrome.browser.ui.system.StatusBarColorController;
@@ -260,7 +259,6 @@
     private final CompositorViewHolder mCompositorViewHolder;
     private final BrowserControlsSizer mBrowserControlsSizer;
     private final FullscreenManager mFullscreenManager;
-    private final ObservableSupplier<EdgeToEdgeController> mEdgeToEdgeControllerSupplier;
     private LocationBarFocusScrimHandler mLocationBarFocusHandler;
     private ComponentCallbacks mComponentCallbacks;
     private final LoadProgressCoordinator mProgressBarCoordinator;
@@ -465,8 +463,6 @@
      * @param activity The Android activity.
      * @param controlsSizer The {@link BrowserControlsSizer} for the activity.
      * @param fullscreenManager The {@link FullscreenManager} for the activity.
-     * @param edgeToEdgeControllerSupplier Supplies an {@link EdgeToEdgeController} needed for
-     *     Bottom Controls Toolbar.
      * @param controlContainer The container of the toolbar.
      * @param compositorViewHolder Class that holds a {@link CompositorView}.
      * @param urlFocusChangedCallback The callback to be notified when the URL focus changes.
@@ -518,7 +514,6 @@
             AppCompatActivity activity,
             BrowserControlsSizer controlsSizer,
             FullscreenManager fullscreenManager,
-            ObservableSupplier<EdgeToEdgeController> edgeToEdgeControllerSupplier,
             ToolbarControlContainer controlContainer,
             CompositorViewHolder compositorViewHolder,
             Callback<Boolean> urlFocusChangedCallback,
@@ -569,7 +564,6 @@
         mCompositorViewHolder = compositorViewHolder;
         mBrowserControlsSizer = controlsSizer;
         mFullscreenManager = fullscreenManager;
-        mEdgeToEdgeControllerSupplier = edgeToEdgeControllerSupplier;
         mActionBarDelegate =
                 new ViewShiftingActionBarDelegate(
                         activity.getSupportActionBar(),
@@ -1656,7 +1650,6 @@
                         mCompositorViewHolder.getResourceManager(),
                         mBrowserControlsSizer,
                         mFullscreenManager,
-                        mEdgeToEdgeControllerSupplier,
                         (ScrollingBottomViewResourceFrameLayout) root,
                         mTabGroupUi,
                         mTabObscuringHandler,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
index 83e1bc4..4b1698b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -1395,7 +1395,6 @@
                             mActivity,
                             mBrowserControlsManager,
                             mFullscreenManager,
-                            mEdgeToEdgeControllerSupplier,
                             toolbarContainer,
                             mCompositorViewHolderSupplier.get(),
                             urlFocusChangedCallback,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
index 7e946287..67f44970 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
@@ -515,9 +515,15 @@
         }
 
         if (mIsTablet) {
+            // When applicable, the status bar should use the focused activity tab strip color
+            // (default), and should not be affected by an activity focus change.
+            // TODO (crbug.com/326290073): Use another boolean to allow using the default color spec
+            // even when the activity is not in focus, to avoid any confusion stemming from why
+            // |isActivityFocused| is always true in this invocation here.
             return mTabStripHiddenOnTablet
                     ? mToolbarColor
-                    : TabUiThemeUtil.getTabStripBackgroundColor(mWindow.getContext(), mIsIncognito);
+                    : TabUiThemeUtil.getTabStripBackgroundColor(
+                            mWindow.getContext(), mIsIncognito, /* isActivityFocused= */ true);
         }
 
         // When Omnibox gains focus, we want to clear the status bar theme color.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
index ab46358..f2b44a4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
@@ -751,7 +751,8 @@
                         tabListMode =
                                 mActivityTestRule
                                         .getActivity()
-                                        .getTabSwitcherForTesting()
+                                        .getTabSwitcherSupplierForTesting()
+                                        .get()
                                         .getTabListDelegate()
                                         .getListModeForTesting();
                     } else {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java
index 0c37a178..eee0d64b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java
@@ -503,7 +503,7 @@
                 () -> statusBarColorController.updateStatusBarColor());
         assertEquals(
                 "Wrong value returned for Tab Strip Redesign Folio.",
-                TabUiThemeUtil.getTabStripBackgroundColor(activity, false),
+                TabUiThemeUtil.getTabStripBackgroundColor(activity, false, true),
                 activity.getWindow().getStatusBarColor());
     }
 
@@ -552,7 +552,7 @@
                 "Status bar color on tablet should use the tab strip transition scrim overlay"
                         + " during a strip transition.",
                 ColorUtils.getColorWithOverlay(
-                        TabUiThemeUtil.getTabStripBackgroundColor(activity, false),
+                        TabUiThemeUtil.getTabStripBackgroundColor(activity, false, true),
                         toolbarColor,
                         0.5f),
                 activity.getWindow().getStatusBarColor());
@@ -566,7 +566,7 @@
         assertEquals(
                 "Status bar color on tablet should match the tab strip background when the tab"
                         + " strip is visible.",
-                TabUiThemeUtil.getTabStripBackgroundColor(activity, false),
+                TabUiThemeUtil.getTabStripBackgroundColor(activity, false, true),
                 activity.getWindow().getStatusBarColor());
         ToolbarFeatures.USE_TOOLBAR_BG_COLOR_FOR_STRIP_TRANSITION_SCRIM.setForTesting(false);
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java
index 20f21566..822f146 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java
@@ -182,11 +182,80 @@
     }
 
     @Test
-    public void testGetBackgroundColor() {
-        mStripLayoutHelperManager.onContextChanged(mContext);
+    @DisableFeatures(ChromeFeatureList.TAB_STRIP_LAYOUT_OPTIMIZATION)
+    public void testGetBackgroundColor_ActivityFocusChange_TsloDisabled() {
         assertEquals(
+                "Initial strip background color is incorrect.",
                 ChromeColors.getSurfaceColor(mContext, R.dimen.default_elevation_3),
                 mStripLayoutHelperManager.getBackgroundColor());
+        // Assume the current activity lost focus.
+        mStripLayoutHelperManager.onTopResumedActivityChanged(false);
+        assertEquals(
+                "Strip background color should not be updated when activity focus state changes",
+                ChromeColors.getSurfaceColor(mContext, R.dimen.default_elevation_3),
+                mStripLayoutHelperManager.getBackgroundColor());
+    }
+
+    @Test
+    @EnableFeatures(ChromeFeatureList.TAB_STRIP_LAYOUT_OPTIMIZATION)
+    public void testGetBackgroundColor_ActivityFocusChange_LightTheme() {
+        doTestBackgroundColorOnActivityFocusChange(
+                /* isNightMode= */ false, /* isIncognito= */ false);
+    }
+
+    @Test
+    @Config(qualifiers = "night")
+    @EnableFeatures(ChromeFeatureList.TAB_STRIP_LAYOUT_OPTIMIZATION)
+    public void testGetBackgroundColor_ActivityFocusChange_DarkTheme() {
+        doTestBackgroundColorOnActivityFocusChange(
+                /* isNightMode= */ true, /* isIncognito= */ false);
+    }
+
+    @Test
+    @EnableFeatures(ChromeFeatureList.TAB_STRIP_LAYOUT_OPTIMIZATION)
+    public void testGetBackgroundColor_ActivityFocusChange_Incognito() {
+        mStripLayoutHelperManager.setIsIncognitoForTesting(true);
+        doTestBackgroundColorOnActivityFocusChange(
+                /* isNightMode= */ false, /* isIncognito= */ true);
+    }
+
+    private void doTestBackgroundColorOnActivityFocusChange(
+            boolean isNightMode, boolean isIncognito) {
+        @ColorInt
+        int focusedColor =
+                ChromeColors.getSurfaceColor(
+                        mContext,
+                        isNightMode ? R.dimen.default_elevation_2 : R.dimen.default_elevation_3);
+        @ColorInt
+        int unfocusedColor =
+                ChromeColors.getSurfaceColor(
+                        mContext,
+                        isNightMode ? R.dimen.default_elevation_1 : R.dimen.default_elevation_2);
+
+        if (isIncognito) {
+            focusedColor = mContext.getColor(R.color.default_bg_color_dark_elev_2_baseline);
+            unfocusedColor = mContext.getColor(R.color.default_bg_color_dark_elev_1_baseline);
+        }
+
+        // Initially use the default tab strip background.
+        assertEquals(
+                "Initial strip background color is incorrect.",
+                focusedColor,
+                mStripLayoutHelperManager.getBackgroundColor());
+        // Assume the current activity lost focus.
+        mStripLayoutHelperManager.onTopResumedActivityChanged(false);
+        assertEquals(
+                "Strip background color should be updated when activity focus state changes to"
+                        + " false.",
+                unfocusedColor,
+                mStripLayoutHelperManager.getBackgroundColor());
+        // Assume the current activity gained focus.
+        mStripLayoutHelperManager.onTopResumedActivityChanged(true);
+        assertEquals(
+                "Strip background color should be updated when activity focus state changes to"
+                        + " true.",
+                focusedColor,
+                mStripLayoutHelperManager.getBackgroundColor());
     }
 
     @Test
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn
index f8116214..be528e1 100644
--- a/chrome/app/vector_icons/BUILD.gn
+++ b/chrome/app/vector_icons/BUILD.gn
@@ -161,6 +161,7 @@
     "palette.icon",
     "paste_menu.icon",
     "payments/save_card_and_vcn_success_confirmation.icon",
+    "payments/save_card_and_vcn_success_confirmation_dark.icon",
     "performance.icon",
     "person_filled_padded_large.icon",
     "person_filled_padded_small.icon",
diff --git a/chrome/app/vector_icons/payments/save_card_and_vcn_success_confirmation.icon b/chrome/app/vector_icons/payments/save_card_and_vcn_success_confirmation.icon
index aeb0a5b..b492619a 100644
--- a/chrome/app/vector_icons/payments/save_card_and_vcn_success_confirmation.icon
+++ b/chrome/app/vector_icons/payments/save_card_and_vcn_success_confirmation.icon
@@ -2,93 +2,95 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-CANVAS_DIMENSIONS, 104,
+CANVAS_DIMENSIONS, 103,
 PATH_COLOR_ARGB, 0xFF, 0x34, 0xA8, 0x53,
-MOVE_TO, 48.9f, 35.38f,
-R_CUBIC_TO, -12.15f, 0, -22.02f, 9.87f, -22.02f, 22.02f,
-R_CUBIC_TO, 0, 12.15f, 9.86f, 22.02f, 22.02f, 22.02f,
-R_CUBIC_TO, 12.15f, 0, 22.02f, -9.86f, 22.02f, -22.02f,
-R_CUBIC_TO, 0, -12.15f, -9.86f, -22.02f, -22.02f, -22.02f,
+MOVE_TO, 48.29f, 35.38f,
+CUBIC_TO, 36.13f, 35.38f, 26.27f, 45.24f, 26.27f, 57.4f,
+CUBIC_TO, 26.27f, 69.55f, 36.13f, 79.42f, 48.29f, 79.42f,
+CUBIC_TO, 60.44f, 79.42f, 70.3f, 69.55f, 70.3f, 57.4f,
+CUBIC_TO, 70.3f, 45.24f, 60.44f, 35.38f, 48.29f, 35.38f,
 CLOSE,
-R_MOVE_TO, -4.4f, 33.03f,
-LINE_TO, 35.69f, 59.6f,
-R_LINE_TO, 3.08f, -3.08f,
-R_LINE_TO, 5.73f, 5.72f,
-R_LINE_TO, 14.53f, -14.53f,
-R_LINE_TO, 3.08f, 3.08f,
-R_LINE_TO, -17.61f, 17.61f,
+MOVE_TO, 43.88f, 68.41f,
+LINE_TO, 35.08f, 59.6f,
+LINE_TO, 38.16f, 56.52f,
+LINE_TO, 43.88f, 62.24f,
+LINE_TO, 58.41f, 47.71f,
+LINE_TO, 61.5f, 50.79f,
+LINE_TO, 43.88f, 68.41f,
 CLOSE,
 NEW_PATH,
 PATH_COLOR_ARGB, 0xFF, 0x39, 0x82, 0xF8,
-MOVE_TO, 77.15f, 34.11f,
-R_CUBIC_TO, 2.01f, 0, 3.64f, -1.69f, 3.64f, -3.77f,
-R_CUBIC_TO, 0, -2.08f, -1.63f, -3.77f, -3.64f, -3.77f,
-R_CUBIC_TO, -2.01f, 0, -3.64f, 1.69f, -3.64f, 3.77f,
-R_CUBIC_TO, 0, 2.08f, 1.63f, 3.77f, 3.65f, 3.77f,
+MOVE_TO, 76.53f, 34.11f,
+CUBIC_TO, 78.54f, 34.11f, 80.18f, 32.42f, 80.18f, 30.33f,
+CUBIC_TO, 80.18f, 28.25f, 78.54f, 26.56f, 76.53f, 26.56f,
+CUBIC_TO, 74.52f, 26.56f, 72.89f, 28.25f, 72.89f, 30.33f,
+CUBIC_TO, 72.89f, 32.42f, 74.52f, 34.11f, 76.53f, 34.11f,
 CLOSE,
 NEW_PATH,
 PATH_COLOR_ARGB, 0xFF, 0xE8, 0xEA, 0xED,
-MOVE_TO, 4.26f, 70.92f,
-R_CUBIC_TO, 2.01f, 0, 3.64f, -1.69f, 3.64f, -3.77f,
-R_CUBIC_TO, 0, -2.08f, -1.63f, -3.77f, -3.64f, -3.77f,
-R_CUBIC_TO, -2.01f, 0, -3.64f, 1.69f, -3.64f, 3.77f,
-R_CUBIC_TO, 0, 2.09f, 1.63f, 3.78f, 3.65f, 3.78f,
+MOVE_TO, 3.64f, 70.92f,
+CUBIC_TO, 5.66f, 70.92f, 7.29f, 69.23f, 7.29f, 67.15f,
+CUBIC_TO, 7.29f, 65.06f, 5.66f, 63.37f, 3.64f, 63.37f,
+CUBIC_TO, 1.63f, 63.37f, 0, 65.06f, 0, 67.15f,
+CUBIC_TO, 0, 69.23f, 1.63f, 70.92f, 3.64f, 70.92f,
 CLOSE,
 NEW_PATH,
 PATH_COLOR_ARGB, 0xFF, 0x34, 0xA8, 0x53,
-MOVE_TO, 93.13f, 83.11f,
-R_CUBIC_TO, 1.43f, 0.46f, 2.22f, 2.04f, 1.78f, 3.52f,
-R_CUBIC_TO, -0.45f, 1.48f, -1.97f, 2.3f, -3.4f, 1.84f,
-R_LINE_TO, -5.17f, -1.68f,
-R_CUBIC_TO, -1.43f, -0.46f, -2.22f, -2.04f, -1.78f, -3.52f,
-R_CUBIC_TO, 0.45f, -1.48f, 1.97f, -2.3f, 3.4f, -1.84f,
-R_LINE_TO, 5.18f, 1.68f,
+MOVE_TO, 92.52f, 83.11f,
+CUBIC_TO, 93.95f, 83.58f, 94.74f, 85.15f, 94.29f, 86.63f,
+CUBIC_TO, 93.85f, 88.11f, 92.32f, 88.94f, 90.9f, 88.47f,
+LINE_TO, 85.72f, 86.79f,
+CUBIC_TO, 84.29f, 86.33f, 83.5f, 84.75f, 83.94f, 83.27f,
+CUBIC_TO, 84.39f, 81.79f, 85.91f, 80.97f, 87.34f, 81.43f,
+LINE_TO, 92.52f, 83.11f,
 CLOSE,
 NEW_PATH,
 PATH_COLOR_ARGB, 0xFF, 0xFB, 0xBC, 0x04,
-MOVE_TO, 11.02f, 27.22f,
-R_CUBIC_TO, -1.73f, -1.72f, -1.78f, -4.56f, -0.12f, -6.35f,
-R_ARC_TO, 4.23f, 4.23f, 0, 0, 1, 6.13f, -0.12f,
-R_LINE_TO, 6.25f, 6.23f,
-R_CUBIC_TO, 1.73f, 1.72f, 1.78f, 4.56f, 0.12f, 6.35f,
-R_ARC_TO, 4.23f, 4.23f, 0, 0, 1, -6.13f, 0.12f,
-R_LINE_TO, -6.25f, -6.23f,
+MOVE_TO, 10.4f, 27.22f,
+CUBIC_TO, 8.67f, 25.5f, 8.62f, 22.66f, 10.28f, 20.87f,
+CUBIC_TO, 11.94f, 19.08f, 14.68f, 19.03f, 16.41f, 20.75f,
+LINE_TO, 22.66f, 26.98f,
+CUBIC_TO, 24.38f, 28.7f, 24.44f, 31.54f, 22.78f, 33.33f,
+CUBIC_TO, 21.12f, 35.12f, 18.37f, 35.17f, 16.65f, 33.45f,
+LINE_TO, 10.4f, 27.22f,
 CLOSE,
 NEW_PATH,
 PATH_COLOR_ARGB, 0xFF, 0xEA, 0x43, 0x35,
-MOVE_TO, 25.45f, 87.96f,
-R_CUBIC_TO, 1.16f, -1.17f, 1.18f, -3.09f, 0.05f, -4.29f,
-R_ARC_TO, 2.86f, 2.86f, 0, 0, 0, -4.14f, -0.05f,
-R_LINE_TO, -4.19f, 4.23f,
-R_CUBIC_TO, -1.16f, 1.17f, -1.18f, 3.09f, -0.05f, 4.29f,
-R_ARC_TO, 2.86f, 2.86f, 0, 0, 0, 4.14f, 0.05f,
-R_LINE_TO, 4.19f, -4.23f,
+MOVE_TO, 24.84f, 87.96f,
+CUBIC_TO, 25.99f, 86.79f, 26.02f, 84.88f, 24.89f, 83.68f,
+CUBIC_TO, 23.76f, 82.48f, 21.91f, 82.45f, 20.75f, 83.62f,
+LINE_TO, 16.56f, 87.86f,
+CUBIC_TO, 15.4f, 89.02f, 15.37f, 90.94f, 16.5f, 92.14f,
+CUBIC_TO, 17.63f, 93.34f, 19.48f, 93.37f, 20.64f, 92.2f,
+LINE_TO, 24.84f, 87.96f,
 CLOSE,
 NEW_PATH,
 PATH_COLOR_ARGB, 0xFF, 0xFB, 0xBC, 0x04,
-MOVE_TO, 93.7f, 55.07f,
-R_CUBIC_TO, -1.77f, 0.93f, -3.93f, 0.2f, -4.83f, -1.63f,
-R_CUBIC_TO, -0.9f, -1.83f, -0.19f, -4.07f, 1.58f, -5,
-R_LINE_TO, 6.41f, -3.36f,
-R_CUBIC_TO, 1.77f, -0.93f, 3.93f, -0.2f, 4.83f, 1.64f,
-R_CUBIC_TO, 0.9f, 1.83f, 0.19f, 4.07f, -1.58f, 5,
-R_LINE_TO, -6.41f, 3.36f,
+MOVE_TO, 93.08f, 55.06f,
+CUBIC_TO, 91.31f, 55.99f, 89.15f, 55.26f, 88.25f, 53.43f,
+CUBIC_TO, 87.36f, 51.6f, 88.07f, 49.36f, 89.83f, 48.43f,
+LINE_TO, 96.24f, 45.07f,
+CUBIC_TO, 98.01f, 44.14f, 100.17f, 44.87f, 101.07f, 46.7f,
+CUBIC_TO, 101.97f, 48.53f, 101.26f, 50.77f, 99.49f, 51.7f,
+LINE_TO, 93.08f, 55.06f,
 CLOSE,
 NEW_PATH,
 PATH_COLOR_ARGB, 0xFF, 0xE8, 0xEA, 0xED,
-MOVE_TO, 49.67f, 6.42f,
-R_ARC_TO, 1, 1, 0, 0, 1, 1.5f, -0.87f,
-R_LINE_TO, 11, 6.3f,
-R_ARC_TO, 1, 1, 0, 0, 1, 0.01f, 1.73f,
-R_LINE_TO, -10.95f, 6.38f,
-R_ARC_TO, 1, 1, 0, 0, 1, -1.5f, -0.86f,
-R_LINE_TO, -0.05f, -12.68f,
+MOVE_TO, 49.06f, 6.42f,
+CUBIC_TO, 49.05f, 5.65f, 49.89f, 5.17f, 50.55f, 5.55f,
+LINE_TO, 61.56f, 11.85f,
+CUBIC_TO, 62.22f, 12.23f, 62.23f, 13.19f, 61.56f, 13.58f,
+LINE_TO, 50.61f, 19.96f,
+CUBIC_TO, 49.94f, 20.35f, 49.11f, 19.87f, 49.11f, 19.1f,
+LINE_TO, 49.06f, 6.42f,
 CLOSE,
-MOVE_TO, 64.84f, 94.97f,
-R_ARC_TO, 1, 1, 0, 0, 1, -1.5f, 0.87f,
-R_LINE_TO, -6.88f, -3.97f,
-R_ARC_TO, 1, 1, 0, 0, 1, 0, -1.73f,
-R_LINE_TO, 6.88f, -3.97f,
-R_ARC_TO, 1, 1, 0, 0, 1, 1.5f, 0.87f,
-R_V_LINE_TO, 7.95f,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xE8, 0xEA, 0xED,
+MOVE_TO, 64.23f, 94.97f,
+CUBIC_TO, 64.23f, 95.74f, 63.39f, 96.22f, 62.73f, 95.84f,
+LINE_TO, 55.84f, 91.86f,
+CUBIC_TO, 55.18f, 91.48f, 55.18f, 90.52f, 55.84f, 90.13f,
+LINE_TO, 62.73f, 86.16f,
+CUBIC_TO, 63.39f, 85.77f, 64.23f, 86.25f, 64.23f, 87.02f,
+LINE_TO, 64.23f, 94.97f,
 CLOSE
diff --git a/chrome/app/vector_icons/payments/save_card_and_vcn_success_confirmation_dark.icon b/chrome/app/vector_icons/payments/save_card_and_vcn_success_confirmation_dark.icon
new file mode 100644
index 0000000..1e68036d6
--- /dev/null
+++ b/chrome/app/vector_icons/payments/save_card_and_vcn_success_confirmation_dark.icon
@@ -0,0 +1,96 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 103,
+PATH_COLOR_ARGB, 0xFF, 0x81, 0xC9, 0x95,
+MOVE_TO, 48.29f, 35.38f,
+CUBIC_TO, 36.13f, 35.38f, 26.27f, 45.24f, 26.27f, 57.4f,
+CUBIC_TO, 26.27f, 69.55f, 36.13f, 79.42f, 48.29f, 79.42f,
+CUBIC_TO, 60.44f, 79.42f, 70.3f, 69.55f, 70.3f, 57.4f,
+CUBIC_TO, 70.3f, 45.24f, 60.44f, 35.38f, 48.29f, 35.38f,
+CLOSE,
+MOVE_TO, 43.88f, 68.41f,
+LINE_TO, 35.08f, 59.6f,
+LINE_TO, 38.16f, 56.52f,
+LINE_TO, 43.88f, 62.24f,
+LINE_TO, 58.41f, 47.71f,
+LINE_TO, 61.5f, 50.79f,
+LINE_TO, 43.88f, 68.41f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x8A, 0xB4, 0xF8,
+MOVE_TO, 76.53f, 34.11f,
+CUBIC_TO, 78.54f, 34.11f, 80.18f, 32.42f, 80.18f, 30.33f,
+CUBIC_TO, 80.18f, 28.25f, 78.54f, 26.56f, 76.53f, 26.56f,
+CUBIC_TO, 74.52f, 26.56f, 72.89f, 28.25f, 72.89f, 30.33f,
+CUBIC_TO, 72.89f, 32.42f, 74.52f, 34.11f, 76.53f, 34.11f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
+MOVE_TO, 3.64f, 70.92f,
+CUBIC_TO, 5.66f, 70.92f, 7.29f, 69.23f, 7.29f, 67.15f,
+CUBIC_TO, 7.29f, 65.06f, 5.66f, 63.37f, 3.64f, 63.37f,
+CUBIC_TO, 1.63f, 63.37f, 0, 65.06f, 0, 67.15f,
+CUBIC_TO, 0, 69.23f, 1.63f, 70.92f, 3.64f, 70.92f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x81, 0xC9, 0x95,
+MOVE_TO, 92.52f, 83.11f,
+CUBIC_TO, 93.95f, 83.58f, 94.74f, 85.15f, 94.29f, 86.63f,
+CUBIC_TO, 93.85f, 88.11f, 92.32f, 88.94f, 90.9f, 88.47f,
+LINE_TO, 85.72f, 86.79f,
+CUBIC_TO, 84.29f, 86.33f, 83.5f, 84.75f, 83.94f, 83.27f,
+CUBIC_TO, 84.39f, 81.79f, 85.91f, 80.97f, 87.34f, 81.43f,
+LINE_TO, 92.52f, 83.11f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xFD, 0xD6, 0x63,
+MOVE_TO, 10.4f, 27.22f,
+CUBIC_TO, 8.67f, 25.5f, 8.62f, 22.66f, 10.28f, 20.87f,
+CUBIC_TO, 11.94f, 19.08f, 14.68f, 19.03f, 16.41f, 20.75f,
+LINE_TO, 22.66f, 26.98f,
+CUBIC_TO, 24.38f, 28.7f, 24.44f, 31.54f, 22.78f, 33.33f,
+CUBIC_TO, 21.12f, 35.12f, 18.37f, 35.17f, 16.65f, 33.45f,
+LINE_TO, 10.4f, 27.22f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xF2, 0x8B, 0x82,
+MOVE_TO, 24.84f, 87.96f,
+CUBIC_TO, 25.99f, 86.79f, 26.02f, 84.88f, 24.89f, 83.68f,
+CUBIC_TO, 23.76f, 82.48f, 21.91f, 82.45f, 20.75f, 83.62f,
+LINE_TO, 16.56f, 87.86f,
+CUBIC_TO, 15.4f, 89.02f, 15.37f, 90.94f, 16.5f, 92.14f,
+CUBIC_TO, 17.63f, 93.34f, 19.48f, 93.37f, 20.64f, 92.2f,
+LINE_TO, 24.84f, 87.96f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xFD, 0xD6, 0x63,
+MOVE_TO, 93.08f, 55.06f,
+CUBIC_TO, 91.31f, 55.99f, 89.15f, 55.26f, 88.25f, 53.43f,
+CUBIC_TO, 87.36f, 51.6f, 88.07f, 49.36f, 89.83f, 48.43f,
+LINE_TO, 96.24f, 45.07f,
+CUBIC_TO, 98.01f, 44.14f, 100.17f, 44.87f, 101.07f, 46.7f,
+CUBIC_TO, 101.97f, 48.53f, 101.26f, 50.77f, 99.49f, 51.7f,
+LINE_TO, 93.08f, 55.06f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
+MOVE_TO, 49.06f, 6.42f,
+CUBIC_TO, 49.05f, 5.65f, 49.89f, 5.17f, 50.55f, 5.55f,
+LINE_TO, 61.56f, 11.85f,
+CUBIC_TO, 62.22f, 12.23f, 62.23f, 13.19f, 61.56f, 13.58f,
+LINE_TO, 50.61f, 19.96f,
+CUBIC_TO, 49.94f, 20.35f, 49.11f, 19.87f, 49.11f, 19.1f,
+LINE_TO, 49.06f, 6.42f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
+MOVE_TO, 64.23f, 94.97f,
+CUBIC_TO, 64.23f, 95.74f, 63.39f, 96.22f, 62.73f, 95.84f,
+LINE_TO, 55.84f, 91.86f,
+CUBIC_TO, 55.18f, 91.48f, 55.18f, 90.52f, 55.84f, 90.13f,
+LINE_TO, 62.73f, 86.16f,
+CUBIC_TO, 63.39f, 85.77f, 64.23f, 86.25f, 64.23f, 87.02f,
+LINE_TO, 64.23f, 94.97f,
+CLOSE
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 9b8a614e..8d84b51 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -5808,8 +5808,8 @@
       "policy/restricted_mgs_policy_provider.h",
       "policy/system_features_disable_list_policy_handler.cc",
       "policy/system_features_disable_list_policy_handler.h",
-      "renderer_context_menu/quick_answers_menu_observer.cc",
-      "renderer_context_menu/quick_answers_menu_observer.h",
+      "renderer_context_menu/read_write_card_observer.cc",
+      "renderer_context_menu/read_write_card_observer.h",
       "speech/tts_crosapi_util.cc",
       "speech/tts_crosapi_util.h",
       "usb/usb_pinned_notification.cc",
diff --git a/chrome/browser/android/lifecycle/BUILD.gn b/chrome/browser/android/lifecycle/BUILD.gn
index f13cce7..3370908f 100644
--- a/chrome/browser/android/lifecycle/BUILD.gn
+++ b/chrome/browser/android/lifecycle/BUILD.gn
@@ -20,6 +20,7 @@
     "java/src/org/chromium/chrome/browser/lifecycle/RecreateObserver.java",
     "java/src/org/chromium/chrome/browser/lifecycle/SaveInstanceStateObserver.java",
     "java/src/org/chromium/chrome/browser/lifecycle/StartStopWithNativeObserver.java",
+    "java/src/org/chromium/chrome/browser/lifecycle/TopResumedActivityChangedObserver.java",
     "java/src/org/chromium/chrome/browser/lifecycle/WindowFocusChangedObserver.java",
   ]
 }
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/TopResumedActivityChangedObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/TopResumedActivityChangedObserver.java
new file mode 100644
index 0000000..ce98d32
--- /dev/null
+++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/TopResumedActivityChangedObserver.java
@@ -0,0 +1,19 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.lifecycle;
+
+import android.app.Activity;
+
+/**
+ * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive
+ * onTopResumedActivityChanged events.
+ */
+public interface TopResumedActivityChangedObserver extends LifecycleObserver {
+    /**
+     * Called when an activity gets or loses the top resumed position in the system. See {@link
+     * Activity#onTopResumedActivityChanged(boolean)}.
+     */
+    void onTopResumedActivityChanged(boolean isTopResumedActivity);
+}
diff --git a/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.cc b/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.cc
index e47a270a..1aef969 100644
--- a/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.cc
@@ -30,8 +30,8 @@
   DCHECK(profile_);
   DCHECK(proto_);
 
-  proto_->RegisterOnRead(
-      base::BindOnce(&RemovedResultsRanker::OnRemovedResultsProtoReady,
+  on_init_subscription_ = proto_->RegisterOnInit(
+      base::BindOnce(&RemovedResultsRanker::OnRemovedResultsProtoInit,
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
@@ -77,8 +77,7 @@
   }
 }
 
-void RemovedResultsRanker::OnRemovedResultsProtoReady(
-    app_list::ReadStatus read_status) {
+void RemovedResultsRanker::OnRemovedResultsProtoInit() {
   // Record `proto_` size in KB.
   base::UmaHistogramMemoryKB("Apps.AppList.RemovedResultsProto.SizeInKB",
                              (*proto_)->ByteSizeLong() / 1000);
diff --git a/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.h b/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.h
index ab355535..4a0d55e5 100644
--- a/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.h
+++ b/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_REMOVED_RESULTS_RANKER_H_
 #define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_REMOVED_RESULTS_RANKER_H_
 
+#include "base/callback_list.h"
 #include "base/files/file_path.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
@@ -43,9 +44,8 @@
  private:
   friend class RemovedResultsRankerTest;
 
-  // Called when `proto_` finishes initialization. Note: `proto_` is initialized
-  // asyncly.
-  void OnRemovedResultsProtoReady(app_list::ReadStatus read_status);
+  // Called when `proto_` finishes init. Note: `proto_` is initialized asyncly.
+  void OnRemovedResultsProtoInit();
 
   ash::FileSuggestKeyedService* GetFileSuggestKeyedService();
 
@@ -61,6 +61,8 @@
   // should own a proto that contains only non-file result ids.
   const raw_ptr<PersistentProto<RemovedResultsProto>> proto_;
 
+  base::CallbackListSubscription on_init_subscription_;
+
   base::WeakPtrFactory<RemovedResultsRanker> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/ash/app_list/search/util/ftrl_optimizer.cc b/chrome/browser/ash/app_list/search/util/ftrl_optimizer.cc
index 64d04a2..2f43124 100644
--- a/chrome/browser/ash/app_list/search/util/ftrl_optimizer.cc
+++ b/chrome/browser/ash/app_list/search/util/ftrl_optimizer.cc
@@ -7,6 +7,7 @@
 #include <cmath>
 
 #include "base/files/file_path.h"
+#include "base/functional/bind.h"
 #include "base/numerics/safe_conversions.h"
 
 namespace app_list {
@@ -41,8 +42,10 @@
   DCHECK_LE(params.gamma, 1.0);
   DCHECK_GT(params.num_experts, 0u);
 
-  proto_.RegisterOnRead(
-      base::BindOnce(&FtrlOptimizer::OnProtoRead, weak_factory_.GetWeakPtr()));
+  // `proto_` is a class member so it is safe to call `RegisterOnInitUnsafe()`.
+  proto_.RegisterOnInitUnsafe(
+      base::BindOnce(&FtrlOptimizer::OnProtoInit, base::Unretained(this)));
+
   proto_.Init();
 }
 
@@ -132,7 +135,7 @@
   return static_cast<double>(rank) / last_expert_scores_.size();
 }
 
-void FtrlOptimizer::OnProtoRead(ReadStatus status) {
+void FtrlOptimizer::OnProtoInit() {
   if (!proto_->has_version() || proto_->version() != kVersion ||
       params_.num_experts !=
           base::checked_cast<size_t>(proto_->weights_size())) {
diff --git a/chrome/browser/ash/app_list/search/util/ftrl_optimizer.h b/chrome/browser/ash/app_list/search/util/ftrl_optimizer.h
index c87614f..7c9f12a 100644
--- a/chrome/browser/ash/app_list/search/util/ftrl_optimizer.h
+++ b/chrome/browser/ash/app_list/search/util/ftrl_optimizer.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "base/files/file_path.h"
-#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/app_list/search/util/ftrl_optimizer.pb.h"
 #include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
 
@@ -82,7 +81,7 @@
  private:
   double Loss(size_t expert, const std::string& item);
 
-  void OnProtoRead(ReadStatus status);
+  void OnProtoInit();
 
   Params params_;
 
@@ -92,8 +91,6 @@
   std::map<std::string, std::vector<double>> last_expert_scores_;
 
   PersistentProto<FtrlOptimizerProto> proto_;
-
-  base::WeakPtrFactory<FtrlOptimizer> weak_factory_{this};
 };
 
 }  // namespace app_list
diff --git a/chrome/browser/ash/app_list/search/util/mrfu_cache.cc b/chrome/browser/ash/app_list/search/util/mrfu_cache.cc
index 3b2006f8..e0e1d6b 100644
--- a/chrome/browser/ash/app_list/search/util/mrfu_cache.cc
+++ b/chrome/browser/ash/app_list/search/util/mrfu_cache.cc
@@ -7,6 +7,7 @@
 #include <cmath>
 
 #include "base/files/file_path.h"
+#include "base/functional/bind.h"
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/time/time.h"
@@ -74,8 +75,10 @@
 
 MrfuCache::MrfuCache(MrfuCache::Proto proto, const Params& params)
     : proto_(std::move(proto)) {
-  proto_.RegisterOnRead(
-      base::BindOnce(&MrfuCache::OnProtoRead, weak_factory_.GetWeakPtr()));
+  // `proto_` is a class member so it is safe to call `RegisterOnInitUnsafe()`.
+  proto_.RegisterOnInitUnsafe(
+      base::BindOnce(&MrfuCache::OnProtoInit, base::Unretained(this)));
+
   proto_.Init();
   // See header comment for explanation.
   decay_coeff_ = exp(log(0.5f) / params.half_life);
@@ -238,7 +241,7 @@
   proto_.QueueWrite();
 }
 
-void MrfuCache::OnProtoRead(ReadStatus status) {
+void MrfuCache::OnProtoInit() {
   if (!proto_->has_version() || proto_->version() != kVersion) {
     proto_.Purge();
   }
diff --git a/chrome/browser/ash/app_list/search/util/mrfu_cache.h b/chrome/browser/ash/app_list/search/util/mrfu_cache.h
index e10f80a0..18aba10 100644
--- a/chrome/browser/ash/app_list/search/util/mrfu_cache.h
+++ b/chrome/browser/ash/app_list/search/util/mrfu_cache.h
@@ -8,7 +8,6 @@
 #include <map>
 #include <string>
 
-#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/app_list/search/util/mrfu_cache.pb.h"
 #include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
 
@@ -143,7 +142,7 @@
 
   void Decay(Score* score);
   void MaybeCleanup();
-  void OnProtoRead(ReadStatus status);
+  void OnProtoInit();
 
   PersistentProto<MrfuCacheProto> proto_;
 
@@ -151,8 +150,6 @@
   float boost_coeff_;
   size_t max_items_;
   float min_score_;
-
-  base::WeakPtrFactory<MrfuCache> weak_factory_{this};
 };
 
 }  // namespace app_list
diff --git a/chrome/browser/ash/app_list/search/util/persistent_proto.cc b/chrome/browser/ash/app_list/search/util/persistent_proto.cc
new file mode 100644
index 0000000..d0340ba
--- /dev/null
+++ b/chrome/browser/ash/app_list/search/util/persistent_proto.cc
@@ -0,0 +1,25 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
+
+namespace app_list::internal {
+
+WriteStatus Write(const base::FilePath& filepath, std::string_view proto_str) {
+  if (const base::FilePath directory = filepath.DirName();
+      !base::DirectoryExists(directory)) {
+    base::CreateDirectory(directory);
+  }
+
+  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                base::BlockingType::MAY_BLOCK);
+  if (!base::ImportantFileWriter::WriteFileAtomically(
+          filepath, proto_str, "AppListPersistentProto")) {
+    return WriteStatus::kWriteError;
+  }
+
+  return WriteStatus::kOk;
+}
+
+}  // namespace app_list::internal
diff --git a/chrome/browser/ash/app_list/search/util/persistent_proto.h b/chrome/browser/ash/app_list/search/util/persistent_proto.h
index 8c2437f..d801c7a 100644
--- a/chrome/browser/ash/app_list/search/util/persistent_proto.h
+++ b/chrome/browser/ash/app_list/search/util/persistent_proto.h
@@ -5,9 +5,16 @@
 #ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_PERSISTENT_PROTO_H_
 #define CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_PERSISTENT_PROTO_H_
 
+#include <memory>
+#include <string>
+#include <string_view>
+#include <utility>
+
+#include "base/callback_list.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/important_file_writer.h"
+#include "base/functional/bind.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram_functions.h"
@@ -20,6 +27,10 @@
 
 namespace app_list {
 
+namespace internal {
+
+// Data types ------------------------------------------------------------------
+
 // The result of reading a backing file from disk. These values persist to logs.
 // Entries should not be renumbered and numeric values should never be reused.
 enum class ReadStatus {
@@ -42,7 +53,7 @@
   kMaxValue = kSerializationError,
 };
 
-namespace {
+// Helpers ---------------------------------------------------------------------
 
 template <class T>
 std::pair<ReadStatus, std::unique_ptr<T>> Read(const base::FilePath& filepath) {
@@ -62,52 +73,40 @@
   return {ReadStatus::kOk, std::move(proto)};
 }
 
-WriteStatus Write(const base::FilePath& filepath,
-                  const std::string& proto_str) {
-  const auto directory = filepath.DirName();
-  if (!base::DirectoryExists(directory))
-    base::CreateDirectory(directory);
+// Writes `proto_str` to the file specified by `filepath`.
+WriteStatus Write(const base::FilePath& filepath, std::string_view proto_str);
 
-  bool write_result;
-  {
-    base::ScopedBlockingCall scoped_blocking_call(
-        FROM_HERE, base::BlockingType::MAY_BLOCK);
-    write_result = base::ImportantFileWriter::WriteFileAtomically(
-        filepath, proto_str, "AppListPersistentProto");
-  }
-
-  if (!write_result)
-    return WriteStatus::kWriteError;
-  return WriteStatus::kOk;
-}
-
-}  // namespace
+}  // namespace internal
 
 // PersistentProto wraps a proto class and persists it to disk. Usage summary:
-//  - Init is asynchronous, usage before |on_read| is called will crash.
-//  - pproto->Method() will call Method on the underlying proto.
-//  - Call QueueWrite() to write to disk.
+// 1. Init is asynchronous. Using the object before initialization is complete
+//     will result in a crash.
+// 2. pproto->Method() will call Method on the underlying proto.
+// 3. Call `QueueWrite()` to write to disk.
 //
-// Reading. The backing file is read asynchronously from disk once at
-// initialization, and the |on_read| callback is run once this is done. Until
-// |on_read| is called, has_value is false and get() will always return nullptr.
-// If no proto file exists on disk, or it is invalid, a blank proto is
-// constructed and immediately written to disk.
+// Reading. The backing file is loaded asynchronously during initialization.
+// Until initialization completed, `has_value()` will be false and `get()` will
+// return `nullptr`. Register an init callback to be notified of completion.
 //
 // Writing. Writes must be triggered manually. Two methods are available:
-//  - QueueWrite() delays writing to disk for |write_delay| time, in order to
+// 1. `QueueWrite()` delays writing to disk for `write_delay` time, in order to
 //    batch successive writes.
-//  - StartWrite() writes to disk as soon as the task scheduler allows.
-// The |on_write| callback is run each time a write has completed.
+// 2. `StartWrite()` writes to disk as soon as the task scheduler allows.
+// Registered write callbacks are executed whenever a write operation finishes.
 template <class T>
 class PersistentProto {
  public:
-  using ReadCallback = base::OnceCallback<void(ReadStatus)>;
-  using WriteCallback = base::RepeatingCallback<void(WriteStatus)>;
+  using InitCallback = base::OnceClosure;
+  using WriteCallback = base::RepeatingCallback<void(/*success=*/bool)>;
 
   PersistentProto(const base::FilePath& path, const base::TimeDelta write_delay)
       : path_(path),
         write_delay_(write_delay),
+        on_init_callbacks_(
+            std::make_unique<base::OnceCallbackList<InitCallback::RunType>>()),
+        on_write_callbacks_(
+            std::make_unique<
+                base::RepeatingCallbackList<WriteCallback::RunType>>()),
         task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
             {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
              base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {}
@@ -123,25 +122,33 @@
     initialized_ = other.initialized_;
     write_is_queued_ = false;
     purge_after_reading_ = other.purge_after_reading_;
-    read_callbacks_ = std::move(other.read_callbacks_);
-    write_callbacks_ = std::move(other.write_callbacks_);
+    on_init_callbacks_ = std::move(other.on_init_callbacks_);
+    on_write_callbacks_ = std::move(other.on_write_callbacks_);
     task_runner_ = std::move(other.task_runner_);
     proto_ = std::move(other.proto_);
   }
 
   void Init() {
     task_runner_->PostTaskAndReplyWithResult(
-        FROM_HERE, base::BindOnce(&Read<T>, path_),
+        FROM_HERE, base::BindOnce(&internal::Read<T>, path_),
         base::BindOnce(&PersistentProto<T>::OnReadComplete,
                        weak_factory_.GetWeakPtr()));
   }
 
-  void RegisterOnRead(ReadCallback on_read) {
-    read_callbacks_.push_back(std::move(on_read));
+  [[nodiscard]] base::CallbackListSubscription RegisterOnInit(
+      InitCallback on_init) {
+    return on_init_callbacks_->Add(std::move(on_init));
   }
 
-  void RegisterOnWrite(WriteCallback on_write) {
-    write_callbacks_.push_back(std::move(on_write));
+  // NOTE: The caller must ensure `on_init` to be valid when init completes.
+  void RegisterOnInitUnsafe(InitCallback on_init) {
+    on_init_callbacks_->AddUnsafe(std::move(on_init));
+  }
+
+  // NOTE: The caller must ensure `on_write` to be valid during the life cycle
+  // of `PersistentProto`.
+  void RegisterOnWriteUnsafe(WriteCallback on_write) {
+    on_write_callbacks_->AddUnsafe(std::move(on_write));
   }
 
   T* get() { return proto_.get(); }
@@ -167,7 +174,7 @@
 
   constexpr explicit operator bool() const { return has_value(); }
 
-  // Write the backing proto to disk after |save_delay_ms_| has elapsed.
+  // Write the backing proto to disk after `save_delay_ms_` has elapsed.
   void QueueWrite() {
     DCHECK(proto_);
     if (!proto_)
@@ -197,13 +204,13 @@
     // causing a crash.
     std::string proto_str;
     if (!proto_->SerializeToString(&proto_str))
-      OnWriteComplete(WriteStatus::kSerializationError);
+      OnWriteComplete(internal::WriteStatus::kSerializationError);
 
     // The SequentialTaskRunner ensures the writes won't trip over each other,
     // so we can schedule without checking whether another write is currently
     // active.
     task_runner_->PostTaskAndReplyWithResult(
-        FROM_HERE, base::BindOnce(&Write, path_, proto_str),
+        FROM_HERE, base::BindOnce(&internal::Write, path_, proto_str),
         base::BindOnce(&PersistentProto<T>::OnWriteComplete,
                        weak_factory_.GetWeakPtr()));
   }
@@ -212,7 +219,7 @@
   // the proto, because it ensures the proto is purged even if called before the
   // backing file is read from disk. In this case, the file is overwritten after
   // it has been read. In either case, the file is written as soon as possible,
-  // skipping the |save_delay_ms_| wait time.
+  // skipping the `save_delay_ms_` wait time.
   void Purge() {
     if (proto_) {
       proto_.reset();
@@ -224,10 +231,13 @@
   }
 
  private:
-  void OnReadComplete(std::pair<ReadStatus, std::unique_ptr<T>> result) {
+  void OnReadComplete(
+      std::pair<internal::ReadStatus, std::unique_ptr<T>> result) {
+    const internal::ReadStatus status = result.first;
     base::UmaHistogramEnumeration("Apps.AppList.PersistentProto.ReadStatus",
-                                  result.first);
-    if (result.first == ReadStatus::kOk) {
+                                  status);
+
+    if (status == internal::ReadStatus::kOk) {
       proto_ = std::move(result.second);
     } else {
       proto_ = std::make_unique<T>();
@@ -242,23 +252,19 @@
     }
 
     initialized_ = true;
-    for (auto& cb : read_callbacks_) {
-      std::move(cb).Run(result.first);
-    }
-    read_callbacks_.clear();
+    on_init_callbacks_->Notify();
   }
 
-  void OnWriteComplete(const WriteStatus status) {
+  void OnWriteComplete(const internal::WriteStatus status) {
     base::UmaHistogramEnumeration("Apps.AppList.PersistentProto.WriteStatus",
                                   status);
-    for (auto& cb : write_callbacks_) {
-      cb.Run(status);
-    }
+    on_write_callbacks_->Notify(/*success=*/status ==
+                                internal::WriteStatus::kOk);
   }
 
   void OnQueueWrite() {
     // Reset the queued flag before posting the task. Last-moment updates to
-    // |proto_| will post another task to write the proto, avoiding race
+    // `proto_` will post another task to write the proto, avoiding race
     // conditions.
     write_is_queued_ = false;
     StartWrite();
@@ -270,8 +276,8 @@
   // How long to delay writing to disk for on a call to QueueWrite.
   base::TimeDelta write_delay_;
 
-  // Whether the proto has finished reading from disk. |proto_| will be empty
-  // before |initialized_| is true.
+  // Whether the proto has finished reading from disk. `proto_` will be empty
+  // before `initialized_` is true.
   bool initialized_ = false;
 
   // Whether or not a write is currently scheduled.
@@ -280,11 +286,13 @@
   // Whether we should immediately clear the proto after reading it.
   bool purge_after_reading_ = false;
 
-  // Run when the cache finishes reading from disk.
-  std::vector<ReadCallback> read_callbacks_;
+  // Run when `proto_` finishes initialization.
+  std::unique_ptr<base::OnceCallbackList<InitCallback::RunType>>
+      on_init_callbacks_;
 
   // Run when the cache finishes writing to disk.
-  std::vector<WriteCallback> write_callbacks_;
+  std::unique_ptr<base::RepeatingCallbackList<WriteCallback::RunType>>
+      on_write_callbacks_;
 
   // The proto itself.
   std::unique_ptr<T> proto_;
diff --git a/chrome/browser/ash/app_list/search/util/persistent_proto_unittest.cc b/chrome/browser/ash/app_list/search/util/persistent_proto_unittest.cc
index 420ef42..5df86769 100644
--- a/chrome/browser/ash/app_list/search/util/persistent_proto_unittest.cc
+++ b/chrome/browser/ash/app_list/search/util/persistent_proto_unittest.cc
@@ -4,12 +4,12 @@
 
 #include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
 
-#include <memory>
 #include <string>
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/app_list/search/util/persistent_proto_test.pb.h"
@@ -67,21 +67,18 @@
     ASSERT_TRUE(base::WriteFile(GetPath(), proto.SerializeAsString()));
   }
 
-  void OnRead(const ReadStatus status) {
-    read_status_ = status;
-    ++read_count_;
+  void OnInit() { ++read_count_; }
+
+  base::OnceClosure GetInitCallback() {
+    return base::BindOnce(&PersistentProtoTest::OnInit, base::Unretained(this));
   }
 
-  base::OnceCallback<void(ReadStatus)> ReadCallback() {
-    return base::BindOnce(&PersistentProtoTest::OnRead, base::Unretained(this));
-  }
-
-  void OnWrite(const WriteStatus status) {
-    ASSERT_EQ(status, WriteStatus::kOk);
+  void OnWrite(bool success) {
+    ASSERT_TRUE(success);
     ++write_count_;
   }
 
-  base::RepeatingCallback<void(WriteStatus)> WriteCallback() {
+  base::RepeatingCallback<void(bool)> GetWriteCallback() {
     return base::BindRepeating(&PersistentProtoTest::OnWrite,
                                base::Unretained(this));
   }
@@ -89,7 +86,6 @@
   void Wait() { task_environment_.RunUntilIdle(); }
 
   // Records the information passed to the callbacks for later expectation.
-  ReadStatus read_status_;
   int read_count_ = 0;
   int write_count_ = 0;
 
@@ -99,12 +95,12 @@
   base::ScopedTempDir temp_dir_;
 };
 
-// Test that the underlying proto is nullptr until a read is complete, and isn't
-// after that.
+// Test that the underlying proto is nullptr until proto initialization
+// completes, and isn't after that.
 TEST_F(PersistentProtoTest, Initialization) {
   PersistentProto<TestProto> pproto(GetPath(), WriteDelay());
-  pproto.RegisterOnRead(ReadCallback());
-  pproto.RegisterOnWrite(WriteCallback());
+  pproto.RegisterOnInitUnsafe(GetInitCallback());
+  pproto.RegisterOnWriteUnsafe(GetWriteCallback());
   pproto.Init();
   EXPECT_EQ(pproto.get(), nullptr);
   Wait();
@@ -114,8 +110,8 @@
 // Test bool conversion and has_value.
 TEST_F(PersistentProtoTest, BoolTests) {
   PersistentProto<TestProto> pproto(GetPath(), WriteDelay());
-  pproto.RegisterOnRead(ReadCallback());
-  pproto.RegisterOnWrite(WriteCallback());
+  pproto.RegisterOnInitUnsafe(GetInitCallback());
+  pproto.RegisterOnWriteUnsafe(GetWriteCallback());
   pproto.Init();
   EXPECT_EQ(pproto.get(), nullptr);
   EXPECT_FALSE(pproto);
@@ -129,8 +125,8 @@
 // Test -> and *.
 TEST_F(PersistentProtoTest, Getters) {
   PersistentProto<TestProto> pproto(GetPath(), WriteDelay());
-  pproto.RegisterOnRead(ReadCallback());
-  pproto.RegisterOnWrite(WriteCallback());
+  pproto.RegisterOnInitUnsafe(GetInitCallback());
+  pproto.RegisterOnWriteUnsafe(GetWriteCallback());
   pproto.Init();
   Wait();
   // We're really just checking these don't crash.
@@ -143,15 +139,19 @@
 
 // Test that the pproto correctly saves the in-memory proto to disk.
 TEST_F(PersistentProtoTest, Read) {
+  // Build a `PersistentProto` whose underlying file does not exist before init.
   PersistentProto<TestProto> pproto(GetPath(), WriteDelay());
-  pproto.RegisterOnRead(ReadCallback());
-  pproto.RegisterOnWrite(WriteCallback());
+  pproto.RegisterOnInitUnsafe(GetInitCallback());
+  pproto.RegisterOnWriteUnsafe(GetWriteCallback());
   pproto.Init();
   // Underlying proto should be nullptr until read is complete.
   EXPECT_EQ(pproto.get(), nullptr);
 
+  base::HistogramTester histogram_tester;
   Wait();
-  EXPECT_EQ(read_status_, ReadStatus::kMissing);
+  histogram_tester.ExpectBucketCount("Apps.AppList.PersistentProto.ReadStatus",
+                                     internal::ReadStatus::kMissing,
+                                     /*expected_count=*/1);
   EXPECT_EQ(read_count_, 1);
   EXPECT_EQ(write_count_, 1);
 
@@ -168,12 +168,17 @@
 TEST_F(PersistentProtoTest, ReadInvalidProto) {
   ASSERT_TRUE(base::WriteFile(GetPath(), "this isn't a valid proto"));
 
+  // Build a `PersistentProto` with an invalid proto file.
   PersistentProto<TestProto> pproto(GetPath(), WriteDelay());
-  pproto.RegisterOnRead(ReadCallback());
-  pproto.RegisterOnWrite(WriteCallback());
+
+  pproto.RegisterOnInitUnsafe(GetInitCallback());
+  pproto.RegisterOnWriteUnsafe(GetWriteCallback());
   pproto.Init();
+  base::HistogramTester histogram_tester;
   Wait();
-  EXPECT_EQ(read_status_, ReadStatus::kParseError);
+  histogram_tester.ExpectBucketCount("Apps.AppList.PersistentProto.ReadStatus",
+                                     internal::ReadStatus::kParseError,
+                                     /*expected_count=*/1);
   EXPECT_EQ(read_count_, 1);
   EXPECT_EQ(write_count_, 1);
 }
@@ -184,13 +189,16 @@
   WriteToDisk(test_proto);
 
   PersistentProto<TestProto> pproto(GetPath(), WriteDelay());
-  pproto.RegisterOnRead(ReadCallback());
-  pproto.RegisterOnWrite(WriteCallback());
+  pproto.RegisterOnInitUnsafe(GetInitCallback());
+  pproto.RegisterOnWriteUnsafe(GetWriteCallback());
   pproto.Init();
   EXPECT_EQ(pproto.get(), nullptr);
 
+  base::HistogramTester histogram_tester;
   Wait();
-  EXPECT_EQ(read_status_, ReadStatus::kOk);
+  histogram_tester.ExpectBucketCount("Apps.AppList.PersistentProto.ReadStatus",
+                                     internal::ReadStatus::kOk,
+                                     /*expected_count=*/1);
   EXPECT_EQ(read_count_, 1);
   EXPECT_EQ(write_count_, 0);
   EXPECT_NE(pproto.get(), nullptr);
@@ -200,8 +208,8 @@
 // Test that several saves all happen correctly.
 TEST_F(PersistentProtoTest, MultipleWrites) {
   PersistentProto<TestProto> pproto(GetPath(), WriteDelay());
-  pproto.RegisterOnRead(ReadCallback());
-  pproto.RegisterOnWrite(WriteCallback());
+  pproto.RegisterOnInitUnsafe(GetInitCallback());
+  pproto.RegisterOnWriteUnsafe(GetWriteCallback());
   pproto.Init();
   EXPECT_EQ(pproto.get(), nullptr);
 
@@ -223,8 +231,8 @@
 // write.
 TEST_F(PersistentProtoTest, QueueWrites) {
   PersistentProto<TestProto> pproto(GetPath(), WriteDelay());
-  pproto.RegisterOnRead(ReadCallback());
-  pproto.RegisterOnWrite(WriteCallback());
+  pproto.RegisterOnInitUnsafe(GetInitCallback());
+  pproto.RegisterOnWriteUnsafe(GetWriteCallback());
   pproto.Init();
   Wait();
   EXPECT_EQ(write_count_, 1);
diff --git a/chrome/browser/ash/app_list/search/util/score_normalizer.cc b/chrome/browser/ash/app_list/search/util/score_normalizer.cc
index 92d0a0e..1920aa4 100644
--- a/chrome/browser/ash/app_list/search/util/score_normalizer.cc
+++ b/chrome/browser/ash/app_list/search/util/score_normalizer.cc
@@ -8,6 +8,7 @@
 #include <cmath>
 #include <limits>
 
+#include "base/functional/bind.h"
 #include "base/logging.h"
 
 namespace app_list {
@@ -61,8 +62,10 @@
 ScoreNormalizer::ScoreNormalizer(ScoreNormalizer::Proto proto,
                                  const Params& params)
     : proto_(std::move(proto)), params_(params) {
-  proto_.RegisterOnRead(base::BindOnce(&ScoreNormalizer::OnProtoRead,
-                                       weak_factory_.GetWeakPtr()));
+  // `proto_` is a class member so it is safe to call `RegisterOnInitUnsafe()`.
+  proto_.RegisterOnInitUnsafe(
+      base::BindOnce(&ScoreNormalizer::OnProtoInit, base::Unretained(this)));
+
   proto_.Init();
 }
 
@@ -244,7 +247,7 @@
   proto_.QueueWrite();
 }
 
-void ScoreNormalizer::OnProtoRead(ReadStatus status) {
+void ScoreNormalizer::OnProtoInit() {
   DCHECK(proto_.initialized());
 
   if ((proto_->has_model_version() &&
diff --git a/chrome/browser/ash/app_list/search/util/score_normalizer.h b/chrome/browser/ash/app_list/search/util/score_normalizer.h
index f6025358..bd9f84c 100644
--- a/chrome/browser/ash/app_list/search/util/score_normalizer.h
+++ b/chrome/browser/ash/app_list/search/util/score_normalizer.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_SCORE_NORMALIZER_H_
 #define CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_SCORE_NORMALIZER_H_
 
-#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
 #include "chrome/browser/ash/app_list/search/util/score_normalizer.pb.h"
 
@@ -56,12 +55,10 @@
  private:
   friend class test::ScoreNormalizerTest;
 
-  void OnProtoRead(ReadStatus status);
+  void OnProtoInit();
 
   PersistentProto<ScoreNormalizerProto> proto_;
   Params params_;
-
-  base::WeakPtrFactory<ScoreNormalizer> weak_factory_{this};
 };
 
 }  // namespace app_list
diff --git a/chrome/browser/ash/file_suggest/file_suggest_keyed_service.cc b/chrome/browser/ash/file_suggest/file_suggest_keyed_service.cc
index f90ba07..fb6c19f 100644
--- a/chrome/browser/ash/file_suggest/file_suggest_keyed_service.cc
+++ b/chrome/browser/ash/file_suggest/file_suggest_keyed_service.cc
@@ -6,6 +6,7 @@
 
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/app_list/app_list_types.h"
+#include "base/functional/bind.h"
 #include "chrome/browser/ash/file_manager/fileapi_util.h"
 #include "chrome/browser/ash/file_suggest/drive_file_suggestion_provider.h"
 #include "chrome/browser/ash/file_suggest/drive_recent_file_suggestion_provider.h"
@@ -25,9 +26,11 @@
     : profile_(profile), proto_(std::move(proto)) {
   DCHECK(profile_);
 
-  proto_.RegisterOnRead(
+  // `proto_` is a class member so it is safe to call `RegisterOnInitUnsafe()`.
+  proto_.RegisterOnInitUnsafe(
       base::BindOnce(&FileSuggestKeyedService::OnRemovedSuggestionProtoReady,
-                     weak_factory_.GetWeakPtr()));
+                     base::Unretained(this)));
+
   proto_.Init();
 
   if (features::IsLauncherContinueSectionWithRecentsEnabled() ||
@@ -189,8 +192,7 @@
   return proto_.initialized();
 }
 
-void FileSuggestKeyedService::OnRemovedSuggestionProtoReady(
-    app_list::ReadStatus read_status) {
+void FileSuggestKeyedService::OnRemovedSuggestionProtoReady() {
   OnSuggestionProviderUpdated(FileSuggestionType::kDriveFile);
 
   if (local_file_suggestion_provider_->IsInitialized()) {
diff --git a/chrome/browser/ash/file_suggest/file_suggest_keyed_service.h b/chrome/browser/ash/file_suggest/file_suggest_keyed_service.h
index 2e42ba16..f26c0a6 100644
--- a/chrome/browser/ash/file_suggest/file_suggest_keyed_service.h
+++ b/chrome/browser/ash/file_suggest/file_suggest_keyed_service.h
@@ -117,7 +117,7 @@
 
  private:
   // Called when `proto_` is ready to read.
-  void OnRemovedSuggestionProtoReady(app_list::ReadStatus read_status);
+  void OnRemovedSuggestionProtoReady();
 
   // Removes the suggestions specified by type-id pairs.
   void RemoveSuggestionsByTypeIdPairs(
diff --git a/chrome/browser/ash/file_suggest/local_file_suggestion_provider.cc b/chrome/browser/ash/file_suggest/local_file_suggestion_provider.cc
index 892243c..64b4644a 100644
--- a/chrome/browser/ash/file_suggest/local_file_suggestion_provider.cc
+++ b/chrome/browser/ash/file_suggest/local_file_suggestion_provider.cc
@@ -99,9 +99,13 @@
         app_list::RankerStateDirectory(profile).AppendASCII(
             "zero_state_local_files.pb"),
         kSaveDelay);
-    proto.RegisterOnRead(
+
+    // `proto` is owned by `files_ranker_` which is a class member so it is safe
+    // to call `RegisterOnInitUnsafe()`.
+    proto.RegisterOnInitUnsafe(
         base::BindOnce(&LocalFileSuggestionProvider::OnProtoInitialized,
                        base::Unretained(this)));
+
     files_ranker_ =
         std::make_unique<app_list::MrfuCache>(std::move(proto), params);
   }
@@ -189,8 +193,7 @@
   }
 }
 
-void LocalFileSuggestionProvider::OnProtoInitialized(
-    app_list::ReadStatus status) {
+void LocalFileSuggestionProvider::OnProtoInitialized() {
   NotifySuggestionUpdate(FileSuggestionType::kLocalFile);
 }
 
diff --git a/chrome/browser/ash/file_suggest/local_file_suggestion_provider.h b/chrome/browser/ash/file_suggest/local_file_suggestion_provider.h
index cc9f116..717637b 100644
--- a/chrome/browser/ash/file_suggest/local_file_suggestion_provider.h
+++ b/chrome/browser/ash/file_suggest/local_file_suggestion_provider.h
@@ -55,7 +55,7 @@
 
 
  private:
-  void OnProtoInitialized(app_list::ReadStatus status);
+  void OnProtoInitialized();
   void OnValidationComplete(std::pair<std::vector<LocalFileData>,
                                       std::vector<base::FilePath>> results);
 
diff --git a/chrome/browser/autofill/autofill_across_iframes_browsertest.cc b/chrome/browser/autofill/autofill_across_iframes_browsertest.cc
index 3a04715..625740f 100644
--- a/chrome/browser/autofill/autofill_across_iframes_browsertest.cc
+++ b/chrome/browser/autofill/autofill_across_iframes_browsertest.cc
@@ -43,7 +43,6 @@
 #include "net/test/embedded_test_server/http_response.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/switches.h"
 
 using base::ASCIIToUTF16;
@@ -215,9 +214,6 @@
 // go/autofill-iframes-race-condition-explainer for some explanation.
 class AutofillAcrossIframesTest : public InProcessBrowserTest {
  public:
-  AutofillAcrossIframesTest()
-      : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
-
   void SetUpOnMainThread() override {
     InProcessBrowserTest::SetUpOnMainThread();
     // Prevent the Keychain from coming up on Mac.
@@ -227,8 +223,8 @@
     // Every hostname is handled by that server.
     host_resolver()->AddRule("*", "127.0.0.1");
     cert_verifier_.mock_cert_verifier()->set_default_result(net::OK);
-    https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
-    https_server_.RegisterRequestHandler(base::BindRepeating(
+    embedded_https_test_server().SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
+    embedded_https_test_server().RegisterRequestHandler(base::BindRepeating(
         [](const std::map<std::string, std::string>* pages,
            const net::test_server::HttpRequest& request)
             -> std::unique_ptr<net::test_server::HttpResponse> {
@@ -243,8 +239,8 @@
           return response;
         },
         base::Unretained(&pages_)));
-    ASSERT_TRUE(https_server_.InitializeAndListen());
-    https_server_.StartAcceptingConnections();
+    ASSERT_TRUE(embedded_https_test_server().InitializeAndListen());
+    embedded_https_test_server().StartAcceptingConnections();
   }
 
   void TearDownOnMainThread() override {
@@ -263,7 +259,7 @@
     command_line->AppendSwitch(blink::switches::kAllowPreCommitInput);
   }
 
-  // Registers the response `content_html` for a given `relative_path`, wth
+  // Registers the response `content_html` for a given `relative_path`, with
   // all placeholders $1, $2, ... in `content_html` replaced with the
   // corresponding hostname from `kHostnames`.
   // This response is served by for *every* hostname.
@@ -273,9 +269,9 @@
     std::vector<std::string> replacements;
     replacements.reserve(std::size(kHostnames));
     for (const char* hostname : kHostnames) {
-      replacements.push_back(std::string(
-          base::TrimString(https_server_.GetURL(hostname, "/").spec(), "/",
-                           base::TRIM_TRAILING)));
+      replacements.push_back(std::string(base::TrimString(
+          embedded_https_test_server().GetURL(hostname, "/").spec(), "/",
+          base::TRIM_TRAILING)));
     }
     pages_[std::move(relative_path)] =
         base::ReplaceStringPlaceholders(content_html, replacements, nullptr);
@@ -292,9 +288,10 @@
   // advance.
   const FormStructure* NavigateToUrl(base::StringPiece relative_url,
                                      size_t num_fields) {
-    NavigateParams params(browser(),
-                          https_server_.GetURL(kMainHostname, relative_url),
-                          ui::PAGE_TRANSITION_LINK);
+    NavigateParams params(
+        browser(),
+        embedded_https_test_server().GetURL(kMainHostname, relative_url),
+        ui::PAGE_TRANSITION_LINK);
     params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
     ui_test_utils::NavigateToURL(&params);
     return GetOrWaitForFormWithFocusableFields(
@@ -360,7 +357,6 @@
   test::AutofillBrowserTestEnvironment autofill_test_environment_;
   base::test::ScopedFeatureList feature_list_{
       features::kAutofillSharedAutofill};
-  net::EmbeddedTestServer https_server_;
   content::ContentMockCertVerifier cert_verifier_;
   // Maps relative paths to HTML content.
   std::map<std::string, std::string> pages_;
diff --git a/chrome/browser/autofill/autofill_server_browsertest.cc b/chrome/browser/autofill/autofill_server_browsertest.cc
index 9454d41..219ae08e 100644
--- a/chrome/browser/autofill/autofill_server_browsertest.cc
+++ b/chrome/browser/autofill/autofill_server_browsertest.cc
@@ -25,14 +25,17 @@
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/version_info/version_info.h"
+#include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_mock_cert_verifier.h"
 #include "content/public/test/test_utils.h"
 #include "content/public/test/url_loader_interceptor.h"
+#include "net/dns/mock_host_resolver.h"
 #include "services/network/test/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "url/third_party/mozilla/url_parse.h"
+#include "third_party/blink/public/common/switches.h"
 
 using testing::AllOf;
 using testing::Eq;
@@ -110,37 +113,78 @@
   std::unique_ptr<content::URLLoaderInterceptor> interceptor_;
 };
 
-}  // namespace
-
 class AutofillServerTest : public InProcessBrowserTest {
  public:
-  void SetUp() override {
-    // Enable data-url support.
-    // TODO(crbug.com/894428) - fix this suite to use the embedded test server
-    // instead of data urls.
+  AutofillServerTest() {
     scoped_feature_list_.InitWithFeatures(
         // Enabled.
-        {features::test::kAutofillAllowNonHttpActivation,
-         features::test::kAutofillServerCommunication,
+        {features::test::kAutofillServerCommunication,
          features::kAutofillEnableSupportForApartmentNumbers},
         // Disabled.
         {});
-
-    // Note that features MUST be enabled/disabled before continuing with
-    // SetUp(); otherwise, the feature state doesn't propagate to the test
-    // browser instance.
-    InProcessBrowserTest::SetUp();
   }
 
   void SetUpOnMainThread() override {
+    InProcessBrowserTest::SetUpOnMainThread();
+    // Prevent the Keychain from coming up on Mac.
+    test::DisableSystemServices(browser()->profile()->GetPrefs());
+
     // Wait for Personal Data Manager to be fully loaded as the events about
     // being loaded may throw off the tests and cause flakiness.
     WaitForPersonalDataManagerToBeLoaded(browser()->profile());
+
+    // Set up the HTTPS (!) server (embedded_test_server() is an HTTP server).
+    // Every hostname is handled by that server.
+    host_resolver()->AddRule("a.com", "127.0.0.1");
+    cert_verifier_.mock_cert_verifier()->set_default_result(net::OK);
+    embedded_https_test_server().SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
+    embedded_https_test_server().RegisterRequestHandler(base::BindRepeating(
+        [](const std::map<std::string, std::string>* pages,
+           const net::test_server::HttpRequest& request)
+            -> std::unique_ptr<net::test_server::HttpResponse> {
+          auto it = pages->find(request.GetURL().path());
+          if (it == pages->end()) {
+            return nullptr;
+          }
+          auto response =
+              std::make_unique<net::test_server::BasicHttpResponse>();
+          response->set_code(net::HTTP_OK);
+          response->set_content_type("text/html;charset=utf-8");
+          response->set_content(it->second);
+          return response;
+        },
+        base::Unretained(&pages_)));
+    ASSERT_TRUE(embedded_https_test_server().InitializeAndListen());
+    embedded_https_test_server().StartAcceptingConnections();
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    cert_verifier_.SetUpCommandLine(command_line);
+    // Slower test bots (ChromeOS, debug, etc.) are flaky due to slower loading
+    // interacting with deferred commits.
+    command_line->AppendSwitch(blink::switches::kAllowPreCommitInput);
+  }
+
+  void NavigateToUrl(base::StringPiece relative_url) {
+    NavigateParams params(
+        browser(), embedded_https_test_server().GetURL("a.com", relative_url),
+        ui::PAGE_TRANSITION_LINK);
+    params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
+    ui_test_utils::NavigateToURL(&params);
+  }
+
+  // Registers the response `content_html` for a given `relative_path`.
+  void SetUrlContent(std::string relative_path,
+                     base::StringPiece content_html) {
+    ASSERT_EQ(relative_path[0], '/');
+    pages_[std::move(relative_path)] = content_html;
   }
 
  private:
   test::AutofillBrowserTestEnvironment autofill_test_environment_;
   base::test::ScopedFeatureList scoped_feature_list_;
+  content::ContentMockCertVerifier cert_verifier_;
+  std::map<std::string, std::string> pages_;
 };
 
 MATCHER_P(EqualsUploadProto, expected_const, "") {
@@ -186,26 +230,26 @@
   personal_data_observer.Wait();
 
   // Load the test page. Expect a query request upon loading the page.
-  const char kDataURIPrefix[] = "data:text/html;charset=utf-8,";
-  const char kFormHtml[] =
-      "<form id='test_form' action='about:blank'>"
-      "  <input name='one'>"
-      "  <input name='two' autocomplete='off'>"
-      "  <input name='three'>"
-      "  <input name='four' autocomplete='off'>"
-      "  <input type='submit'>"
-      "</form>"
-      "<script>"
-      "  document.onclick = function() {"
-      "    document.getElementById('test_form').submit();"
-      "  };"
-      "</script>";
+  SetUrlContent("/test.html", R"(
+      <form id=test_form action=about:blank>
+        <input name=one>
+        <input name=two autocomplete=off>
+        <input name=three>
+        <input name=four autocomplete=off>
+        <input type=submit>
+      </form>
+      <script>
+        document.onclick = function() {
+          document.getElementById('test_form').submit();
+        };
+      </script>
+  )");
 
   AutofillPageQueryRequest query;
   query.set_client_version(std::string(GetProductNameAndVersionForUserAgent()));
   auto* query_form = query.add_forms();
-  query_form->set_signature(15916856893790176210U);
-  query_form->set_alternative_signature(1512434549531087U);
+  query_form->set_signature(16565345157617645697U);
+  query_form->set_alternative_signature(11880064796695671551U);
 
   query_form->add_fields()->set_signature(2594484045U);
   query_form->add_fields()->set_signature(2750915947U);
@@ -217,8 +261,7 @@
 
   WindowedNetworkObserver query_network_observer(expected_query_string);
 
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), GURL(std::string(kDataURIPrefix) + kFormHtml)));
+  NavigateToUrl("/test.html");
   query_network_observer.Wait();
 
   // Submit the form, using a simulated mouse click because form submissions not
@@ -229,7 +272,7 @@
   upload->set_submission(true);
   upload->set_client_version(
       std::string(GetProductNameAndVersionForUserAgent()));
-  upload->set_form_signature(15916856893790176210U);
+  upload->set_form_signature(16565345157617645697U);
   upload->set_autofill_used(false);
 
   // The `data_present` fields is a bit mask of field types that are associated
@@ -275,20 +318,20 @@
 // of user defined autocomplete types.
 IN_PROC_BROWSER_TEST_F(AutofillServerTest, AlwaysQueryForPasswordFields) {
   // Load the test page. Expect a query request upon loading the page.
-  const char kDataURIPrefix[] = "data:text/html;charset=utf-8,";
-  const char kFormHtml[] =
-      "<form id='test_form'>"
-      "  <input type='text' id='one' autocomplete='username'>"
-      "  <input type='text' id='two' autocomplete='off'>"
-      "  <input type='password' id='three'>"
-      "  <input type='submit'>"
-      "</form>";
+  SetUrlContent("/test.html", R"(
+      <form id=test_form>
+        <input type=text id=one autocomplete=username>
+        <input type=text id=two autocomplete=off>
+        <input type=password id=three>
+        <input type=submit>
+      </form>
+  )");
 
   AutofillPageQueryRequest query;
   query.set_client_version(std::string(GetProductNameAndVersionForUserAgent()));
   auto* query_form = query.add_forms();
-  query_form->set_signature(8900697631820480876U);
-  query_form->set_alternative_signature(8962829409320837774U);
+  query_form->set_signature(4875414400744072230U);
+  query_form->set_alternative_signature(130271417830211693U);
 
   query_form->add_fields()->set_signature(2594484045U);
   query_form->add_fields()->set_signature(2750915947U);
@@ -298,9 +341,9 @@
   ASSERT_TRUE(query.SerializeToString(&expected_query_string));
 
   WindowedNetworkObserver query_network_observer(expected_query_string);
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), GURL(std::string(kDataURIPrefix) + kFormHtml)));
+  NavigateToUrl("/test.html");
   query_network_observer.Wait();
 }
 
+}  // namespace
 }  // namespace autofill
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
index a26c98c..0d7f6d21 100644
--- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -122,6 +122,7 @@
 #include "net/dns/mock_host_resolver.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_status_code.h"
+#include "net/test/embedded_test_server/controllable_http_response.h"
 #include "net/test/embedded_test_server/default_handlers.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
@@ -6937,6 +6938,85 @@
   bfcache_render_frame_host_delete_observer->WaitUntilDeleted();
 }
 
+class DeclarativeNetRequestControllableResponseTest
+    : public DeclarativeNetRequestBrowserTest {
+ public:
+  DeclarativeNetRequestControllableResponseTest() = default;
+
+  void SetUpOnMainThread() override {
+    // The controllable response handler needs to be set up first before the
+    // test server can be started, which is why the SetUpOnMainThread from the
+    // super class which starts the test server is called afterwards here.
+    controllable_http_response_.emplace(embedded_test_server(),
+                                        "/pages_with_script/index.html");
+    DeclarativeNetRequestBrowserTest::SetUpOnMainThread();
+  }
+
+ protected:
+  net::test_server::ControllableHttpResponse& controllable_http_response() {
+    return *controllable_http_response_;
+  }
+
+ private:
+  std::optional<net::test_server::ControllableHttpResponse>
+      controllable_http_response_;
+};
+
+// Test that DNR actions from an extension are cleaned up when the extension is
+// disabled. This fixes a crash/bug where DNR actions such as modifyHeaders
+// which are created on the OnBeforeRequest phase when an extension was enabled
+// are supposed to take effect in a later request stage but the extension may no
+// longer be enabled at that point.
+// Regression for crbug.com/40072083 which would've caused a crash in this test.
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestControllableResponseTest,
+                       EraseActionsOnExtensionDisabled) {
+  // Create an extension with a rule that modifies response headers. This
+  // extension will match its rule during OnBeforeRequest but the rule would not
+  // be applied until OnHeadersReceived which is after when the request is sent
+  // and the response has started.
+  TestRule headers_rule = CreateModifyHeadersRule(
+      kMinValidID, kMinValidPriority, "google.com", std::nullopt,
+      std::vector<TestHeaderInfo>(
+          {TestHeaderInfo("resp-header", "append", "resp-value")}));
+  headers_rule.condition->resource_types =
+      std::vector<std::string>({"main_frame"});
+
+  ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(
+      {headers_rule}, "extension_1", {URLPattern::kAllUrlsPattern}));
+  const ExtensionId& extension_id = last_loaded_extension_id();
+
+  const GURL page_url = embedded_test_server()->GetURL(
+      "google.com", "/pages_with_script/index.html");
+
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), page_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+
+  controllable_http_response().WaitForRequest();
+
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  controllable_http_response().Send(net::HTTP_OK, "text/html",
+                                    "<html>Hello, World!</html>");
+
+  // Disable the extension after the response has been sent but before the
+  // request has finished.
+  DisableExtension(extension_id);
+
+  controllable_http_response().Done();
+
+  // Block until the web contents have been fully loaded to be certain that the
+  // web request event router finishes processing all events after the request
+  // has finished, such as OnHeadersReceived, and that the extension will be
+  // disabled at that point. The test should not crash at this point.
+  // TODO(crbug.com/40072083): Follow up with verifying the values of response
+  // headers. This may require initiating a request from a JS script injected
+  // into the page.
+  ASSERT_TRUE(content::WaitForLoadStop(web_contents));
+  EXPECT_FALSE(extension_service()->IsExtensionEnabled(extension_id));
+}
+
 INSTANTIATE_TEST_SUITE_P(All,
                          DeclarativeNetRequestBrowserTest,
                          ::testing::Values(ExtensionLoadType::PACKED,
@@ -6982,6 +7062,10 @@
                          ::testing::Values(ExtensionLoadType::PACKED,
                                            ExtensionLoadType::UNPACKED));
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         DeclarativeNetRequestControllableResponseTest,
+                         ::testing::Values(ExtensionLoadType::PACKED,
+                                           ExtensionLoadType::UNPACKED));
 }  // namespace
 }  // namespace declarative_net_request
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/printing/printing_test_utils.cc b/chrome/browser/extensions/api/printing/printing_test_utils.cc
index 266322c..2b43196 100644
--- a/chrome/browser/extensions/api/printing/printing_test_utils.cc
+++ b/chrome/browser/extensions/api/printing/printing_test_utils.cc
@@ -48,9 +48,19 @@
 
 constexpr int kHorizontalDpi = 300;
 constexpr int kVerticalDpi = 400;
-constexpr int kMediaSizeWidth = 210000;
-constexpr int kMediaSizeHeight = 297000;
-constexpr char kMediaSizeVendorId[] = "iso_a4_210x297mm";
+
+// Size of ISO A4 paper in microns.
+constexpr int kIsoA4Width = 210000;
+constexpr int kIsoA4Height = 297000;
+
+// Size of NA Letter paper in microns.
+constexpr int kNaLetterWidth = 215900;
+constexpr int kNaLetterHeight = 279400;
+
+// Size of a custom paper with variable height in microns.
+constexpr int kCustomPaperWidth = 200000;
+constexpr int kCustomPaperHeight = 250000;
+constexpr int kCustomPaperMaxHeight = 300000;
 
 // Mapping of the different extension types used in the test to the specific
 // manifest file names to create an extension of that type. The actual location
@@ -225,10 +235,18 @@
   capabilities->copies_max = 2;
   capabilities->default_dpi = {kHorizontalDpi, kVerticalDpi};
   capabilities->dpis.emplace_back(capabilities->default_dpi);
-  printing::PrinterSemanticCapsAndDefaults::Paper paper(
-      /*display_name=*/"", kMediaSizeVendorId,
-      {kMediaSizeWidth, kMediaSizeHeight});
-  capabilities->papers.push_back(std::move(paper));
+  printing::PrinterSemanticCapsAndDefaults::Paper iso_a4_paper(
+      /*display_name=*/"", /*vendor_id=*/"", {kIsoA4Width, kIsoA4Height});
+  printing::PrinterSemanticCapsAndDefaults::Paper na_letter_paper(
+      /*display_name=*/"", /*vendor_id=*/"", {kNaLetterWidth, kNaLetterHeight});
+  printing::PrinterSemanticCapsAndDefaults::Paper custom_paper(
+      /*display_name=*/"", /*vendor_id=*/"",
+      {kCustomPaperWidth, kCustomPaperHeight},
+      /*printable_area_um=*/{kCustomPaperWidth, kCustomPaperHeight},
+      /*max_height_um=*/kCustomPaperMaxHeight);
+  capabilities->default_paper = iso_a4_paper;
+  capabilities->papers = {std::move(iso_a4_paper), std::move(na_letter_paper),
+                          std::move(custom_paper)};
   capabilities->collate_capable = true;
   return capabilities;
 }
diff --git a/chrome/browser/extensions/events_apitest.cc b/chrome/browser/extensions/events_apitest.cc
index 4cad0c1..d73548b 100644
--- a/chrome/browser/extensions/events_apitest.cc
+++ b/chrome/browser/extensions/events_apitest.cc
@@ -36,6 +36,10 @@
 
 namespace extensions {
 
+namespace {
+
+using ContextType = ExtensionBrowserTest::ContextType;
+
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Events) {
   ASSERT_TRUE(RunExtensionTest("events")) << message_;
 }
@@ -614,44 +618,58 @@
   EXPECT_FALSE(observed_extension_names().count("chrome updates non listener"));
 }
 
-class EventPageEventDispatchingApiTest : public ExtensionApiTest {
+// TODO(crbug.com/41493334): Also test extensions with service workers and their
+// equivalent to ExtensionHost (EventAckData) for these scenarios:
+//   1. Dispatch to background context acks (duplicate of
+//     DispatchToBackgroundPage_Acks)
+//   2. Dispatch to content script doesn't ack (duplicate of
+//     DispatchToContentScript_DoesNotRecordMessageForAcking)
+//   2. Dispatch guest view event (EventRouter::DispatchEventToSender()) acks
+//     (similar to DispatchToPage_Acks)
+
+class EventDispatchingApiTest
+    : public ExtensionApiTest,
+      public testing::WithParamInterface<ContextType> {
  public:
-  EventPageEventDispatchingApiTest() = default;
+  EventDispatchingApiTest() = default;
 
-  EventPageEventDispatchingApiTest(const EventPageEventDispatchingApiTest&) =
-      delete;
-  EventPageEventDispatchingApiTest& operator=(
-      const EventPageEventDispatchingApiTest&) = delete;
-
-  void SetUpOnMainThread() override {
-    ExtensionApiTest::SetUpOnMainThread();
-    host_resolver()->AddRule("*", "127.0.0.1");
-    ASSERT_TRUE(StartEmbeddedTestServer());
-  }
-
-  content::WebContents* web_contents() {
-    return browser()->tab_strip_model()->GetActiveWebContents();
-  }
+  EventDispatchingApiTest(const EventDispatchingApiTest&) = delete;
+  EventDispatchingApiTest& operator=(const EventDispatchingApiTest&) = delete;
 };
 
-// Tests that an event page will receive an event message and properly track
-// and remove the unacked event message in ExtensionHost.
-IN_PROC_BROWSER_TEST_F(EventPageEventDispatchingApiTest,
-                       DispatchToEventPage_Acks) {
-  // Load an extension with a chrome.storage.onChanged listener.
+// Tests that background pages will receive an event message (routed through the
+// EventRouter::DispatchToProcess() flow) and properly track and remove the
+// unacked event message in ExtensionHost. Rather than send generate webRequest
+// events this uses storage events to use this flow.
+IN_PROC_BROWSER_TEST_P(EventDispatchingApiTest, DispatchToBackgroundPage_Acks) {
+  // Load either a persistent background page or a event page script.
+  static constexpr char kManifestPersistentBackgroundScript[] =
+      R"("persistent": true)";
+  static constexpr char kManifestEventPageBackgroundScript[] =
+      R"("persistent": false)";
+
+  // Load an extension with a chrome.storage.onChanged
+  // (EventRouter::DispatchToProcess()) listener and wait for the
+  // chrome.runtime.onInstalled listener to fire.
   static constexpr char kManifest[] =
       R"({
-           "name": "Event page",
-           "version": "0.1",
-           "manifest_version": 2,
-           "background": {
-             "scripts": ["background.js"],
-             "persistent": false
-            },
-           "permissions": ["storage"]
-         })";
+       "name": "Background page",
+       "version": "0.1",
+       "manifest_version": 2,
+       "background": {
+         "scripts": ["background.js"],
+         %s
+       },
+       "permissions": ["storage"]
+     })";
+  bool persistent_background_extension =
+      GetParam() == ContextType::kPersistentBackground;
+  const char* background_script = persistent_background_extension
+                                      ? kManifestPersistentBackgroundScript
+                                      : kManifestEventPageBackgroundScript;
+  std::string manifest = base::StringPrintf(kManifest, background_script);
   TestExtensionDir test_dir;
-  test_dir.WriteManifest(kManifest);
+  test_dir.WriteManifest(manifest);
   constexpr char kBackgroundJs[] =
       R"(
       chrome.runtime.onInstalled.addListener((details) => {
@@ -685,7 +703,7 @@
       process_manager->GetBackgroundHostForExtension(extension->id());
   ASSERT_EQ(extension_host->GetUnackedMessagesSizeForTesting(), 0UL);
 
-  // Set storage value which should fire chrome.storage.onChanged listeners.
+  // Set storage value which should fire chrome.storage.onChanged listener.
   ExtensionTestMessageListener extension_event_listener_fired("listener fired");
   static constexpr char kScript[] =
       R"(chrome.storage.local.set({"key" : "value"});)";
@@ -699,19 +717,47 @@
   EXPECT_EQ(extension_host->GetUnackedMessagesSizeForTesting(), 0UL);
 }
 
-// TODO(crbug.com/41493334): Refactor this test into the
-// DispatchToEventPage_Acks test since they are so similar.
-using PersistentBackgroundPageEventDispatchToSenderApiTest =
-    EventPageEventDispatchingApiTest;
+INSTANTIATE_TEST_SUITE_P(PersistentBackground,
+                         EventDispatchingApiTest,
+                         ::testing::Values(ContextType::kPersistentBackground));
+INSTANTIATE_TEST_SUITE_P(EventPage,
+                         EventDispatchingApiTest,
+                         ::testing::Values(ContextType::kEventPage));
+
+// This allows tests to perform web navigations that trigger webRequest API
+// events to be sent.
+class NavigatingEventDispatchingApiTest : public EventDispatchingApiTest {
+ public:
+  NavigatingEventDispatchingApiTest() = default;
+
+  NavigatingEventDispatchingApiTest(const NavigatingEventDispatchingApiTest&) =
+      delete;
+  NavigatingEventDispatchingApiTest& operator=(
+      const NavigatingEventDispatchingApiTest&) = delete;
+
+  void SetUpOnMainThread() override {
+    ExtensionApiTest::SetUpOnMainThread();
+    host_resolver()->AddRule("*", "127.0.0.1");
+    ASSERT_TRUE(StartEmbeddedTestServer());
+  }
+
+  content::WebContents* web_contents() {
+    return browser()->tab_strip_model()->GetActiveWebContents();
+  }
+};
+
+using PersistentBackgroundPageDispatchEventToSenderEventApiTest =
+    NavigatingEventDispatchingApiTest;
 
 // Tests that persistent background pages will receive an event message (routed
-// through the EventRouter::DispatchToSender() flow) and properly track and
+// through the EventRouter::DispatchEventToSender() flow) and properly track and
 // remove the unacked event message in ExtensionHost. Only persistent background
 // pages can use the webRequest API so event pages are not tested.
-IN_PROC_BROWSER_TEST_F(PersistentBackgroundPageEventDispatchToSenderApiTest,
-                       DispatchToPage_Acks) {
+IN_PROC_BROWSER_TEST_F(
+    PersistentBackgroundPageDispatchEventToSenderEventApiTest,
+    DispatchToPage_Acks) {
   // Load an extension with a chrome.webRequest.onBeforeRequest
-  // (EventRouter::DispatchToSender()) listener and wait for the
+  // (EventRouter::DispatchEventToSender()) listener and wait for the
   // chrome.runtime.onInstalled listener to fire.
   static constexpr char kManifest[] =
       R"({
@@ -776,20 +822,28 @@
   EXPECT_EQ(extension_host->GetUnackedMessagesSizeForTesting(), 0UL);
 }
 
-// Tests that an event targeted to a content script listener is not recorded
-// in unacked event messages in ExtensionHost.
-IN_PROC_BROWSER_TEST_F(EventPageEventDispatchingApiTest,
+// Tests that an event targeted to a content script listener is not recorded in
+// unacked event messages in ExtensionHost (for event pages and persistent
+// background pages). EventRouter::DispatchEventToSender() flow is not tested
+// since content scripts cannot listen to webRequest events.
+IN_PROC_BROWSER_TEST_P(NavigatingEventDispatchingApiTest,
                        DispatchToContentScript_DoesNotRecordMessageForAcking) {
+  // Load either a persistent background page or a event page script.
+  static constexpr char kManifestPersistentBackgroundScript[] =
+      R"("persistent": true)";
+  static constexpr char kManifestEventPageBackgroundScript[] =
+      R"("persistent": false)";
+
   // Load an extension with a content script that has the only
   // chrome.storage.onChanged listener.
   static constexpr char kManifest[] =
       R"({
-           "name": "Event page",
+           "name": "Background page",
            "version": "0.1",
            "manifest_version": 2,
            "background": {
              "scripts": ["background.js"],
-             "persistent": false
+             %s
             },
            "content_scripts": [{
              "matches": ["https://*/*", "http://*/*"],
@@ -797,8 +851,14 @@
            }],
            "permissions": ["storage"]
          })";
+  bool persistent_background_extension =
+      GetParam() == ContextType::kPersistentBackground;
+  const char* background_script = persistent_background_extension
+                                      ? kManifestPersistentBackgroundScript
+                                      : kManifestEventPageBackgroundScript;
+  std::string manifest = base::StringPrintf(kManifest, background_script);
   TestExtensionDir test_dir;
-  test_dir.WriteManifest(kManifest);
+  test_dir.WriteManifest(manifest);
   constexpr char kContentScriptJs[] =
       R"(
        chrome.storage.onChanged.addListener((details) => {
@@ -858,8 +918,16 @@
   // messages remain.
   EXPECT_TRUE(content_script_event_listener_fired.WaitUntilSatisfied());
   // TODO(crbug.com/1496093): Can we add an observer so that we know that an
-  // unacked message was not added to map at all?
+  // unacked message was not added to the map at all?
   EXPECT_EQ(extension_host->GetUnackedMessagesSizeForTesting(), 0UL);
 }
 
+INSTANTIATE_TEST_SUITE_P(PersistentBackground,
+                         NavigatingEventDispatchingApiTest,
+                         ::testing::Values(ContextType::kPersistentBackground));
+INSTANTIATE_TEST_SUITE_P(EventPage,
+                         NavigatingEventDispatchingApiTest,
+                         ::testing::Values(ContextType::kEventPage));
+
+}  // namespace
 }  // namespace extensions
diff --git a/chrome/browser/history_embeddings/OWNERS b/chrome/browser/history_embeddings/OWNERS
new file mode 100644
index 0000000..6310b61e
--- /dev/null
+++ b/chrome/browser/history_embeddings/OWNERS
@@ -0,0 +1 @@
+file://components/history_embeddings/OWNERS
diff --git a/chrome/browser/history_embeddings/history_embeddings_service_browsertest.cc b/chrome/browser/history_embeddings/history_embeddings_service_browsertest.cc
new file mode 100644
index 0000000..5d64df6
--- /dev/null
+++ b/chrome/browser/history_embeddings/history_embeddings_service_browsertest.cc
@@ -0,0 +1,51 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/history_embeddings/history_embeddings_service.h"
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/test/test_future.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/test/browser_test.h"
+
+namespace history_embeddings {
+
+class HistoryEmbeddingsBrowserTest : public InProcessBrowserTest {
+ public:
+  void SetUp() override {
+    CHECK(history_dir_.CreateUniqueTempDir());
+    InProcessBrowserTest::SetUp();
+  }
+
+ protected:
+  base::ScopedTempDir history_dir_;
+};
+
+IN_PROC_BROWSER_TEST_F(HistoryEmbeddingsBrowserTest, BrowserRetrievesPassages) {
+  auto service =
+      std::make_unique<HistoryEmbeddingsService>(history_dir_.GetPath());
+
+  ASSERT_TRUE(embedded_test_server()->Start());
+  auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), embedded_test_server()->GetURL("/inner_text/test1.html")));
+
+  base::test::TestFuture<UrlPassages> future;
+  service->RetrievePassages(*web_contents->GetPrimaryMainFrame(),
+                            future.GetCallback());
+
+  UrlPassages url_passages = future.Take();
+  ASSERT_EQ(url_passages.url.path(), "/inner_text/test1.html");
+
+  // Note: Currently the passage extraction algorithm does not recurse
+  // into iframes. If that changes then the passage structure and content
+  // here will need to change accordingly.
+  ASSERT_EQ(url_passages.passages.size(), 1u);
+  ASSERT_EQ(url_passages.passages[0], "A B C D");
+}
+
+}  // namespace history_embeddings
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index f86cda11..33e3b86 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -387,65 +387,40 @@
 // Content-Security-Policy, the embed tag is still sized correctly.
 // Regression test for https://crbug.com/271452.
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, CSPDoesNotBlockEmbedStyles) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   const GURL main_url(embedded_test_server()->GetURL("/pdf/test-csp.pdf"));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
-  ASSERT_TRUE(GetActiveWebContents());
+  content::RenderFrameHost* extension_host = LoadPdfGetExtensionHost(main_url);
+  ASSERT_TRUE(extension_host);
   auto* primary_main_frame = GetActiveWebContents()->GetPrimaryMainFrame();
-  ASSERT_TRUE(primary_main_frame);
-
-  // Verify the pdf has loaded.
-  auto* guest_view = GetGuestViewManager()->WaitForSingleGuestViewCreated();
-  ASSERT_TRUE(guest_view);
-  auto* guest_main_frame = guest_view->GetGuestMainFrame();
-  EXPECT_NE(primary_main_frame, guest_main_frame);
-  TestMimeHandlerViewGuest::WaitForGuestLoadStartThenStop(guest_view);
 
   // Verify the extension was loaded.
   const GURL extension_url(
       "chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html");
-  EXPECT_EQ(extension_url, guest_main_frame->GetLastCommittedURL());
+  EXPECT_EQ(extension_url, extension_host->GetLastCommittedURL());
   EXPECT_EQ(main_url, primary_main_frame->GetLastCommittedURL());
 
   // Verify that the plugin occupies all of the page area.
   const gfx::Rect embedder_rect =
       primary_main_frame->GetView()->GetViewBounds();
-  const gfx::Rect guest_rect = guest_main_frame->GetView()->GetViewBounds();
-  EXPECT_EQ(embedder_rect, guest_rect);
+  const gfx::Rect extension_rect = extension_host->GetView()->GetViewBounds();
+  EXPECT_EQ(embedder_rect, extension_rect);
 }
 
 // This test verifies that when a PDF is served with
 // Content-Security-Policy: sandbox, this is ignored and the PDF is displayed.
 // Regression test for https://crbug.com/1187122.
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, CSPWithSandboxDoesNotBlockPDF) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   const GURL main_url(
       embedded_test_server()->GetURL("/pdf/test-csp-sandbox.pdf"));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
-  ASSERT_TRUE(GetActiveWebContents());
-  auto* primary_main_frame = GetActiveWebContents()->GetPrimaryMainFrame();
-  ASSERT_TRUE(primary_main_frame);
-
-  // Verify the pdf has loaded.
-  auto* guest_view = GetGuestViewManager()->WaitForSingleGuestViewCreated();
-  ASSERT_TRUE(guest_view);
-  EXPECT_NE(primary_main_frame, guest_view->GetGuestMainFrame());
-  TestMimeHandlerViewGuest::WaitForGuestLoadStartThenStop(guest_view);
+  content::RenderFrameHost* extension_host = LoadPdfGetExtensionHost(main_url);
+  ASSERT_TRUE(extension_host);
 
   // Verify the extension was loaded.
   const GURL extension_url(
       "chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html");
-  EXPECT_EQ(extension_url,
-            guest_view->GetGuestMainFrame()->GetLastCommittedURL());
-  EXPECT_EQ(main_url, primary_main_frame->GetLastCommittedURL());
+  EXPECT_EQ(extension_url, extension_host->GetLastCommittedURL());
+  EXPECT_EQ(
+      main_url,
+      GetActiveWebContents()->GetPrimaryMainFrame()->GetLastCommittedURL());
 }
 
 // This test verifies that Content-Security-Policy's frame-ancestors 'none'
@@ -472,30 +447,35 @@
 // Regression test for https://crbug.com/1107535.
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest,
                        CSPFrameAncestorsOverridesXFrameOptions) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   const GURL main_url(
       embedded_test_server()->GetURL("/pdf/frame-test-csp-and-xfo.html"));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
-  ASSERT_TRUE(GetActiveWebContents());
-  auto* primary_main_frame = GetActiveWebContents()->GetPrimaryMainFrame();
-  ASSERT_TRUE(primary_main_frame);
 
-  // Verify the pdf has loaded.
-  auto* guest_view = GetGuestViewManager()->WaitForSingleGuestViewCreated();
-  ASSERT_TRUE(guest_view);
-  EXPECT_NE(primary_main_frame, guest_view->GetGuestMainFrame());
-  TestMimeHandlerViewGuest::WaitForGuestLoadStartThenStop(guest_view);
+  content::RenderFrameHost* extension_host;
+  if (UseOopif()) {
+    extension_host = LoadPdfInFirstChildGetExtensionHost(main_url);
+  } else {
+    // The URL uses an iframe element to embed the PDF, so
+    // `LoadPdfInFirstChild()` can't be used here.
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+
+    // Verify the pdf has loaded.
+    auto* guest_view = GetGuestViewManager()->WaitForSingleGuestViewCreated();
+    ASSERT_TRUE(guest_view);
+    TestMimeHandlerViewGuest::WaitForGuestLoadStartThenStop(guest_view);
+    extension_host = guest_view->GetGuestMainFrame();
+  }
+  ASSERT_TRUE(extension_host);
+
+  auto* primary_main_frame = GetActiveWebContents()->GetPrimaryMainFrame();
+  EXPECT_NE(primary_main_frame, extension_host);
 
   // Verify the extension was loaded.
   const GURL extension_url(
       "chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html");
-  EXPECT_EQ(extension_url,
-            guest_view->GetGuestMainFrame()->GetLastCommittedURL());
-  EXPECT_EQ(main_url, primary_main_frame->GetLastCommittedURL());
+  EXPECT_EQ(extension_url, extension_host->GetLastCommittedURL());
+  EXPECT_EQ(
+      main_url,
+      GetActiveWebContents()->GetPrimaryMainFrame()->GetLastCommittedURL());
 }
 
 class PDFExtensionLoadTest
@@ -829,11 +809,6 @@
 // load is handled by MimeHandlerView, and the plugin only gets the response.
 IN_PROC_BROWSER_TEST_P(PDFExtensionTestWithPartialLoading,
                        PartialRedirectsFailInPlugin) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   // Should match values used by `chrome_pdf::DocumentLoaderImpl`.
   constexpr size_t kDefaultRequestSize = 65536;
   constexpr size_t kChunkCloseDistance = 10;
@@ -1553,18 +1528,24 @@
 }
 
 IN_PROC_BROWSER_TEST_P(PDFExtensionIsolatedContentTest, PdfAndHtml) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   content::RenderProcessHost::SetMaxRendererProcessCount(1);
 
   // Load a page with an embedded PDF and an HTML iframe, both of the same
   // origin.
-  MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
+  const GURL main_url(
       embedded_test_server()->GetURL("/pdf/embed_pdf_and_html.html"));
-  ASSERT_TRUE(guest);
+
+  if (UseOopif()) {
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+
+    // The PDF embed is the second child of the HTML page.
+    content::RenderFrameHost* pdf_embed =
+        ChildFrameAt(GetActiveWebContents(), 1);
+    ASSERT_TRUE(GetTestPdfViewerStreamManager(GetActiveWebContents())
+                    ->WaitUntilPdfLoaded(pdf_embed));
+  } else {
+    ASSERT_TRUE(LoadPdf(main_url));
+  }
 
   // The PDF plugin frame and the iframe should not share renderer processes
   // even though they share origins.
@@ -1584,11 +1565,6 @@
 }
 
 IN_PROC_BROWSER_TEST_P(PDFExtensionIsolatedContentTest, DataNavigation) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   content::RenderFrameHost* extension_host =
       LoadPdfInFirstChildGetExtensionHost(
           embedded_test_server()->GetURL("/pdf/data_url_rectangles.html"));
@@ -1604,11 +1580,6 @@
 }
 
 IN_PROC_BROWSER_TEST_P(PDFExtensionIsolatedContentTest, HistoryNavigation) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   // Navigating to a PDF should spawn a PDF renderer process.
   EXPECT_TRUE(LoadPdf(embedded_test_server()->GetURL("/pdf/test.pdf")));
   EXPECT_EQ(CountPDFProcesses(), 1);
@@ -2699,11 +2670,6 @@
 // The plugin document and the mime handler should both use the same background
 // color.
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, BackgroundColor) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   // The background color for plugins is injected when the first response
   // is intercepted, at which point not all the plugins have loaded. This line
   // ensures that the PDF plugin has loaded and the right background color is
@@ -2723,11 +2689,6 @@
 }
 
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, DefaultFocusForEmbeddedPDF) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   content::RenderFrameHost* extension_host =
       LoadPdfInFirstChildGetExtensionHost(
           embedded_test_server()->GetURL("/pdf/pdf_embed.html"));
@@ -2743,11 +2704,6 @@
 }
 
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, DefaultFocusForNonEmbeddedPDF) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   content::RenderFrameHost* extension_host =
       LoadPdfGetExtensionHost(embedded_test_server()->GetURL("/pdf/test.pdf"));
   ASSERT_TRUE(extension_host);
diff --git a/chrome/browser/pdf/pdf_extension_test_base.h b/chrome/browser/pdf/pdf_extension_test_base.h
index 662cfcc3..6330fdc8 100644
--- a/chrome/browser/pdf/pdf_extension_test_base.h
+++ b/chrome/browser/pdf/pdf_extension_test_base.h
@@ -59,7 +59,8 @@
 
   // Same as `LoadPdf()` but loads URLs where the first child of the primary
   // main frame should be the embedder. This is a common case where an HTML page
-  // only embeds a single PDF.
+  // only embeds a single PDF. For GuestView PDF viewer, the embedder must be an
+  // embed element.
   testing::AssertionResult LoadPdfInFirstChild(const GURL& url);
 
   // Same as LoadPdf(), but also returns a pointer to the `MimeHandlerViewGuest`
diff --git a/chrome/browser/printing/web_api/web_printing_browsertest.cc b/chrome/browser/printing/web_api/web_printing_browsertest.cc
index 73d2f2e2..f0b20e97 100644
--- a/chrome/browser/printing/web_api/web_printing_browsertest.cc
+++ b/chrome/browser/printing/web_api/web_printing_browsertest.cc
@@ -21,6 +21,15 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features_generated.h"
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "base/test/mock_callback.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/printing/print_job.h"
+#include "chrome/browser/printing/print_job_manager.h"
+#include "printing/print_settings.h"
+#include "printing/printed_document.h"
+#endif
+
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "chrome/browser/printing/local_printer_utils_chromeos.h"
 #include "chrome/test/chromeos/printing/mock_local_printer_chromeos.h"
@@ -54,7 +63,21 @@
     const pdfBlob = new Blob([pdf], {type: 'application/pdf'});
     const printers = await navigator.printing.getPrinters();
 
-    const printJob = await printers[0].printJob("Title", { data: pdfBlob }, {});
+    const printJob = await printers[0].printJob("Title", { data: pdfBlob }, {
+      mediaCol: {
+        mediaSize: {
+          xDimension: 21000,
+          yDimension: 29700,
+        }
+      },
+      printColorMode: "color",
+      multipleDocumentHandling: "separate-documents-collated-copies",
+      printerResolution: {
+        crossFeedDirectionResolution: 300,
+        feedDirectionResolution: 400,
+        units: "dots-per-inch",
+      },
+    });
     const printJobComplete = new Promise((resolve, reject) => {
       printJob.onjobstatechange = () => {
         if (printJob.attributes().jobState === $1) {
@@ -70,6 +93,13 @@
 using testing::_;
 using testing::AtMost;
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+using testing::AllOf;
+using testing::Eq;
+using testing::Field;
+using testing::Property;
+#endif
+
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 using testing::DoAll;
 using testing::InSequence;
@@ -101,6 +131,26 @@
       (override));
 };
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+auto ValidatePrintSettings() {
+  // These are synced with the `kPrintScriptWithJobStatePlaceholder` script.
+  return AllOf(
+      // copies:
+      Property(&PrintSettings::copies, Eq(1)),
+      // mediaCol:
+      Property(&PrintSettings::requested_media,
+               Field(&PrintSettings::RequestedMedia::size_microns,
+                     Eq(gfx::Size(210000, 297000)))),
+      // printColorMode:
+      Property(&PrintSettings::color, Eq(mojom::ColorModel::kColorModeColor)),
+      Property(&PrintSettings::title, Eq(u"Title")),
+      // multipleDocumentHandling:
+      Property(&PrintSettings::collate, Eq(true)),
+      // printerResolution:
+      Property(&PrintSettings::dpi_size, Eq(gfx::Size(300, 400))));
+}
+#endif
+
 }  // namespace
 
 class WebPrintingBrowserTestBase
@@ -295,6 +345,35 @@
     },
     "documentFormatDefault": "application/pdf",
     "documentFormatSupported": [ "application/pdf" ],
+    "mediaColDefault": {
+      "mediaSize": {
+        "xDimension": 21000,
+        "yDimension": 29700,
+      },
+      "mediaSizeName": "iso_a4_210x297mm",
+    },
+    "mediaColDatabase": [{
+      "mediaSize": {
+        "xDimension": 21000,
+        "yDimension": 29700,
+      },
+      "mediaSizeName": "iso_a4_210x297mm",
+    }, {
+      "mediaSize": {
+        "xDimension": 21590,
+        "yDimension": 27940,
+      },
+      "mediaSizeName": "na_letter_8.5x11in",
+    }, {
+      "mediaSize": {
+        "xDimension": 20000,
+        "yDimension": {
+          "from": 25000,
+          "to": 30000,
+        },
+      },
+      "mediaSizeName": "om_200000x250000um_200x250mm",
+    }],
     "multipleDocumentHandlingDefault": "separate-documents-uncollated-copies",
     "multipleDocumentHandlingSupported": [
       "separate-documents-uncollated-copies",
@@ -339,6 +418,16 @@
 
 IN_PROC_BROWSER_TEST_F(WebPrintingBrowserTest, Print) {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+  // Set up a matcher to validate correctness of `PrintSettings`.
+  base::MockRepeatingCallback<void(PrintJob*, PrintedDocument*, int)>
+      doc_done_cb;
+  EXPECT_CALL(
+      doc_done_cb,
+      Run(_, Property(&PrintedDocument::settings, ValidatePrintSettings()), _));
+  auto subscription =
+      g_browser_process->print_job_manager()->AddDocDoneCallback(
+          doc_done_cb.Get());
+
   AddPrinterWithSemanticCaps(kId, kName,
                              extensions::ConstructPrinterCapabilities());
 #elif BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/printing/web_api/web_printing_mojom_traits.cc b/chrome/browser/printing/web_api/web_printing_mojom_traits.cc
index f493f66..3f8c1c00 100644
--- a/chrome/browser/printing/web_api/web_printing_mojom_traits.cc
+++ b/chrome/browser/printing/web_api/web_printing_mojom_traits.cc
@@ -9,6 +9,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "mojo/public/cpp/bindings/type_converter.h"
 #include "printing/mojom/print.mojom-shared.h"
+#include "printing/units.h"
 #include "third_party/blink/public/mojom/printing/web_printing.mojom.h"
 
 namespace mojo {
@@ -48,6 +49,27 @@
   }
 }
 
+bool InferRequestedMedia(
+    blink::mojom::WebPrintJobTemplateAttributesDataView data,
+    printing::PrintSettings& settings) {
+  blink::mojom::WebPrintingMediaCollectionRequestedDataView media_col;
+  data.GetMediaColDataView(&media_col);
+  if (media_col.is_null()) {
+    // media-col is an optional field.
+    return true;
+  }
+  gfx::Size media_size;
+  if (!media_col.ReadMediaSize(&media_size)) {
+    return false;
+  }
+  // The incoming size is specified in hundredths of millimeters (PWG units)
+  // whereas the printing subsystem operates on microns.
+  settings.set_requested_media(
+      {.size_microns = {media_size.width() * printing::kMicronsPerPwgUnit,
+                        media_size.height() * printing::kMicronsPerPwgUnit}});
+  return true;
+}
+
 }  // namespace
 
 // static
@@ -208,6 +230,9 @@
         break;
     }
   }
+  if (!InferRequestedMedia(data, *settings)) {
+    return false;
+  }
   if (auto mdh = data.multiple_document_handling()) {
     switch (*mdh) {
       case MultipleDocumentHandling::kSeparateDocumentsCollatedCopies:
diff --git a/chrome/browser/printing/web_api/web_printing_mojom_traits.h b/chrome/browser/printing/web_api/web_printing_mojom_traits.h
index 73e9ca6..d44f95c 100644
--- a/chrome/browser/printing/web_api/web_printing_mojom_traits.h
+++ b/chrome/browser/printing/web_api/web_printing_mojom_traits.h
@@ -68,6 +68,10 @@
   static uint32_t copies(const std::unique_ptr<printing::PrintSettings>& ptr) {
     NOTREACHED_NORETURN();
   }
+  static const blink::mojom::WebPrintingMediaCollectionRequestedPtr& media_col(
+      const std::unique_ptr<printing::PrintSettings>& ptr) {
+    NOTREACHED_NORETURN();
+  }
   static const std::optional<blink::mojom::WebPrintingMultipleDocumentHandling>&
   multiple_document_handling(
       const std::unique_ptr<printing::PrintSettings>& ptr) {
diff --git a/chrome/browser/printing/web_api/web_printing_service_chromeos.cc b/chrome/browser/printing/web_api/web_printing_service_chromeos.cc
index acec0c10..ec268e0 100644
--- a/chrome/browser/printing/web_api/web_printing_service_chromeos.cc
+++ b/chrome/browser/printing/web_api/web_printing_service_chromeos.cc
@@ -48,9 +48,41 @@
   return color_model != mojom::ColorModel::kUnknownColorModel;
 }
 
-bool ValidatePrintJobTemplateAttributesAgainstPrinterAttributes(
+bool ValidateMediaCol(
     const PrintSettings& pjt_attributes,
     const PrinterSemanticCapsAndDefaults& printer_attributes) {
+  // media-size / media-size-name:
+  const auto& media = pjt_attributes.requested_media();
+  if (media.IsDefault()) {
+    // Means nothing has actually been requested.
+    return true;
+  }
+  const auto& papers = printer_attributes.papers;
+  // Validate that the requested paper is supported by the printer.
+  if (!base::ranges::any_of(papers, [&](const auto& paper) {
+        return paper.IsSizeWithinBounds(media.size_microns);
+      })) {
+    return false;
+  }
+  return true;
+}
+
+void UpdatePrintJobTemplateAttributesWithPrinterDefaults(
+    PrintSettings& pjt_attributes,
+    const PrinterSemanticCapsAndDefaults& printer_attributes) {
+  if (!IsDuplexModeKnown(pjt_attributes.duplex_mode())) {
+    pjt_attributes.set_duplex_mode(printer_attributes.duplex_default);
+  }
+  if (!IsColorModelKnown(pjt_attributes.color())) {
+    pjt_attributes.set_color(printer_attributes.color_default
+                                 ? mojom::ColorModel::kColorModeColor
+                                 : mojom::ColorModel::kColorModeMonochrome);
+  }
+}
+
+bool ValidateAttributesAndUpdateIfNecessary(
+    PrintSettings& pjt_attributes,
+    const PrinterSemanticCapsAndDefaults& printer_attributes) {
   if (pjt_attributes.copies() < 1 ||
       pjt_attributes.copies() > printer_attributes.copies_max) {
     return false;
@@ -77,22 +109,15 @@
       !base::Contains(printer_attributes.dpis, pjt_attributes.dpi_size())) {
     return false;
   }
+  if (!ValidateMediaCol(pjt_attributes, printer_attributes)) {
+    return false;
+  }
+  // Update selected fields to printer defaults if they're not specified.
+  UpdatePrintJobTemplateAttributesWithPrinterDefaults(pjt_attributes,
+                                                      printer_attributes);
   return true;
 }
 
-void UpdatePrintJobTemplateAttributesWithPrinterDefaults(
-    PrintSettings* pjt_attributes,
-    const PrinterSemanticCapsAndDefaults& printer_attributes) {
-  if (!IsDuplexModeKnown(pjt_attributes->duplex_mode())) {
-    pjt_attributes->set_duplex_mode(printer_attributes.duplex_default);
-  }
-  if (!IsColorModelKnown(pjt_attributes->color())) {
-    pjt_attributes->set_color(printer_attributes.color_default
-                                  ? mojom::ColorModel::kColorModeColor
-                                  : mojom::ColorModel::kColorModeMonochrome);
-  }
-}
-
 blink::mojom::WebPrinterAttributesPtr MergePrinterAttributesAndStatus(
     blink::mojom::WebPrinterAttributesPtr printer_attributes,
     std::unique_ptr<PrinterStatus> printer_status) {
@@ -260,15 +285,12 @@
     return;
   }
 
-  if (!ValidatePrintJobTemplateAttributesAgainstPrinterAttributes(
-          *pjt_attributes, *printer_attributes)) {
+  if (!ValidateAttributesAndUpdateIfNecessary(*pjt_attributes,
+                                              *printer_attributes)) {
     std::move(callback).Run(blink::mojom::WebPrintResult::NewError(
         blink::mojom::WebPrintError::kPrintJobTemplateAttributesMismatch));
     return;
   }
-  // Update selected fields to printer defaults if they're not specified.
-  UpdatePrintJobTemplateAttributesWithPrinterDefaults(pjt_attributes.get(),
-                                                      *printer_attributes);
 
   pdf_flattener_->ReadAndFlattenPdf(
       std::move(document),
diff --git a/chrome/browser/printing/web_api/web_printing_type_converters.cc b/chrome/browser/printing/web_api/web_printing_type_converters.cc
index 7278ff1e..427b07a 100644
--- a/chrome/browser/printing/web_api/web_printing_type_converters.cc
+++ b/chrome/browser/printing/web_api/web_printing_type_converters.cc
@@ -7,10 +7,57 @@
 #include <optional>
 
 #include "base/containers/contains.h"
+#include "chrome/common/printing/print_media_l10n.h"
 #include "mojo/public/cpp/bindings/message.h"
 #include "printing/backend/print_backend.h"
+#include "printing/units.h"
 #include "third_party/blink/public/mojom/printing/web_printing.mojom.h"
 
+namespace {
+
+using MediaCollection = blink::mojom::WebPrintingMediaCollection;
+using MediaCollectionPtr = blink::mojom::WebPrintingMediaCollectionPtr;
+using Paper = printing::PrinterSemanticCapsAndDefaults::Paper;
+
+using MediaSize = blink::mojom::WebPrintingMediaSize;
+using MediaSizeDimension = blink::mojom::WebPrintingMediaSizeDimension;
+using Range = blink::mojom::WebPrintingRange;
+
+}  // namespace
+
+namespace mojo {
+
+template <>
+struct TypeConverter<MediaCollectionPtr, Paper> {
+  static MediaCollectionPtr Convert(const Paper& paper) {
+    // The printing subsystem operates on microns, whereas the spec-compliant
+    // `media_size` must be represented in hundredths of millimeters (PWG
+    // units).
+    auto media_size = MediaSize::New();
+    if (paper.SupportsCustomSize()) {
+      media_size->y_dimension = MediaSizeDimension::NewRange(
+          Range::New(paper.size_um().height() / printing::kMicronsPerPwgUnit,
+                     paper.max_height_um() / printing::kMicronsPerPwgUnit));
+    } else {
+      media_size->y_dimension = MediaSizeDimension::NewValue(
+          paper.size_um().height() / printing::kMicronsPerPwgUnit);
+    }
+    // `Paper` struct doesn't provide information about variable width
+    // (moreover, papers with variable width are silently discarded by
+    // ChromeOS). Hence `x_dimension` is always a single value.
+    media_size->x_dimension = MediaSizeDimension::NewValue(
+        paper.size_um().width() / printing::kMicronsPerPwgUnit);
+
+    auto media_col = MediaCollection::New();
+    media_col->media_size = std::move(media_size);
+    media_col->media_size_name =
+        printing::LocalizePaperDisplayName(paper.size_um()).vendor_id;
+    return media_col;
+  }
+};
+
+}  // namespace mojo
+
 namespace printing {
 namespace {
 
@@ -38,6 +85,14 @@
       blink::mojom::WebPrintingRange::New(1, caps.copies_max);
 }
 
+void ProcessMediaCollection(const PrinterSemanticCapsAndDefaults& caps,
+                            blink::mojom::WebPrinterAttributes* attributes) {
+  attributes->media_col_default =
+      mojo::ConvertTo<MediaCollectionPtr>(caps.default_paper);
+  attributes->media_col_database =
+      mojo::ConvertTo<std::vector<MediaCollectionPtr>>(caps.papers);
+}
+
 void ProcessMultipleDocumentHandling(
     const PrinterSemanticCapsAndDefaults& caps,
     blink::mojom::WebPrinterAttributes* attributes) {
@@ -122,6 +177,7 @@
   auto attributes = blink::mojom::WebPrinterAttributes::New();
 
   printing::ProcessCopies(capabilities, attributes.get());
+  printing::ProcessMediaCollection(capabilities, attributes.get());
   printing::ProcessMultipleDocumentHandling(capabilities, attributes.get());
   printing::ProcessOrientationRequested(capabilities, attributes.get());
   printing::ProcessPrinterResolution(capabilities, attributes.get());
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudIPHController.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudIPHController.java
index 15d6dc6..c1957b9 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudIPHController.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudIPHController.java
@@ -86,8 +86,8 @@
                 new IPHCommandBuilder(
                                 mToolbarMenuButton.getContext().getResources(),
                                 FeatureConstants.READ_ALOUD_APP_MENU_FEATURE,
-                                R.string.menu_listen_to_this_page,
-                                R.string.menu_listen_to_this_page)
+                                R.string.menu_listen_to_this_page_iph,
+                                R.string.menu_listen_to_this_page_iph)
                         .setAnchorView(mToolbarMenuButton)
                         .setOnShowCallback(() -> turnOnHighlightForMenuItem(R.id.readaloud_menu_id))
                         .setOnDismissCallback(this::turnOffHighlightForMenuItem)
diff --git a/chrome/browser/renderer_context_menu/quick_answers_menu_observer.cc b/chrome/browser/renderer_context_menu/read_write_card_observer.cc
similarity index 79%
rename from chrome/browser/renderer_context_menu/quick_answers_menu_observer.cc
rename to chrome/browser/renderer_context_menu/read_write_card_observer.cc
index 4089adc63..177e352 100644
--- a/chrome/browser/renderer_context_menu/quick_answers_menu_observer.cc
+++ b/chrome/browser/renderer_context_menu/read_write_card_observer.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/renderer_context_menu/quick_answers_menu_observer.h"
+#include "chrome/browser/renderer_context_menu/read_write_card_observer.h"
 
 #include <utility>
 #include <vector>
@@ -22,14 +22,13 @@
 
 }  // namespace
 
-QuickAnswersMenuObserver::QuickAnswersMenuObserver(
-    RenderViewContextMenuProxy* proxy,
-    Profile* profile)
+ReadWriteCardObserver::ReadWriteCardObserver(RenderViewContextMenuProxy* proxy,
+                                             Profile* profile)
     : proxy_(proxy), profile_(profile) {}
 
-QuickAnswersMenuObserver::~QuickAnswersMenuObserver() = default;
+ReadWriteCardObserver::~ReadWriteCardObserver() = default;
 
-void QuickAnswersMenuObserver::OnContextMenuShown(
+void ReadWriteCardObserver::OnContextMenuShown(
     const content::ContextMenuParams& params,
     const gfx::Rect& bounds_in_screen) {
   chromeos::ReadWriteCardsManager* cards_manager =
@@ -38,11 +37,11 @@
 
   cards_manager->FetchController(
       params, proxy_->GetBrowserContext(),
-      base::BindOnce(&QuickAnswersMenuObserver::OnFetchControllers,
+      base::BindOnce(&ReadWriteCardObserver::OnFetchControllers,
                      weak_factory_.GetWeakPtr(), params, bounds_in_screen));
 }
 
-void QuickAnswersMenuObserver::OnContextMenuViewBoundsChanged(
+void ReadWriteCardObserver::OnContextMenuViewBoundsChanged(
     const gfx::Rect& bounds_in_screen) {
   for (auto controller : read_write_card_controllers_) {
     if (!controller) {
@@ -55,7 +54,7 @@
   }
 }
 
-void QuickAnswersMenuObserver::OnMenuClosed() {
+void ReadWriteCardObserver::OnMenuClosed() {
   for (auto controller : read_write_card_controllers_) {
     if (!controller) {
       continue;
@@ -68,11 +67,11 @@
   is_other_command_executed_ = false;
 }
 
-void QuickAnswersMenuObserver::CommandWillBeExecuted(int command_id) {
+void ReadWriteCardObserver::CommandWillBeExecuted(int command_id) {
   is_other_command_executed_ = true;
 }
 
-void QuickAnswersMenuObserver::OnTextSurroundingSelectionAvailable(
+void ReadWriteCardObserver::OnTextSurroundingSelectionAvailable(
     const std::u16string& selected_text,
     const std::u16string& surrounding_text,
     uint32_t start_offset,
@@ -88,7 +87,7 @@
   }
 }
 
-void QuickAnswersMenuObserver::OnFetchControllers(
+void ReadWriteCardObserver::OnFetchControllers(
     const content::ContextMenuParams& params,
     const gfx::Rect& bounds_in_screen,
     std::vector<base::WeakPtr<chromeos::ReadWriteCardController>> controllers) {
@@ -116,7 +115,7 @@
   if (focused_frame) {
     focused_frame->RequestTextSurroundingSelection(
         base::BindOnce(
-            &QuickAnswersMenuObserver::OnTextSurroundingSelectionAvailable,
+            &ReadWriteCardObserver::OnTextSurroundingSelectionAvailable,
             weak_factory_.GetWeakPtr(), params.selection_text),
         kMaxSurroundingTextLength);
   }
diff --git a/chrome/browser/renderer_context_menu/quick_answers_menu_observer.h b/chrome/browser/renderer_context_menu/read_write_card_observer.h
similarity index 69%
rename from chrome/browser/renderer_context_menu/quick_answers_menu_observer.h
rename to chrome/browser/renderer_context_menu/read_write_card_observer.h
index f427b1ec..9d13b2c 100644
--- a/chrome/browser/renderer_context_menu/quick_answers_menu_observer.h
+++ b/chrome/browser/renderer_context_menu/read_write_card_observer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_RENDERER_CONTEXT_MENU_QUICK_ANSWERS_MENU_OBSERVER_H_
-#define CHROME_BROWSER_RENDERER_CONTEXT_MENU_QUICK_ANSWERS_MENU_OBSERVER_H_
+#ifndef CHROME_BROWSER_RENDERER_CONTEXT_MENU_READ_WRITE_CARD_OBSERVER_H_
+#define CHROME_BROWSER_RENDERER_CONTEXT_MENU_READ_WRITE_CARD_OBSERVER_H_
 
 #include <memory>
 #include <string>
@@ -21,14 +21,15 @@
 class ReadWriteCardController;
 }  // namespace chromeos
 
-// A class that implements the quick answers menu.
-class QuickAnswersMenuObserver : public RenderViewContextMenuObserver {
+// A class that observes context menu actions and notify all the associated
+// `ReadWriteCardController` about the events.
+class ReadWriteCardObserver : public RenderViewContextMenuObserver {
  public:
-  QuickAnswersMenuObserver(const QuickAnswersMenuObserver&) = delete;
-  QuickAnswersMenuObserver& operator=(const QuickAnswersMenuObserver&) = delete;
+  ReadWriteCardObserver(const ReadWriteCardObserver&) = delete;
+  ReadWriteCardObserver& operator=(const ReadWriteCardObserver&) = delete;
 
-  QuickAnswersMenuObserver(RenderViewContextMenuProxy* proxy, Profile* profile);
-  ~QuickAnswersMenuObserver() override;
+  ReadWriteCardObserver(RenderViewContextMenuProxy* proxy, Profile* profile);
+  ~ReadWriteCardObserver() override;
 
   // RenderViewContextMenuObserver implementation.
   void CommandWillBeExecuted(int command_id) override;
@@ -39,7 +40,7 @@
   void OnMenuClosed() override;
 
  private:
-  friend class QuickAnswersMenuObserverTest;
+  friend class ReadWriteCardObserverTest;
 
   void OnTextSurroundingSelectionAvailable(
       const std::u16string& selected_text,
@@ -67,7 +68,7 @@
   std::vector<raw_ptr<chromeos::ReadWriteCardController>>
       read_write_card_controllers_;
 
-  base::WeakPtrFactory<QuickAnswersMenuObserver> weak_factory_{this};
+  base::WeakPtrFactory<ReadWriteCardObserver> weak_factory_{this};
 };
 
-#endif  // CHROME_BROWSER_RENDERER_CONTEXT_MENU_QUICK_ANSWERS_MENU_OBSERVER_H_
+#endif  // CHROME_BROWSER_RENDERER_CONTEXT_MENU_READ_WRITE_CARD_OBSERVER_H_
diff --git a/chrome/browser/renderer_context_menu/quick_answers_menu_observer_unittest.cc b/chrome/browser/renderer_context_menu/read_write_card_observer_unittest.cc
similarity index 84%
rename from chrome/browser/renderer_context_menu/quick_answers_menu_observer_unittest.cc
rename to chrome/browser/renderer_context_menu/read_write_card_observer_unittest.cc
index 5e318de..a97d0888 100644
--- a/chrome/browser/renderer_context_menu/quick_answers_menu_observer_unittest.cc
+++ b/chrome/browser/renderer_context_menu/read_write_card_observer_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/renderer_context_menu/quick_answers_menu_observer.h"
+#include "chrome/browser/renderer_context_menu/read_write_card_observer.h"
 
 #include <cstddef>
 #include <memory>
@@ -73,22 +73,22 @@
 
 }  // namespace
 
-class QuickAnswersMenuObserverTest : public ChromeRenderViewHostTestHarness {
+class ReadWriteCardObserverTest : public ChromeRenderViewHostTestHarness {
  public:
-  QuickAnswersMenuObserverTest() = default;
+  ReadWriteCardObserverTest() = default;
 
-  QuickAnswersMenuObserverTest(const QuickAnswersMenuObserverTest&) = delete;
-  QuickAnswersMenuObserverTest& operator=(const QuickAnswersMenuObserverTest&) =
+  ReadWriteCardObserverTest(const ReadWriteCardObserverTest&) = delete;
+  ReadWriteCardObserverTest& operator=(const ReadWriteCardObserverTest&) =
       delete;
 
-  ~QuickAnswersMenuObserverTest() override = default;
+  ~ReadWriteCardObserverTest() override = default;
 
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
 
     context_menu_ = CreateContextMenu(web_contents());
-    observer_ = std::make_unique<QuickAnswersMenuObserver>(context_menu_.get(),
-                                                           profile());
+    observer_ =
+        std::make_unique<ReadWriteCardObserver>(context_menu_.get(), profile());
 
     auto controllers = InitControllers();
 
@@ -110,7 +110,7 @@
 
  protected:
   std::vector<std::unique_ptr<TestReadWriteCardController>> controllers_;
-  std::unique_ptr<QuickAnswersMenuObserver> observer_;
+  std::unique_ptr<ReadWriteCardObserver> observer_;
 
  private:
   std::vector<base::WeakPtr<chromeos::ReadWriteCardController>>
@@ -132,7 +132,7 @@
 
 // Make sure that all controllers are fetched into the class after
 // `OnFetchControllers`.
-TEST_F(QuickAnswersMenuObserverTest, FetchController) {
+TEST_F(ReadWriteCardObserverTest, FetchController) {
   EXPECT_EQ(controllers_.size(), GetReadWriteCardControllers().size());
   EXPECT_FALSE(controllers_.empty());
 
@@ -141,14 +141,14 @@
   }
 }
 
-TEST_F(QuickAnswersMenuObserverTest, BoundsChanged) {
+TEST_F(ReadWriteCardObserverTest, BoundsChanged) {
   observer_->OnContextMenuViewBoundsChanged(/*bounds_in_screen=*/gfx::Rect());
   for (auto& controller : controllers_) {
     EXPECT_TRUE(controller->on_anchor_bounds_changed_called());
   }
 }
 
-TEST_F(QuickAnswersMenuObserverTest, OnMenuClosed) {
+TEST_F(ReadWriteCardObserverTest, OnMenuClosed) {
   observer_->OnMenuClosed();
   for (auto& controller : controllers_) {
     EXPECT_TRUE(controller->on_dismiss_called());
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 aae767a..93466423 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -286,6 +286,7 @@
 
 #if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
 #include "chrome/browser/lens/region_search/lens_region_search_controller.h"
+#include "chrome/browser/ui/lens/lens_overlay_controller.h"
 #include "chrome/browser/ui/lens/lens_side_panel_helper.h"
 #include "chrome/grit/theme_resources.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -300,7 +301,7 @@
 #include "chrome/browser/chromeos/arc/start_smart_selection_action_menu.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h"
-#include "chrome/browser/renderer_context_menu/quick_answers_menu_observer.h"
+#include "chrome/browser/renderer_context_menu/read_write_card_observer.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "chromeos/ui/clipboard_history/clipboard_history_submenu_model.h"
 #include "chromeos/ui/clipboard_history/clipboard_history_util.h"
@@ -1323,10 +1324,10 @@
     menu_model_.RemoveItemAt(0);
   }
 
-  // Always add Quick Answers view last, as it is rendered next to the context
+  // Always add read write cards UI last, as it is rendered next to the context
   // menu, meaning that each menu item added/removed in this function will cause
   // it to visibly jump on the screen (see b/173569669).
-  AppendQuickAnswersItems();
+  AppendReadWriteCardItems();
 
   if (base::FeatureList::IsEnabled(
           autofill::features::kAutofillPopupDoesNotOverlapWithContextMenu)) {
@@ -1892,15 +1893,15 @@
 #endif
 }
 
-void RenderViewContextMenu::AppendQuickAnswersItems() {
+void RenderViewContextMenu::AppendReadWriteCardItems() {
 #if BUILDFLAG(IS_CHROMEOS)
-  if (!quick_answers_menu_observer_) {
-    quick_answers_menu_observer_ =
-        std::make_unique<QuickAnswersMenuObserver>(this, GetProfile());
+  if (!read_write_card_observer_) {
+    read_write_card_observer_ =
+        std::make_unique<ReadWriteCardObserver>(this, GetProfile());
   }
 
-  observers_.AddObserver(quick_answers_menu_observer_.get());
-  quick_answers_menu_observer_->InitMenu(params_);
+  observers_.AddObserver(read_write_card_observer_.get());
+  read_write_card_observer_->InitMenu(params_);
 #endif
 }
 
@@ -4273,6 +4274,15 @@
     return;
   }
 
+  if (is_google_default_search_provider &&
+      lens::features::IsLensOverlayEnabled()) {
+    browser->tab_strip_model()
+        ->GetActiveTab()
+        ->lens_overlay_controller()
+        ->ShowUI();
+    return;
+  }
+
   // We don't use `source_web_contents_` here because it doesn't work with the
   // PDF reader.
   WebContents* web_contents =
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 b49ccaa5..e83fec15 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.h
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -63,7 +63,7 @@
 class LinkToTextMenuObserver;
 class PrintPreviewContextMenuObserver;
 class Profile;
-class QuickAnswersMenuObserver;
+class ReadWriteCardObserver;
 class SpellingMenuObserver;
 class SpellingOptionsSubMenuObserver;
 #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
@@ -283,7 +283,7 @@
   void AppendOpenWithLinkItems();
   void AppendSmartSelectionActionItems();
   void AppendOpenInWebAppLinkItems();
-  void AppendQuickAnswersItems();
+  void AppendReadWriteCardItems();
   void AppendImageItems();
   void AppendAudioItems();
   void AppendCanvasItems();
@@ -499,8 +499,8 @@
   // An observer that handles smart text selection action items.
   std::unique_ptr<RenderViewContextMenuObserver>
       start_smart_selection_action_menu_observer_;
-  // An observer that generate Quick answers queries.
-  std::unique_ptr<QuickAnswersMenuObserver> quick_answers_menu_observer_;
+  // An observer that populates events to read write cards.
+  std::unique_ptr<ReadWriteCardObserver> read_write_card_observer_;
 
   // A submenu model to contain clipboard history item descriptors. Used only if
   // the clipboard history refresh feature is enabled.
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index 9e8177d7..6b13041 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -171,6 +171,8 @@
 #endif
 
 #if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+#include "base/test/run_until.h"
+#include "chrome/browser/ui/lens/lens_overlay_controller.h"
 #include "chrome/browser/ui/lens/lens_side_panel_helper.h"
 #include "ui/events/test/event_generator.h"
 #endif
@@ -2644,6 +2646,57 @@
   EXPECT_EQ(new_tab_content, expected_content);
 }
 
+class LensOverlayBrowserTest : public SearchByRegionBrowserBaseTest {
+ protected:
+  void SetUp() override {
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitWithFeatures({lens::features::kLensOverlay}, {});
+
+    // This does not use SearchByRegionBrowserBaseTest::SetUp because that
+    // function does its own conflicting initialization of a FeatureList.
+    InProcessBrowserTest::SetUp();
+  }
+
+  void OpenContextMenuAndClickRegionSearchEntrypoint(
+      ContextMenuNotificationObserver::MenuShownCallback callback) {
+    // |menu_observer_| will cause the search lens for image menu item to be
+    // clicked.
+    menu_observer_ = std::make_unique<ContextMenuNotificationObserver>(
+        IDC_CONTENT_CONTEXT_LENS_REGION_SEARCH, ui::EF_MOUSE_BUTTON,
+        std::move(callback));
+    RightClickToOpenContextMenu();
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(LensOverlayBrowserTest,
+                       RegionSearchContextMenuOpensLensOverlay) {
+  // State should start in off.
+  auto* controller =
+      browser()->tab_strip_model()->GetActiveTab()->lens_overlay_controller();
+  ASSERT_EQ(controller->state(), LensOverlayController::State::kOff);
+
+  OpenContextMenuAndClickRegionSearchEntrypoint(base::NullCallback());
+
+  // Clicking the region search entrypoint should eventually result in overlay
+  // state.
+  ASSERT_TRUE(base::test::RunUntil([&]() {
+    return controller->state() == LensOverlayController::State::kOverlay;
+  }));
+}
+
+IN_PROC_BROWSER_TEST_F(LensOverlayBrowserTest,
+                       RegionSearchContextMenuDoesNotOpenRegionSearch) {
+  OpenContextMenuAndClickRegionSearchEntrypoint(
+      // Callback that will be called after the context menu item is clicked.
+      base::BindLambdaForTesting([&](RenderViewContextMenu* menu) {
+        // Verify the normal region search flow does not activate
+        lens::LensRegionSearchController* controller =
+            menu->GetLensRegionSearchControllerForTesting();
+        ASSERT_EQ(controller, nullptr);
+      }));
+  base::RunLoop().RunUntilIdle();
+}
+
 #endif  // BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
 
 #if BUILDFLAG(ENABLE_PDF)
diff --git a/chrome/browser/resources/ash/settings/os_printing_page/cups_printers.html b/chrome/browser/resources/ash/settings/os_printing_page/cups_printers.html
index cefa5e9..a77ce66 100644
--- a/chrome/browser/resources/ash/settings/os_printing_page/cups_printers.html
+++ b/chrome/browser/resources/ash/settings/os_printing_page/cups_printers.html
@@ -17,7 +17,7 @@
     padding: 20px;
   }
 
-  #addManualPrinterButtonRevamp {
+  #addManualPrinterButton {
     background: none;
   }
 
@@ -66,7 +66,7 @@
     pointer-events: none;
   }
 
-  #nearbyPrintersRevamp {
+  #nearbyPrinters {
     display: flex;
   }
 
@@ -120,12 +120,12 @@
     padding-inline-start: 20px;
   }
 
-  #addPrinterSectionRevamp {
+  #addPrinterSection {
     height: 64px;
     padding-inline: 0;
   }
 
-  #addPrinterSectionRevampContainer {
+  #addPrinterSectionContainer {
     padding-inline-start: 10px;
     padding-top: 8px;
   }
@@ -245,10 +245,10 @@
           active-printer="{{activePrinter}}"
           printers-count="{{nearbyPrinterCount_}}">
       </settings-cups-nearby-printers>
-      <div id="addPrinterSectionRevamp" class="list-frame add-printer-section">
-        <div id="addPrinterSectionRevampContainer"
+      <div id="addPrinterSection" class="list-frame add-printer-section">
+        <div id="addPrinterSectionContainer"
             class="layout horizontal center custom-list-item-top">
-          <cr-button id="addManualPrinterButtonRevamp"
+          <cr-button id="addManualPrinterButton"
               class="prefix-icon" on-click="onAddPrinterClick_"
               disabled="[[!addPrinterButtonActive_(hasActiveNetworkConnection,
                   prefs.native_printing.user_native_printers_allowed.value)]]"
diff --git a/chrome/browser/resources/ash/settings/os_printing_page/cups_printers.ts b/chrome/browser/resources/ash/settings/os_printing_page/cups_printers.ts
index 2f54a375..953c2ef 100644
--- a/chrome/browser/resources/ash/settings/os_printing_page/cups_printers.ts
+++ b/chrome/browser/resources/ash/settings/os_printing_page/cups_printers.ts
@@ -471,7 +471,7 @@
 
   private onAddPrinterDialogClose_(): void {
     const icon = this.shadowRoot!.querySelector<CrIconButtonElement>(
-        '#addManualPrinterButtonRevamp');
+        '#addManualPrinterButton');
     assert(icon);
     focusWithoutInk(icon);
   }
diff --git a/chrome/browser/resources/ash/settings/os_settings_routes.ts b/chrome/browser/resources/ash/settings/os_settings_routes.ts
index fde3ec4..5a7271b 100644
--- a/chrome/browser/resources/ash/settings/os_settings_routes.ts
+++ b/chrome/browser/resources/ash/settings/os_settings_routes.ts
@@ -321,10 +321,11 @@
   if (!isGuest()) {
     r.OS_PEOPLE = createSection(
         r.BASIC, routesMojom.PEOPLE_SECTION_PATH, Section.kPeople);
-    r.ACCOUNT_MANAGER = createSubpage(
-        r.OS_PEOPLE, routesMojom.MY_ACCOUNTS_SUBPAGE_PATH, Subpage.kMyAccounts);
 
     if (!isRevampWayfindingEnabled()) {
+      r.ACCOUNT_MANAGER = createSubpage(
+          r.OS_PEOPLE, routesMojom.MY_ACCOUNTS_SUBPAGE_PATH,
+          Subpage.kMyAccounts);
       // TODO(b/305747266) : Disambiguate the names for OS_SYNC and SYNC.
       r.OS_SYNC = createSubpage(
           r.OS_PEOPLE, routesMojom.SYNC_SUBPAGE_PATH, Subpage.kSync);
diff --git a/chrome/browser/resources/new_tab_page/app.html b/chrome/browser/resources/new_tab_page/app.html
index 3026d95..d343309 100644
--- a/chrome/browser/resources/new_tab_page/app.html
+++ b/chrome/browser/resources/new_tab_page/app.html
@@ -338,6 +338,56 @@
     }
   }
 
+  :host([wallpaper-search-button-animation-enabled_])
+      #wallpaperSearchButtonContainer {
+    animation: 750ms forwards grow;
+    opacity: 0;
+    right: 0px;
+    transform-origin: right;
+  }
+
+  @keyframes grow {
+    from {
+      opacity: 0;
+      right: 0px;
+      transform: scale(0.8);
+    }
+    to {
+      opacity: 100%;
+      right: 40px;
+      transform: scale(1);
+    }
+  }
+
+  :host([wallpaper-search-button-animation-enabled_])
+      #wallpaperSearchIcon {
+    animation: 2.5s 350ms spin;
+  }
+
+  @keyframes spin {
+    from {
+      transform:rotate(0deg);
+    }
+    to {
+      transform:rotate(720deg);
+    }
+  }
+
+  :host([wallpaper-search-button-animation-enabled_])
+      #wallpaperSearchText {
+    animation: 500ms forwards 300ms show;
+    opacity: 0;
+  }
+
+  @keyframes show {
+    from {
+      opacity: 0;
+    }
+    to {
+      opacity: 100%;
+    }
+  }
+
   #themeAttribution {
     align-self: flex-start;
     bottom: 16px;
@@ -527,7 +577,8 @@
                 aria-pressed="[[showWallpaperSearch_]]">
               <div id="wallpaperSearchIcon"
                   class="customize-icon" slot="prefix-icon"></div>
-              <div class="customize-text" hidden$="[[showWallpaperSearch_]]">
+              <div id="wallpaperSearchText" class="customize-text"
+                  hidden$="[[showWallpaperSearch_]]">
                 $i18n{wallpaperSearchButton}
               </div>
             </cr-button>
diff --git a/chrome/browser/resources/new_tab_page/app.ts b/chrome/browser/resources/new_tab_page/app.ts
index 2d817611..67d889e 100644
--- a/chrome/browser/resources/new_tab_page/app.ts
+++ b/chrome/browser/resources/new_tab_page/app.ts
@@ -335,6 +335,13 @@
         value: document.documentElement.scrollTop <= 0,
       },
 
+      wallpaperSearchButtonAnimationEnabled_: {
+        type: Boolean,
+        value: () =>
+            loadTimeData.getBoolean('wallpaperSearchButtonAnimationEnabled'),
+        reflectToAttribute: true,
+      },
+
       wallpaperSearchButtonEnabled_: {
         type: Boolean,
         value: () => loadTimeData.getBoolean('wallpaperSearchButtonEnabled'),
@@ -382,6 +389,7 @@
   private promoAndModulesLoaded_: boolean;
   private lazyRender_: boolean;
   private scrolledToTop_: boolean;
+  private wallpaperSearchButtonAnimationEnabled_: boolean;
   private wallpaperSearchButtonEnabled_: boolean;
 
   private callbackRouter_: PageCallbackRouter;
diff --git a/chrome/browser/resources/side_panel/read_anything/app.ts b/chrome/browser/resources/side_panel/read_anything/app.ts
index a9cf8a3..ec664dc 100644
--- a/chrome/browser/resources/side_panel/read_anything/app.ts
+++ b/chrome/browser/resources/side_panel/read_anything/app.ts
@@ -1286,14 +1286,16 @@
     if (this.chromeRefresh2023Enabled_ && (colorSuffix === '')) {
       return 'var(--color-sys-state-hover-on-subtle)';
     }
-    return `var(--color-current-read-aloud-highlight${colorSuffix})`;
+    return `var(--color-read-anything-current-read-aloud-highlight${
+        colorSuffix})`;
   }
 
   getPreviousHighlightColorVar(colorSuffix: string) {
     if (this.chromeRefresh2023Enabled_ && (colorSuffix === '')) {
       return 'var(--color-sys-on-surface-secondary)';
     }
-    return `var(--color-previous-read-aloud-highlight${colorSuffix})`;
+    return `var(--color-read-anything-previous-read-aloud-highlight${
+        colorSuffix})`;
   }
 
   getBackgroundColorVar(colorSuffix: string) {
diff --git a/chrome/browser/resources/tab_search/tab_organization_group.html b/chrome/browser/resources/tab_search/tab_organization_group.html
index bf9b926..07bb8d2b 100644
--- a/chrome/browser/resources/tab_search/tab_organization_group.html
+++ b/chrome/browser/resources/tab_search/tab_organization_group.html
@@ -139,6 +139,7 @@
   </iron-selector>
   <template is="dom-if" if="[[!multiTabOrganization]]">
     <tab-organization-results-actions
+        show-refresh="[[refreshButtonEnabled_]]"
         is-last-organization="[[isLastOrganization]]"
         on-create-group-click="onCreateGroupClick_"
         on-reject-click="onRejectGroupClick_">
diff --git a/chrome/browser/resources/tab_search/tab_organization_group.ts b/chrome/browser/resources/tab_search/tab_organization_group.ts
index 76ddd68..c1032fb 100644
--- a/chrome/browser/resources/tab_search/tab_organization_group.ts
+++ b/chrome/browser/resources/tab_search/tab_organization_group.ts
@@ -53,6 +53,12 @@
         value: 0,
       },
 
+      refreshButtonEnabled_: {
+        type: Boolean,
+        value: () =>
+            loadTimeData.getBoolean('tabOrganizationRefreshButtonEnabled'),
+      },
+
       showInput_: Boolean,
 
       tabDatas_: {
@@ -70,6 +76,7 @@
   organizationId: number;
 
   private lastFocusedIndex_: number;
+  private refreshButtonEnabled_: boolean;
   private showInput_: boolean;
   private tabDatas_: TabData[];
 
diff --git a/chrome/browser/resources/tab_search/tab_organization_page.html b/chrome/browser/resources/tab_search/tab_organization_page.html
index 1b150789..f89bd1e 100644
--- a/chrome/browser/resources/tab_search/tab_organization_page.html
+++ b/chrome/browser/resources/tab_search/tab_organization_page.html
@@ -70,7 +70,9 @@
         multi-tab-organization="[[multiTabOrganization_]]"
         available-height="[[availableHeight_]]"
         on-reject-click="onRejectClick_"
+        on-reject-all-groups-click="onRejectAllGroupsClick_"
         on-create-group-click="onCreateGroupClick_"
+        on-create-all-groups-click="onCreateAllGroupsClick_"
         on-remove-tab="onRemoveTab_"
         on-learn-more-click="onLearnMoreClick_"
         on-feedback="onFeedback_">
diff --git a/chrome/browser/resources/tab_search/tab_organization_page.ts b/chrome/browser/resources/tab_search/tab_organization_page.ts
index a0819fa..bcb86aa 100644
--- a/chrome/browser/resources/tab_search/tab_organization_page.ts
+++ b/chrome/browser/resources/tab_search/tab_organization_page.ts
@@ -246,6 +246,10 @@
         this.session_!.sessionId, event.detail.organizationId);
   }
 
+  private onRejectAllGroupsClick_() {
+    this.apiProxy_.rejectSession(this.session_!.sessionId);
+  }
+
   private onCreateGroupClick_(
       event: CustomEvent<{organizationId: number, name: string, tabs: Tab[]}>) {
     this.apiProxy_.acceptTabOrganization(
@@ -253,6 +257,16 @@
         event.detail.name, event.detail.tabs);
   }
 
+  private onCreateAllGroupsClick_(event: CustomEvent<{
+    organizations: Array<{organizationId: number, name: string, tabs: Tab[]}>,
+  }>) {
+    event.detail.organizations.forEach((organization) => {
+      this.apiProxy_.acceptTabOrganization(
+          this.session_!.sessionId, organization.organizationId,
+          organization.name, organization.tabs);
+    });
+  }
+
   private onCheckNow_() {
     this.apiProxy_.restartSession();
   }
diff --git a/chrome/browser/resources/tab_search/tab_organization_results.html b/chrome/browser/resources/tab_search/tab_organization_results.html
index 2ad83b0..6ce6acfd3d 100644
--- a/chrome/browser/resources/tab_search/tab_organization_results.html
+++ b/chrome/browser/resources/tab_search/tab_organization_results.html
@@ -49,7 +49,7 @@
     </template>
   </div>
   <template is="dom-if" if="[[multiTabOrganization]]">
-    <tab-organization-results-actions
+    <tab-organization-results-actions show-refresh
         multiple-organizations="[[hasMultipleOrganizations_(session)]]"
         on-create-group-click="onCreateAllGroupsClick_"
         on-reject-click="onRejectAllGroupsClick_">
diff --git a/chrome/browser/resources/tab_search/tab_organization_results.ts b/chrome/browser/resources/tab_search/tab_organization_results.ts
index 54863c3..e9058ea 100644
--- a/chrome/browser/resources/tab_search/tab_organization_results.ts
+++ b/chrome/browser/resources/tab_search/tab_organization_results.ts
@@ -17,6 +17,7 @@
 import type {IronSelectorElement} from 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import type {TabOrganizationGroupElement} from './tab_organization_group.js';
 import {getTemplate} from './tab_organization_results.html.js';
 import type {TabOrganization, TabOrganizationSession} from './tab_search.mojom-webui.js';
 
@@ -123,13 +124,31 @@
   private onCreateAllGroupsClick_(event: CustomEvent) {
     event.stopPropagation();
     event.preventDefault();
-    // TODO(b/324942857): Implement
+
+    const groups =
+        [...this.shadowRoot!.querySelectorAll('tab-organization-group')];
+    const organizations = groups.map((group: TabOrganizationGroupElement) => {
+      return {
+        organizationId: group.organizationId,
+        name: group.name,
+        tabs: group.tabs,
+      };
+    });
+
+    this.dispatchEvent(new CustomEvent('create-all-groups-click', {
+      bubbles: true,
+      composed: true,
+      detail: {organizations},
+    }));
   }
 
   private onRejectAllGroupsClick_(event: CustomEvent) {
     event.stopPropagation();
     event.preventDefault();
-    // TODO(b/324944497): Implement
+    this.dispatchEvent(new CustomEvent('reject-all-groups-click', {
+      bubbles: true,
+      composed: true,
+    }));
   }
 
   private onLearnMoreClick_() {
diff --git a/chrome/browser/resources/tab_search/tab_organization_results_actions.html b/chrome/browser/resources/tab_search/tab_organization_results_actions.html
index b098ba19..d0b82ed 100644
--- a/chrome/browser/resources/tab_search/tab_organization_results_actions.html
+++ b/chrome/browser/resources/tab_search/tab_organization_results_actions.html
@@ -11,12 +11,14 @@
 </style>
 
 <div class="button-row">
-  <template is="dom-if" if="[[showRefresh_]]">
-    <cr-button class="tonal-button" on-click="onRejectGroupClick_">
+  <template is="dom-if" if="[[showRefresh]]">
+    <cr-button id="refreshButton" class="tonal-button"
+        on-click="onRejectGroupClick_">
       [[getRefreshButtonText_(isLastOrganization, multipleOrganizations)]]
     </cr-button>
   </template>
-  <cr-button class="action-button" on-click="onCreateGroupClick_">
+  <cr-button id="createButton" class="action-button"
+      on-click="onCreateGroupClick_">
     [[getCreateButtonText_(multipleOrganizations)]]
   </cr-button>
 </div>
diff --git a/chrome/browser/resources/tab_search/tab_organization_results_actions.ts b/chrome/browser/resources/tab_search/tab_organization_results_actions.ts
index fc006be..14b34404 100644
--- a/chrome/browser/resources/tab_search/tab_organization_results_actions.ts
+++ b/chrome/browser/resources/tab_search/tab_organization_results_actions.ts
@@ -2,6 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+/**
+ * @fileoverview 'tab-organization-results-actions' is a row with actions that
+ * can be taken on a tab organization suggestion. It is agnostic as to what
+ * that suggestion is, and can be used to suggest one or multiple groups.
+ */
+
 import 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import './strings.m.js';
 
@@ -19,19 +25,13 @@
     return {
       isLastOrganization: Boolean,
       multipleOrganizations: Boolean,
-
-      showRefresh_: {
-        type: Boolean,
-        value: () =>
-            loadTimeData.getBoolean('tabOrganizationRefreshButtonEnabled'),
-      },
+      showRefresh: Boolean,
     };
   }
 
   isLastOrganization: boolean;
   multipleOrganizations: boolean;
-
-  private showRefresh_: boolean;
+  showRefresh: boolean;
 
   static get template() {
     return getTemplate();
diff --git a/chrome/browser/resources/tab_search/tab_search_api_proxy.ts b/chrome/browser/resources/tab_search/tab_search_api_proxy.ts
index f98597c..77834016 100644
--- a/chrome/browser/resources/tab_search/tab_search_api_proxy.ts
+++ b/chrome/browser/resources/tab_search/tab_search_api_proxy.ts
@@ -34,6 +34,8 @@
 
   requestTabOrganization(): void;
 
+  rejectSession(sessionId: number): void;
+
   restartSession(): void;
 
   switchToTab(info: SwitchToTabInfo): void;
@@ -118,6 +120,10 @@
     this.handler.requestTabOrganization();
   }
 
+  rejectSession(sessionId: number) {
+    this.handler.rejectSession(sessionId);
+  }
+
   restartSession() {
     this.handler.restartSession();
   }
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc
index f005cd7..2c04e9c 100644
--- a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc
+++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc
@@ -109,11 +109,12 @@
 void ChromeEnterpriseRealTimeUrlLookupService::GetAccessToken(
     const GURL& url,
     RTLookupResponseCallback response_callback,
-    scoped_refptr<base::SequencedTaskRunner> callback_task_runner) {
+    scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+    SessionID tab_id) {
   token_fetcher_->Start(base::BindOnce(
       &ChromeEnterpriseRealTimeUrlLookupService::OnGetAccessToken,
       weak_factory_.GetWeakPtr(), url, std::move(response_callback),
-      std::move(callback_task_runner), base::TimeTicks::Now()));
+      std::move(callback_task_runner), base::TimeTicks::Now(), tab_id));
 }
 
 void ChromeEnterpriseRealTimeUrlLookupService::OnGetAccessToken(
@@ -121,10 +122,11 @@
     RTLookupResponseCallback response_callback,
     scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
     base::TimeTicks get_token_start_time,
+    SessionID tab_id,
     const std::string& access_token) {
   SendRequest(url, access_token, std::move(response_callback),
               std::move(callback_task_runner),
-              /* is_sampled_report */ false);
+              /* is_sampled_report */ false, tab_id);
 }
 
 std::optional<std::string>
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h
index 12752c6..2237e1f6 100644
--- a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h
+++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h
@@ -72,7 +72,8 @@
   void GetAccessToken(
       const GURL& url,
       RTLookupResponseCallback response_callback,
-      scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override;
+      scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+      SessionID tab_id) override;
 
   // Called when the access token is obtained from |token_fetcher_|.
   void OnGetAccessToken(
@@ -80,6 +81,7 @@
       RTLookupResponseCallback response_callback,
       scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
       base::TimeTicks get_token_start_time,
+      SessionID tab_id,
       const std::string& access_token);
 
   std::optional<std::string> GetDMTokenString() const override;
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_unittest.cc b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_unittest.cc
index 12dde47..85778d7 100644
--- a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_unittest.cc
@@ -62,6 +62,11 @@
                                      event_outermost_main_frame_id,
                                  int user_gesture_count_limit,
                                  ReferrerChain* out_referrer_chain));
+  MOCK_METHOD4(IdentifyReferrerChainByEventURL,
+               AttributionResult(const GURL& event_url,
+                                 SessionID event_tab_id,
+                                 int user_gesture_count_limit,
+                                 ReferrerChain* out_referrer_chain));
   MOCK_METHOD3(IdentifyReferrerChainByPendingEventURL,
                AttributionResult(const GURL& event_url,
                                  int user_gesture_count_limit,
@@ -240,7 +245,8 @@
       request_callback;
   base::MockCallback<RTLookupResponseCallback> response_callback;
   enterprise_rt_service()->StartLookup(url, response_callback.Get(),
-                                       content::GetIOThreadTaskRunner({}));
+                                       content::GetIOThreadTaskRunner({}),
+                                       SessionID::InvalidValue());
 
   test_url_loader_factory_.SetInterceptor(request_callback.Get());
   EXPECT_CALL(request_callback, Run(_)).Times(0);
@@ -266,7 +272,8 @@
 
   base::MockCallback<RTLookupResponseCallback> response_callback;
   enterprise_rt_service()->StartLookup(url, response_callback.Get(),
-                                       content::GetIOThreadTaskRunner({}));
+                                       content::GetIOThreadTaskRunner({}),
+                                       SessionID::InvalidValue());
 
   EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ true,
                                      /* is_cached_response */ false, _));
diff --git a/chrome/browser/safe_browsing/threat_details_unittest.cc b/chrome/browser/safe_browsing/threat_details_unittest.cc
index c827245e1..ff2906b2 100644
--- a/chrome/browser/safe_browsing/threat_details_unittest.cc
+++ b/chrome/browser/safe_browsing/threat_details_unittest.cc
@@ -229,6 +229,11 @@
                                      outermost_event_main_frame_id,
                                  int user_gesture_count_limit,
                                  ReferrerChain* out_referrer_chain));
+  MOCK_METHOD4(IdentifyReferrerChainByEventURL,
+               AttributionResult(const GURL& event_url,
+                                 SessionID event_tab_id,
+                                 int user_gesture_count_limit,
+                                 ReferrerChain* out_referrer_chain));
   MOCK_METHOD3(IdentifyReferrerChainByPendingEventURL,
                AttributionResult(const GURL& event_url,
                                  int user_gesture_count_limit,
diff --git a/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerImpl.java b/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerImpl.java
index 4eb6fd9..c02b5ad 100644
--- a/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerImpl.java
+++ b/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerImpl.java
@@ -207,6 +207,8 @@
                         + newActivity
                         + " new activity task id: "
                         + newActivity.getTaskId()
+                        + " new activity is finishing? "
+                        + newActivity.isFinishing()
                         + " activity at requested index: "
                         + activityAtRequestedIndex;
         if (activityAtRequestedIndex == null) {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index eb2d8f0..34209257 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2525,6 +2525,7 @@
       "../ash/app_list/search/util/manatee.h",
       "../ash/app_list/search/util/mrfu_cache.cc",
       "../ash/app_list/search/util/mrfu_cache.h",
+      "../ash/app_list/search/util/persistent_proto.cc",
       "../ash/app_list/search/util/persistent_proto.h",
       "../ash/app_list/search/util/score_normalizer.cc",
       "../ash/app_list/search/util/score_normalizer.h",
diff --git a/chrome/browser/ui/android/edge_to_edge/internal/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerImpl.java b/chrome/browser/ui/android/edge_to_edge/internal/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerImpl.java
index 894b81690..3906beb 100644
--- a/chrome/browser/ui/android/edge_to_edge/internal/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerImpl.java
+++ b/chrome/browser/ui/android/edge_to_edge/internal/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerImpl.java
@@ -48,7 +48,6 @@
     private final @NonNull Activity mActivity;
     private final @NonNull TabSupplierObserver mTabSupplierObserver;
     private final ObserverList<EdgeToEdgePadAdjuster> mPadAdjusters = new ObserverList<>();
-    private final ObserverList<ChangeObserver> mEdgeChangeObservers = new ObserverList<>();
     private final @NonNull TabObserver mTabObserver;
 
     /** Multiplier to convert from pixels to DPs. */
@@ -144,16 +143,6 @@
     }
 
     @Override
-    public void registerObserver(ChangeObserver changeObserver) {
-        mEdgeChangeObservers.addObserver(changeObserver);
-    }
-
-    @Override
-    public void unregisterObserver(ChangeObserver changeObserver) {
-        mEdgeChangeObservers.removeObserver(changeObserver);
-    }
-
-    @Override
     public int getBottomInset() {
         return mSystemInsets == null || !isToEdge()
                 ? 0
@@ -185,8 +174,7 @@
     }
 
     /**
-     * Conditionally draws the given View ToEdge or ToNormal based on {@link
-     * EdgeToEdgeUtils#shouldDrawToEdge(Tab)}
+     * Conditionally draws the given View ToEdge or ToNormal based on {@link #shouldDrawToEdge(Tab)}
      *
      * @param viewId The ID of the Root UI View.
      * @param webContents The {@link WebContents} to notify of inset env() changes.
@@ -197,8 +185,8 @@
     }
 
     /**
-     * Conditionally draws the given View ToEdge or ToNormal based on {@link
-     * EdgeToEdgeUtils#shouldDrawToEdge(Tab, int)}.
+     * Conditionally draws the given View ToEdge or ToNormal based on {@link #shouldDrawToEdge(Tab,
+     * int)}.
      *
      * @param viewId The ID of the Root UI View.
      * @param value A new {@link WebContentsObserver.ViewportFitType} value being applied now.
@@ -291,9 +279,6 @@
         for (var adjuster : mPadAdjusters) {
             adjuster.adjustToEdge(toEdge, mSystemInsets.bottom);
         }
-        for (var observer : mEdgeChangeObservers) {
-            observer.onToEdgeChange(isToEdge() ? mSystemInsets.bottom : 0);
-        }
 
         // We only make the Nav Bar transparent because it's the only thing we want to draw
         // underneath.
@@ -370,10 +355,6 @@
         mIsActivityToEdge = toEdge;
     }
 
-    public @Nullable ChangeObserver getAnyChangeObserverForTesting() {
-        return mEdgeChangeObservers.isEmpty() ? null : mEdgeChangeObservers.iterator().next();
-    }
-
     void setSystemInsetsForTesting(Insets systemInsetsForTesting) {
         mSystemInsets = systemInsetsForTesting;
     }
diff --git a/chrome/browser/ui/android/edge_to_edge/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeSupplier.java b/chrome/browser/ui/android/edge_to_edge/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeSupplier.java
index 9773b32d..e989761 100644
--- a/chrome/browser/ui/android/edge_to_edge/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeSupplier.java
+++ b/chrome/browser/ui/android/edge_to_edge/java/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeSupplier.java
@@ -4,36 +4,9 @@
 
 package org.chromium.chrome.browser.ui.edge_to_edge;
 
-import androidx.annotation.Px;
-
 /** A supplier notifying of whether edge to edge is on and the value of the bottom inset. */
 public interface EdgeToEdgeSupplier {
-
-    /**
-     * Notifies that a change has occurred that may require an update, and supplies the new bottom
-     * inset in pixels.
-     */
-    interface ChangeObserver {
-
-        /**
-         * Notifies that a change has been made in the bottom inset and supplies the new inset.
-         *
-         * @param bottomInset The new bottom inset.
-         */
-        void onToEdgeChange(@Px int bottomInset);
-    }
-
-    /** Registers an automatic adjuster of padding for a view. See {@link EdgeToEdgePadAdjuster}. */
     void registerAdjuster(EdgeToEdgePadAdjuster adjuster);
 
     void unregisterAdjuster(EdgeToEdgePadAdjuster adjuster);
-
-    /**
-     * Registers an observer to be called any time the system changes ToEdge or back.
-     *
-     * @param changeObserver a {@link ChangeObserver} that provides the new bottom inset.
-     */
-    void registerObserver(ChangeObserver changeObserver);
-
-    void unregisterObserver(ChangeObserver changeObserver);
 }
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index 1afcb77a..6268e66e 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -2517,6 +2517,10 @@
         Listen to this page
       </message>
 
+      <message name="IDS_MENU_LISTEN_TO_THIS_PAGE_IPH" desc="The in-product-help message that encourages users to use the Listen to this Page feature in the app menu">
+        You can listen to this page
+      </message>
+
       <message name="IDS_MENU_PRINT" desc="Menu item for printing the current page. [CHAR_LIMIT=27]">
         Print…
       </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MENU_LISTEN_TO_THIS_PAGE_IPH.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MENU_LISTEN_TO_THIS_PAGE_IPH.png.sha1
new file mode 100644
index 0000000..d7ed7e4
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MENU_LISTEN_TO_THIS_PAGE_IPH.png.sha1
@@ -0,0 +1 @@
+b76351f397799d4eeccb1d4440177cf9da18d65f
\ No newline at end of file
diff --git a/chrome/browser/ui/android/toolbar/BUILD.gn b/chrome/browser/ui/android/toolbar/BUILD.gn
index 79dec1b..6f79c8f 100644
--- a/chrome/browser/ui/android/toolbar/BUILD.gn
+++ b/chrome/browser/ui/android/toolbar/BUILD.gn
@@ -144,7 +144,6 @@
     "//chrome/browser/tab_group:java",
     "//chrome/browser/tabmodel:java",
     "//chrome/browser/ui/android/appmenu:java",
-    "//chrome/browser/ui/android/edge_to_edge:java",
     "//chrome/browser/ui/android/favicon:java",
     "//chrome/browser/ui/android/favicon:java_resources",
     "//chrome/browser/ui/android/layouts:java",
@@ -315,7 +314,6 @@
     "java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerUnitTest.java",
     "java/src/org/chromium/chrome/browser/toolbar/adaptive/TranslateToolbarButtonControllerUnitTest.java",
     "java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarSettingsFragmentTest.java",
-    "java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediatorTest.java",
     "java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinatorTest.java",
     "java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediatorTest.java",
     "java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonCoordinatorTest.java",
@@ -357,8 +355,6 @@
     "//chrome/browser/tab:java",
     "//chrome/browser/tabmodel:java",
     "//chrome/browser/ui/android/appmenu:java",
-    "//chrome/browser/ui/android/edge_to_edge:java",
-    "//chrome/browser/ui/android/edge_to_edge/internal:java",
     "//chrome/browser/ui/android/layouts:java",
     "//chrome/browser/ui/android/omnibox:java",
     "//chrome/browser/ui/android/omnibox:java_resources",
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
index 18d04a7..1cc3d6d 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.tab.TabObscuringHandler;
 import org.chromium.chrome.browser.toolbar.R;
 import org.chromium.chrome.browser.toolbar.bottom.BottomControlsViewBinder.ViewHolder;
-import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeController;
 import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -49,15 +48,13 @@
 
     /**
      * Build the coordinator that manages the bottom controls.
-     *
      * @param activity Activity instance to use.
      * @param windowAndroid A {@link WindowAndroid} for watching keyboard visibility events.
      * @param layoutManager A {@link LayoutManager} to attach overlays to.
      * @param resourceManager A {@link ResourceManager} for loading textures into the compositor.
-     * @param controlsSizer A {@link BrowserControlsSizer} to update the bottom controls height for
-     *     the renderer.
+     * @param controlsSizer A {@link BrowserControlsSizer} to update the bottom controls
+     *                          height for the renderer.
      * @param fullscreenManager A {@link FullscreenManager} to listen for fullscreen changes.
-     * @param edgeToEdgeControllerSupplier A supplier to control drawing to the edge of the screen.
      * @param root The parent {@link ViewGroup} for the bottom controls.
      * @param contentDelegate Delegate for bottom controls UI operations.
      * @param tabObscuringHandler Delegate object handling obscuring views.
@@ -72,7 +69,6 @@
             ResourceManager resourceManager,
             BrowserControlsSizer controlsSizer,
             FullscreenManager fullscreenManager,
-            ObservableSupplier<EdgeToEdgeController> edgeToEdgeControllerSupplier,
             ScrollingBottomViewResourceFrameLayout root,
             BottomControlsContentDelegate contentDelegate,
             TabObscuringHandler tabObscuringHandler,
@@ -91,10 +87,7 @@
 
         View container = root.findViewById(R.id.bottom_container_slot);
         ViewGroup.LayoutParams params = container.getLayoutParams();
-
-        int bottomControlsHeightRes =
-                root.getResources().getDimensionPixelOffset(bottomControlsHeightId);
-        params.height = bottomControlsHeightRes;
+        params.height = root.getResources().getDimensionPixelOffset(bottomControlsHeightId);
         mMediator =
                 new BottomControlsMediator(
                         windowAndroid,
@@ -102,9 +95,9 @@
                         controlsSizer,
                         fullscreenManager,
                         tabObscuringHandler,
-                        bottomControlsHeightRes,
-                        overlayPanelVisibilitySupplier,
-                        edgeToEdgeControllerSupplier);
+                        root.getResources().getDimensionPixelOffset(bottomControlsHeightId),
+                        overlayPanelVisibilitySupplier);
+
         resourceManager
                 .getDynamicResourceLoader()
                 .registerResource(root.getId(), root.getResourceAdapter());
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java
index dc95539d..17f5645 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java
@@ -4,8 +4,6 @@
 
 package org.chromium.chrome.browser.toolbar.bottom;
 
-import androidx.annotation.Nullable;
-
 import org.chromium.base.CallbackController;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsSizer;
@@ -15,8 +13,6 @@
 import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver;
 import org.chromium.chrome.browser.layouts.LayoutType;
 import org.chromium.chrome.browser.tab.TabObscuringHandler;
-import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeController;
-import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeSupplier.ChangeObserver;
 import org.chromium.ui.KeyboardVisibilityDelegate;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -31,8 +27,6 @@
                 KeyboardVisibilityDelegate.KeyboardVisibilityListener,
                 LayoutStateObserver,
                 TabObscuringHandler.Observer {
-    private static final String TAG = "BotControlsMediator";
-
     /** The model for the bottom controls component that holds all of its view state. */
     private final PropertyModel mModel;
 
@@ -46,8 +40,6 @@
 
     private final CallbackController mCallbackController;
 
-    private final ObservableSupplier<EdgeToEdgeController> mEdgeToEdgeControllerSupplier;
-
     /** The height of the bottom bar in pixels, not including the top shadow. */
     private int mBottomControlsHeight;
 
@@ -68,23 +60,17 @@
 
     private LayoutStateProvider mLayoutStateProvider;
 
-    @Nullable private ChangeObserver mEdgeToEdgeChangeObserver;
-    private int mBottomControlsOriginalHeight;
-
     /**
      * Build a new mediator that handles events from outside the bottom controls component.
-     *
      * @param windowAndroid A {@link WindowAndroid} for watching keyboard visibility events.
      * @param model The {@link BottomControlsProperties} that holds all the view state for the
-     *     bottom controls component.
+     *         bottom controls component.
      * @param controlsSizer The {@link BrowserControlsSizer} to manipulate browser controls.
      * @param fullscreenManager A {@link FullscreenManager} for events related to the browser
-     *     controls.
+     *                          controls.
      * @param tabObscuringHandler Delegate object handling obscuring views.
      * @param bottomControlsHeight The height of the bottom bar in pixels.
      * @param overlayPanelVisibilitySupplier Notifies overlay panel visibility event.
-     * @param edgeToEdgeControllerSupplier Supplies an {@link EdgeToEdgeController} to adjust the
-     *     height of the bottom controls when drawing all the way to the edge of the screen.
      */
     BottomControlsMediator(
             WindowAndroid windowAndroid,
@@ -93,8 +79,7 @@
             FullscreenManager fullscreenManager,
             TabObscuringHandler tabObscuringHandler,
             int bottomControlsHeight,
-            ObservableSupplier<Boolean> overlayPanelVisibilitySupplier,
-            ObservableSupplier<EdgeToEdgeController> edgeToEdgeControllerSupplier) {
+            ObservableSupplier<Boolean> overlayPanelVisibilitySupplier) {
         mModel = model;
 
         mFullscreenManager = fullscreenManager;
@@ -115,36 +100,6 @@
         // Watch for keyboard events so we can hide the bottom toolbar when the keyboard is showing.
         mWindowAndroid = windowAndroid;
         mWindowAndroid.getKeyboardDelegate().addKeyboardVisibilityListener(this);
-
-        mEdgeToEdgeControllerSupplier = edgeToEdgeControllerSupplier;
-        if (mEdgeToEdgeControllerSupplier.get() != null) {
-            mBottomControlsOriginalHeight = bottomControlsHeight;
-            mEdgeToEdgeChangeObserver =
-                    (bottomInset) -> {
-                        // TODO(https://crbug.com/327274751) handle coordination between ReadAloud
-                        // and this class.
-                        int adjustedHeight = mBottomControlsOriginalHeight + bottomInset;
-                        if (adjustedHeight != mBrowserControlsSizer.getBottomControlsHeight()) {
-                            mBrowserControlsSizer.setBottomControlsHeight(
-                                    adjustedHeight,
-                                    mBrowserControlsSizer.getBottomControlsMinHeight());
-                            updateBottomControlsOffset(adjustedHeight);
-                        }
-                        if (adjustedHeight
-                                != mModel.get(BottomControlsProperties.ANDROID_VIEW_HEIGHT)) {
-                            mModel.set(
-                                    BottomControlsProperties.ANDROID_VIEW_HEIGHT, adjustedHeight);
-                        }
-                    };
-            mEdgeToEdgeControllerSupplier.get().registerObserver(mEdgeToEdgeChangeObserver);
-        }
-    }
-
-    private void updateBottomControlsOffset(int bottomControlsYOffset) {
-        // TODO(https://crbug.com/41483234) Find a better way to update bottom controls compositor
-        // view when the height changes.
-        final int unused = 0;
-        onControlsOffsetChanged(unused, unused, bottomControlsYOffset, 0, false);
     }
 
     void setLayoutStateProvider(LayoutStateProvider layoutStateProvider) {
@@ -167,10 +122,6 @@
             mLayoutStateProvider.removeObserver(this);
             mLayoutStateProvider = null;
         }
-        if (mEdgeToEdgeControllerSupplier.get() != null && mEdgeToEdgeChangeObserver != null) {
-            mEdgeToEdgeControllerSupplier.get().unregisterObserver(mEdgeToEdgeChangeObserver);
-            mEdgeToEdgeChangeObserver = null;
-        }
         mTabObscuringHandler.removeObserver(this);
     }
 
@@ -253,8 +204,4 @@
     public void updateObscured(boolean obscureTabContent, boolean obscureToolbar) {
         mModel.set(BottomControlsProperties.IS_OBSCURED, obscureToolbar);
     }
-
-    ChangeObserver getEdgeToEdgeChangeObserverForTesting() {
-        return mEdgeToEdgeChangeObserver;
-    }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediatorTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediatorTest.java
deleted file mode 100644
index 941be81b..0000000
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediatorTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.toolbar.bottom;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.verify;
-
-import static org.chromium.chrome.browser.toolbar.bottom.BottomControlsProperties.ANDROID_VIEW_HEIGHT;
-
-import android.app.Activity;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
-import org.robolectric.annotation.Config;
-
-import org.chromium.base.supplier.ObservableSupplier;
-import org.chromium.base.supplier.ObservableSupplierImpl;
-import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.base.test.util.Features;
-import org.chromium.base.test.util.Features.DisableFeatures;
-import org.chromium.base.test.util.Features.EnableFeatures;
-import org.chromium.chrome.browser.browser_controls.BrowserControlsSizer;
-import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.fullscreen.FullscreenManager;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabObscuringHandler;
-import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeController;
-import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeControllerImpl;
-import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeSupplier.ChangeObserver;
-import org.chromium.ui.KeyboardVisibilityDelegate;
-import org.chromium.ui.base.TestActivity;
-import org.chromium.ui.base.WindowAndroid;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/** Unit tests for {@link BottomControlsMediator}. */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-@DisableFeatures({ChromeFeatureList.TOTALLY_EDGE_TO_EDGE})
-public class BottomControlsMediatorTest {
-    @Rule public TestRule mProcessor = new Features.JUnitProcessor();
-
-    private static final int DEFAULT_HEIGHT = 80;
-    private static final int DEFAULT_INSET = 56;
-    @Mock BrowserControlsSizer mBrowserControlsSizer;
-    @Mock BrowserControlsStateProvider mBrowserControlsStateProvider;
-    @Mock WindowAndroid mWindowAndroid;
-    @Mock TabObscuringHandler mTabObscuringHandler;
-    @Mock ObservableSupplier<Boolean> mOverlayPanelVisibilitySupplier;
-    @Mock EdgeToEdgeController mEdgeToEdgeController;
-    @Mock FullscreenManager mFullscreenManager;
-    @Mock KeyboardVisibilityDelegate mKeyboardDelegate;
-
-    private ObservableSupplierImpl<EdgeToEdgeController> mEdgeToEdgeControllerSupplier;
-    private ObservableSupplierImpl<Tab> mTabObservableSupplier = new ObservableSupplierImpl();
-
-    private PropertyModel mModel;
-    private BottomControlsMediator mMediator;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        doReturn(mKeyboardDelegate).when(mWindowAndroid).getKeyboardDelegate();
-        mModel =
-                new PropertyModel.Builder(BottomControlsProperties.ALL_KEYS)
-                        .with(BottomControlsProperties.ANDROID_VIEW_VISIBLE, false)
-                        .with(BottomControlsProperties.COMPOSITED_VIEW_VISIBLE, false)
-                        .build();
-        mEdgeToEdgeControllerSupplier = new ObservableSupplierImpl(mEdgeToEdgeController);
-        mMediator =
-                new BottomControlsMediator(
-                        mWindowAndroid,
-                        mModel,
-                        mBrowserControlsSizer,
-                        mFullscreenManager,
-                        mTabObscuringHandler,
-                        DEFAULT_HEIGHT,
-                        mOverlayPanelVisibilitySupplier,
-                        mEdgeToEdgeControllerSupplier);
-    }
-
-    @Test
-    public void testNoEdgeToEdge() {
-        BottomControlsMediator plainMediator =
-                new BottomControlsMediator(
-                        mWindowAndroid,
-                        mModel,
-                        mBrowserControlsSizer,
-                        mFullscreenManager,
-                        mTabObscuringHandler,
-                        DEFAULT_HEIGHT,
-                        mOverlayPanelVisibilitySupplier,
-                        new ObservableSupplierImpl(null));
-        assertNull(plainMediator.getEdgeToEdgeChangeObserverForTesting());
-    }
-
-    @Test
-    public void testEdgeToEdge_simple() {
-        assertNotNull(mMediator.getEdgeToEdgeChangeObserverForTesting());
-        verify(mEdgeToEdgeController).registerObserver(any());
-    }
-
-    @Test
-    public void testEdgeToEdge_ToNormal() {
-        ChangeObserver changeObserver = mMediator.getEdgeToEdgeChangeObserverForTesting();
-        changeObserver.onToEdgeChange(0);
-        assertEquals(DEFAULT_HEIGHT, mModel.get(ANDROID_VIEW_HEIGHT));
-    }
-
-    @Test
-    public void testEdgeToEdge_ToEdge() {
-        ChangeObserver changeObserver = mMediator.getEdgeToEdgeChangeObserverForTesting();
-        changeObserver.onToEdgeChange(DEFAULT_INSET);
-        assertEquals(DEFAULT_HEIGHT + DEFAULT_INSET, mModel.get(ANDROID_VIEW_HEIGHT));
-    }
-
-    @Test
-    public void testEdgeToEdge_ObserverDestroyed() {
-        // Set up a mediator with a live EdgeToEdgeController.
-        Activity activity = Robolectric.buildActivity(TestActivity.class).setup().get();
-        EdgeToEdgeControllerImpl liveEdgeToEdgeController =
-                new EdgeToEdgeControllerImpl(
-                        activity, mTabObservableSupplier, null, mBrowserControlsStateProvider);
-        BottomControlsMediator plainMediator =
-                new BottomControlsMediator(
-                        mWindowAndroid,
-                        mModel,
-                        mBrowserControlsSizer,
-                        mFullscreenManager,
-                        mTabObscuringHandler,
-                        DEFAULT_HEIGHT,
-                        mOverlayPanelVisibilitySupplier,
-                        new ObservableSupplierImpl(liveEdgeToEdgeController));
-        assertNotNull(liveEdgeToEdgeController.getAnyChangeObserverForTesting());
-        plainMediator.destroy();
-        assertNull(liveEdgeToEdgeController.getAnyChangeObserverForTesting());
-    }
-
-    @Test
-    @EnableFeatures(ChromeFeatureList.DRAW_NATIVE_EDGE_TO_EDGE)
-    public void testEdgeToEdge_ObserverCalled() {
-        // Set up a mediator with a live EdgeToEdgeController.
-        Activity activity = Robolectric.buildActivity(TestActivity.class).setup().get();
-        EdgeToEdgeControllerImpl liveEdgeToEdgeController =
-                new EdgeToEdgeControllerImpl(
-                        activity, mTabObservableSupplier, null, mBrowserControlsStateProvider);
-        new BottomControlsMediator(
-                mWindowAndroid,
-                mModel,
-                mBrowserControlsSizer,
-                mFullscreenManager,
-                mTabObscuringHandler,
-                DEFAULT_HEIGHT,
-                mOverlayPanelVisibilitySupplier,
-                new ObservableSupplierImpl(liveEdgeToEdgeController));
-        assertNotNull(liveEdgeToEdgeController.getAnyChangeObserverForTesting());
-        liveEdgeToEdgeController.setToEdgeForTesting(false);
-        int toNormalHeight = mModel.get(ANDROID_VIEW_HEIGHT);
-        // Go to a native page which will go ToEdge due to our enabled Feature for this test case.
-        mTabObservableSupplier.set(null);
-        assertEquals(toNormalHeight, mModel.get(ANDROID_VIEW_HEIGHT));
-    }
-}
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java
index 409b138a..b670159 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java
@@ -10,8 +10,9 @@
 import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
 
 class BottomControlsProperties {
-    /** The height of the Android View in px. */
-    static final WritableIntPropertyKey ANDROID_VIEW_HEIGHT = new WritableIntPropertyKey();
+    /** The height of the bottom control container (view which includes the top shadow) in px. */
+    static final WritableIntPropertyKey BOTTOM_CONTROLS_CONTAINER_HEIGHT_PX =
+            new WritableIntPropertyKey();
 
     /** The Y offset of the view in px. */
     static final WritableIntPropertyKey Y_OFFSET = new WritableIntPropertyKey();
@@ -35,7 +36,7 @@
 
     static final PropertyKey[] ALL_KEYS =
             new PropertyKey[] {
-                ANDROID_VIEW_HEIGHT,
+                BOTTOM_CONTROLS_CONTAINER_HEIGHT_PX,
                 Y_OFFSET,
                 ANDROID_VIEW_TRANSLATE_Y,
                 ANDROID_VIEW_VISIBLE,
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java
index 75ca1cd..c01ae7a 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java
@@ -34,10 +34,10 @@
     }
 
     static void bind(PropertyModel model, ViewHolder view, PropertyKey propertyKey) {
-        if (BottomControlsProperties.ANDROID_VIEW_HEIGHT == propertyKey) {
-            View bottomControlsView = view.root.findViewById(R.id.bottom_container_slot);
-            bottomControlsView.getLayoutParams().height =
-                    model.get(BottomControlsProperties.ANDROID_VIEW_HEIGHT);
+        if (BottomControlsProperties.BOTTOM_CONTROLS_CONTAINER_HEIGHT_PX == propertyKey) {
+            View bottomControlsWrapper = view.root.findViewById(R.id.bottom_controls_wrapper);
+            bottomControlsWrapper.getLayoutParams().height =
+                    model.get(BottomControlsProperties.BOTTOM_CONTROLS_CONTAINER_HEIGHT_PX);
         } else if (BottomControlsProperties.Y_OFFSET == propertyKey) {
             view.sceneLayer.setYOffset(model.get(BottomControlsProperties.Y_OFFSET));
         } else if (BottomControlsProperties.ANDROID_VIEW_TRANSLATE_Y == propertyKey) {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
index e0afc4d..d291fdfc 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
@@ -147,7 +147,8 @@
     private Drawable getTempTabStripDrawable(boolean incognito) {
         Drawable bgdColor =
                 new ColorDrawable(
-                        TabUiThemeUtil.getTabStripBackgroundColor(getContext(), incognito));
+                        TabUiThemeUtil.getTabStripBackgroundColor(
+                                getContext(), incognito, /* isActivityFocused= */ true));
         Drawable bdgTabImage =
                 ResourcesCompat.getDrawable(
                         getContext().getResources(),
diff --git a/chrome/browser/ui/autofill/autofill_context_menu_manager.cc b/chrome/browser/ui/autofill/autofill_context_menu_manager.cc
index 05edda6b..e60d14f2 100644
--- a/chrome/browser/ui/autofill/autofill_context_menu_manager.cc
+++ b/chrome/browser/ui/autofill/autofill_context_menu_manager.cc
@@ -352,27 +352,30 @@
 void AutofillContextMenuManager::LogManualFallbackContextMenuEntryAccepted(
     BrowserAutofillManager& manager,
     const FillingProduct filling_product) {
-  if (filling_product == FillingProduct::kAddress) {
     auto& driver = static_cast<ContentAutofillDriver&>(manager.driver());
     AutofillField* field = GetAutofillField(manager, driver.GetFrameToken());
-    const bool is_address_field =
-        field && IsAddressType(field->Type().GetStorableType());
-    if (is_address_field) {
-      // Address manual fallback was triggered from a classified address field.
-      manager.GetAutocompleteUnrecognizedFallbackEventLogger()
-          .ContextMenuEntryAccepted(
-              /*address_field_has_ac_unrecognized=*/field
-                  ->ShouldSuppressSuggestionsAndFillingByDefault());
-    } else {
+    if (filling_product == FillingProduct::kAddress) {
+      const bool is_address_field =
+          field && IsAddressType(field->Type().GetStorableType());
+      if (is_address_field) {
+        // Address manual fallback was triggered from a classified address
+        // field.
+        manager.GetAutocompleteUnrecognizedFallbackEventLogger()
+            .ContextMenuEntryAccepted(
+                /*address_field_has_ac_unrecognized=*/field
+                    ->ShouldSuppressSuggestionsAndFillingByDefault());
+      } else {
+        manager.GetManualFallbackEventLogger().ContextMenuEntryAccepted(
+            FillingProduct::kAddress);
+      }
+    } else if (filling_product == FillingProduct::kCreditCard &&
+               !(field &&
+                 field->Type().group() == FieldTypeGroup::kCreditCard)) {
+      // Only log payments manual fallback when triggered from a field that is
+      // not classified as payments.
       manager.GetManualFallbackEventLogger().ContextMenuEntryAccepted(
-          FillingProduct::kAddress);
+          FillingProduct::kCreditCard);
     }
-  } else if (filling_product == FillingProduct::kCreditCard) {
-    // Only log payments manual fallback when triggered from a field that is
-    // not classified as payments.
-    manager.GetManualFallbackEventLogger().ContextMenuEntryAccepted(
-        FillingProduct::kCreditCard);
-  }
 }
 
 void AutofillContextMenuManager::LogManualFallbackContextMenuEntryShown(
diff --git a/chrome/browser/ui/autofill/autofill_context_menu_manager_browsertest.cc b/chrome/browser/ui/autofill/autofill_context_menu_manager_browsertest.cc
index 76a6dbfb..47c0cd9a 100644
--- a/chrome/browser/ui/autofill/autofill_context_menu_manager_browsertest.cc
+++ b/chrome/browser/ui/autofill/autofill_context_menu_manager_browsertest.cc
@@ -676,7 +676,6 @@
              .is_field_unclassified = true,
              .test_name = "UnclassifiedField_Payments_NotAccepted",
          },
-
          {
              .manual_fallback_option =
                  AutofillSuggestionTriggerSource::kManualFallbackAddress,
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc
index 8a0ad31..c2a8c4d 100644
--- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc
@@ -95,7 +95,7 @@
 }
 
 AutofillBubbleBase*
-VirtualCardEnrollBubbleControllerImpl::GetVirtualCardEnrollBubbleView() const {
+VirtualCardEnrollBubbleControllerImpl::GetVirtualCardBubbleView() const {
   return bubble_view();
 }
 
@@ -111,6 +111,10 @@
   return enrollment_status_ == EnrollmentStatus::kPaymentsServerRequestInFlight;
 }
 
+bool VirtualCardEnrollBubbleControllerImpl::IsEnrollmentComplete() const {
+  return enrollment_status_ == EnrollmentStatus::kCompleted;
+}
+
 void VirtualCardEnrollBubbleControllerImpl::ShowConfirmationBubbleView(
     bool is_vcn_enrolled) {
   HideIconAndBubble();
@@ -366,6 +370,13 @@
   // sure further OnVisibilityChanged() don't trigger opening the bubble because
   // we don't want to re-show it every time the web contents become visible.
   bubble_state_ = BubbleState::kShowingIcon;
+
+  // Metrics for showing virtual card enroll bubble are logged once when
+  // enrollment is offered, do not log the same metrics again while showing
+  // confirmation bubble.
+  if (enrollment_status_ == EnrollmentStatus::kCompleted) {
+    return;
+  }
 #endif  // BUILDFLAG(IS_ANDROID)
 
   // If the dialog is to be shown again because user clicked on links, do not
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h
index 78cb96fd..eae63d4 100644
--- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h
+++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h
@@ -54,11 +54,12 @@
   const VirtualCardEnrollUiModel& GetUiModel() const override;
   VirtualCardEnrollmentBubbleSource GetVirtualCardEnrollmentBubbleSource()
       const override;
-  AutofillBubbleBase* GetVirtualCardEnrollBubbleView() const override;
+  AutofillBubbleBase* GetVirtualCardBubbleView() const override;
 
 #if !BUILDFLAG(IS_ANDROID)
   void HideIconAndBubble() override;
   bool IsEnrollmentInProgress() const override;
+  bool IsEnrollmentComplete() const override;
   virtual void ShowConfirmationBubbleView(bool is_vcn_enrolled);
 #endif
 
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_test_api.h b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_test_api.h
index b0f822b2..d297029 100644
--- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_test_api.h
+++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_test_api.h
@@ -26,14 +26,14 @@
         bubble_shown_closure_for_testing;
   }
 
+  void SetFields(const VirtualCardEnrollmentFields& fields) {
+    controller_->ui_model_.enrollment_fields = fields;
+  }
+
 #if BUILDFLAG(IS_ANDROID)
   bool DidShowBottomSheet() {
     return !!controller_->autofill_vcn_enroll_bottom_sheet_bridge_;
   }
-
-  void SetFields(const VirtualCardEnrollmentFields& fields) {
-    controller_->ui_model_.enrollment_fields = fields;
-  }
 #else
   VirtualCardEnrollBubbleControllerImpl::EnrollmentStatus
   GetEnrollmentStatus() {
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc
index e0f92df..27294d5 100644
--- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc
+++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc
@@ -172,7 +172,7 @@
   }
 
   AutofillBubbleBase* GetBubbleViews() {
-    return controller()->GetVirtualCardEnrollBubbleView();
+    return controller()->GetVirtualCardBubbleView();
   }
 
   const VirtualCardEnrollmentFields& virtual_card_enrollment_fields() const {
diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h
index 86443a5d..7ac8ab2c 100644
--- a/chrome/browser/ui/color/chrome_color_id.h
+++ b/chrome/browser/ui/color/chrome_color_id.h
@@ -406,6 +406,16 @@
   E_CPONLY(kColorReadAnythingBackgroundDark) \
   E_CPONLY(kColorReadAnythingBackgroundLight) \
   E_CPONLY(kColorReadAnythingBackgroundYellow) \
+  E_CPONLY(kColorReadAnythingCurrentReadAloudHighlight) \
+  E_CPONLY(kColorReadAnythingCurrentReadAloudHighlightBlue) \
+  E_CPONLY(kColorReadAnythingCurrentReadAloudHighlightDark) \
+  E_CPONLY(kColorReadAnythingCurrentReadAloudHighlightLight) \
+  E_CPONLY(kColorReadAnythingCurrentReadAloudHighlightYellow) \
+  E_CPONLY(kColorReadAnythingFocusRingBackground) \
+  E_CPONLY(kColorReadAnythingFocusRingBackgroundBlue) \
+  E_CPONLY(kColorReadAnythingFocusRingBackgroundDark) \
+  E_CPONLY(kColorReadAnythingFocusRingBackgroundLight) \
+  E_CPONLY(kColorReadAnythingFocusRingBackgroundYellow) \
   E_CPONLY(kColorReadAnythingForeground) \
   E_CPONLY(kColorReadAnythingForegroundBlue) \
   E_CPONLY(kColorReadAnythingForegroundDark) \
@@ -441,21 +451,11 @@
   E_CPONLY(kColorReadAnythingLinkVisitedDark) \
   E_CPONLY(kColorReadAnythingLinkVisitedLight) \
   E_CPONLY(kColorReadAnythingLinkVisitedYellow) \
-  E_CPONLY(kColorReadAnythingFocusRingBackground) \
-  E_CPONLY(kColorReadAnythingFocusRingBackgroundBlue) \
-  E_CPONLY(kColorReadAnythingFocusRingBackgroundDark) \
-  E_CPONLY(kColorReadAnythingFocusRingBackgroundLight) \
-  E_CPONLY(kColorReadAnythingFocusRingBackgroundYellow) \
-  E_CPONLY(kColorCurrentReadAloudHighlight) \
-  E_CPONLY(kColorCurrentReadAloudHighlightBlue) \
-  E_CPONLY(kColorCurrentReadAloudHighlightDark) \
-  E_CPONLY(kColorCurrentReadAloudHighlightLight) \
-  E_CPONLY(kColorCurrentReadAloudHighlightYellow) \
-  E_CPONLY(kColorPreviousReadAloudHighlight) \
-  E_CPONLY(kColorPreviousReadAloudHighlightBlue) \
-  E_CPONLY(kColorPreviousReadAloudHighlightDark) \
-  E_CPONLY(kColorPreviousReadAloudHighlightLight) \
-  E_CPONLY(kColorPreviousReadAloudHighlightYellow) \
+  E_CPONLY(kColorReadAnythingPreviousReadAloudHighlight) \
+  E_CPONLY(kColorReadAnythingPreviousReadAloudHighlightBlue) \
+  E_CPONLY(kColorReadAnythingPreviousReadAloudHighlightDark) \
+  E_CPONLY(kColorReadAnythingPreviousReadAloudHighlightLight) \
+  E_CPONLY(kColorReadAnythingPreviousReadAloudHighlightYellow) \
   /* Realbox colors. */ \
   E_CPONLY(kColorRealboxAnswerIconBackground) \
   E_CPONLY(kColorRealboxAnswerIconForeground) \
diff --git a/chrome/browser/ui/color/chrome_color_mixer.cc b/chrome/browser/ui/color/chrome_color_mixer.cc
index 16b2e742..2dffc89 100644
--- a/chrome/browser/ui/color/chrome_color_mixer.cc
+++ b/chrome/browser/ui/color/chrome_color_mixer.cc
@@ -765,6 +765,17 @@
   // The Read Anything themes need to be hard coded because they do not
   // change with the chrome theme, which is the purpose of the Read Anything
   // feature.
+  mixer[kColorReadAnythingCurrentReadAloudHighlight] = {
+      dark_mode ? kColorReadAnythingCurrentReadAloudHighlightDark
+                : kColorReadAnythingCurrentReadAloudHighlightLight};
+  mixer[kColorReadAnythingCurrentReadAloudHighlightDark] = {
+      SkColorSetARGB(25, 253, 252, 251)};
+  mixer[kColorReadAnythingCurrentReadAloudHighlightLight] = {
+      SkColorSetARGB(15, 31, 31, 31)};
+  mixer[kColorReadAnythingCurrentReadAloudHighlightBlue] = {
+      SkColorSetARGB(15, 31, 31, 31)};
+  mixer[kColorReadAnythingCurrentReadAloudHighlightYellow] = {
+      SkColorSetARGB(15, 31, 31, 31)};
   mixer[kColorReadAnythingForeground] = {
       dark_mode ? kColorReadAnythingForegroundDark
                 : kColorReadAnythingForegroundLight};
@@ -772,23 +783,17 @@
   mixer[kColorReadAnythingForegroundDark] = {SkColorSetRGB(227, 227, 227)};
   mixer[kColorReadAnythingForegroundLight] = {SkColorSetRGB(31, 31, 31)};
   mixer[kColorReadAnythingForegroundYellow] = {SkColorSetRGB(31, 31, 31)};
-  mixer[kColorCurrentReadAloudHighlight] = {
-      dark_mode ? kColorCurrentReadAloudHighlightDark
-                : kColorCurrentReadAloudHighlightLight};
-  mixer[kColorCurrentReadAloudHighlightDark] = {
-      SkColorSetARGB(25, 253, 252, 251)};
-  mixer[kColorCurrentReadAloudHighlightLight] = {
-      SkColorSetARGB(15, 31, 31, 31)};
-  mixer[kColorCurrentReadAloudHighlightBlue] = {SkColorSetARGB(15, 31, 31, 31)};
-  mixer[kColorCurrentReadAloudHighlightYellow] = {
-      SkColorSetARGB(15, 31, 31, 31)};
-  mixer[kColorPreviousReadAloudHighlight] = {
-      dark_mode ? kColorPreviousReadAloudHighlightDark
-                : kColorPreviousReadAloudHighlightLight};
-  mixer[kColorPreviousReadAloudHighlightDark] = {SkColorSetRGB(199, 199, 199)};
-  mixer[kColorPreviousReadAloudHighlightLight] = {SkColorSetRGB(71, 71, 71)};
-  mixer[kColorPreviousReadAloudHighlightBlue] = {SkColorSetRGB(71, 71, 71)};
-  mixer[kColorPreviousReadAloudHighlightYellow] = {SkColorSetRGB(71, 71, 71)};
+  mixer[kColorReadAnythingPreviousReadAloudHighlight] = {
+      dark_mode ? kColorReadAnythingPreviousReadAloudHighlightDark
+                : kColorReadAnythingPreviousReadAloudHighlightLight};
+  mixer[kColorReadAnythingPreviousReadAloudHighlightDark] = {
+      SkColorSetRGB(199, 199, 199)};
+  mixer[kColorReadAnythingPreviousReadAloudHighlightLight] = {
+      SkColorSetRGB(71, 71, 71)};
+  mixer[kColorReadAnythingPreviousReadAloudHighlightBlue] = {
+      SkColorSetRGB(71, 71, 71)};
+  mixer[kColorReadAnythingPreviousReadAloudHighlightYellow] = {
+      SkColorSetRGB(71, 71, 71)};
   mixer[kColorReadAnythingSeparator] = {dark_mode
                                             ? kColorReadAnythingSeparatorDark
                                             : kColorReadAnythingSeparatorLight};
diff --git a/chrome/browser/ui/color/material_chrome_color_mixer.cc b/chrome/browser/ui/color/material_chrome_color_mixer.cc
index 7668f21b..9ba0003 100644
--- a/chrome/browser/ui/color/material_chrome_color_mixer.cc
+++ b/chrome/browser/ui/color/material_chrome_color_mixer.cc
@@ -114,9 +114,11 @@
   mixer[kColorSidePanelBackground] = {ui::kColorSysBaseContainer};
 
   // Read Anything (in the side panel) colors.
+  mixer[kColorReadAnythingCurrentReadAloudHighlight] = {
+      ui::kColorSysStateHoverOnSubtle};
   mixer[kColorReadAnythingForeground] = {ui::kColorSysOnSurface};
-  mixer[kColorCurrentReadAloudHighlight] = {ui::kColorSysStateHoverOnSubtle};
-  mixer[kColorPreviousReadAloudHighlight] = {ui::kColorSysOnSurfaceSecondary};
+  mixer[kColorReadAnythingPreviousReadAloudHighlight] = {
+      ui::kColorSysOnSurfaceSecondary};
 
   // Tab Group Dialog colors.
   mixer[kColorTabGroupDialogIconEnabled] = {ui::kColorSysOnSurfaceSubtle};
diff --git a/chrome/browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc b/chrome/browser/ui/quick_answers/quick_answers_controller_browsertest.cc
similarity index 81%
rename from chrome/browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc
rename to chrome/browser/ui/quick_answers/quick_answers_controller_browsertest.cc
index fb7cc04..67abaa5a 100644
--- a/chrome/browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc
+++ b/chrome/browser/ui/quick_answers/quick_answers_controller_browsertest.cc
@@ -10,11 +10,11 @@
 
 namespace {
 
-using QuickAnswersMenuObserverTest = quick_answers::QuickAnswersBrowserTestBase;
+using QuickAnswersControllerTest = quick_answers::QuickAnswersBrowserTestBase;
 
 }  // namespace
 
-IN_PROC_BROWSER_TEST_F(QuickAnswersMenuObserverTest, FeatureIneligible) {
+IN_PROC_BROWSER_TEST_F(QuickAnswersControllerTest, FeatureIneligible) {
   QuickAnswersState::Get()->set_eligibility_for_testing(false);
 
   ShowMenuParams params;
@@ -27,7 +27,7 @@
             controller()->GetVisibilityForTesting());
 }
 
-IN_PROC_BROWSER_TEST_F(QuickAnswersMenuObserverTest, PasswordField) {
+IN_PROC_BROWSER_TEST_F(QuickAnswersControllerTest, PasswordField) {
   QuickAnswersState::Get()->set_eligibility_for_testing(true);
 
   ShowMenuParams params;
@@ -42,7 +42,7 @@
             controller()->GetVisibilityForTesting());
 }
 
-IN_PROC_BROWSER_TEST_F(QuickAnswersMenuObserverTest, NoSelectedText) {
+IN_PROC_BROWSER_TEST_F(QuickAnswersControllerTest, NoSelectedText) {
   QuickAnswersState::Get()->set_eligibility_for_testing(true);
 
   ShowMenu(ShowMenuParams());
@@ -52,7 +52,7 @@
             controller()->GetVisibilityForTesting());
 }
 
-IN_PROC_BROWSER_TEST_F(QuickAnswersMenuObserverTest, QuickAnswersPending) {
+IN_PROC_BROWSER_TEST_F(QuickAnswersControllerTest, QuickAnswersPending) {
   QuickAnswersState::Get()->set_eligibility_for_testing(true);
 
   ShowMenuParams params;
diff --git a/chrome/browser/ui/views/autofill/payments/dialog_view_ids.h b/chrome/browser/ui/views/autofill/payments/dialog_view_ids.h
index c1f2a3fb..3eb7c7d2 100644
--- a/chrome/browser/ui/views/autofill/payments/dialog_view_ids.h
+++ b/chrome/browser/ui/views/autofill/payments/dialog_view_ids.h
@@ -65,6 +65,8 @@
   // The following are views::Label objects.
   EXPIRATION_DATE_LABEL,  // Appears during save offer bubble
   NICKNAME_LABEL,         // Appears during manage saved IBAN bubble.
+  DESCRIPTION_LABEL,      // Appears during save card and virtual card enroll
+                          // confirmation bubble.
 
   // The following are views::StyledLabel objects.
   SETTINGS_LABEL,  // Appears in the mandatory reauth opt-in confirmation
@@ -72,7 +74,9 @@
 
   // The following are views::Throbber objects.
   LOADING_THROBBER,  // Appears during server card upload in save card offer
-                     // bubble.
+                     // bubble and during ongoing enrollment in virtual card
+                     //  enroll bubble.
+
 };
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views.cc
index 5fda0a9..877d31d 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views.cc
@@ -6,7 +6,11 @@
 
 #include <utility>
 
+#include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/ui/views/accessibility/theme_tracking_non_accessible_image_view.h"
+#include "chrome/browser/ui/views/autofill/payments/dialog_view_ids.h"
 #include "chrome/browser/ui/views/autofill/payments/payments_view_util.h"
+#include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "ui/base/ui_base_types.h"
 
 namespace autofill {
@@ -21,8 +25,13 @@
     : LocationBarBubbleDelegateView(anchor_view, web_contents),
       controller_hide_callback_(std::move(controller_hide_callback)),
       ui_params_(std::move(ui_params)) {
-  SetButtons(ui::DIALOG_BUTTON_NONE);
-  SetShowCloseButton(true);
+  if (ui_params_.is_success) {
+    SetButtons(ui::DIALOG_BUTTON_NONE);
+    SetShowCloseButton(true);
+  } else {
+    SetButtons(ui::DIALOG_BUTTON_OK);
+    SetButtonLabel(ui::DIALOG_BUTTON_OK, ui_params_.failure_button_text);
+  }
   set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
       views::DISTANCE_BUBBLE_PREFERRED_WIDTH));
 }
@@ -35,6 +44,29 @@
   }
 }
 
+void SaveCardAndVirtualCardEnrollConfirmationBubbleViews::AddedToWidget() {
+  if (ui_params_.is_success) {
+    auto image_view = std::make_unique<ThemeTrackingNonAccessibleImageView>(
+        ui::ImageModel::FromVectorIcon(kSaveCardAndVcnSuccessConfirmationIcon),
+        ui::ImageModel::FromVectorIcon(
+            kSaveCardAndVcnSuccessConfirmationDarkIcon),
+        base::BindRepeating(&views::BubbleDialogDelegate::GetBackgroundColor,
+                            base::Unretained(this)));
+    image_view->SetBorder(
+        views::CreateEmptyBorder(ChromeLayoutProvider::Get()
+                                     ->GetInsetsMetric(views::INSETS_DIALOG)
+                                     .set_bottom(0)));
+    GetBubbleFrameView()->SetHeaderView(std::move(image_view));
+  }
+  GetBubbleFrameView()->SetTitleView(CreateTitleView(
+      GetWindowTitle(), TitleWithIconAndSeparatorView::Icon::GOOGLE_PAY));
+}
+
+std::u16string
+SaveCardAndVirtualCardEnrollConfirmationBubbleViews::GetWindowTitle() const {
+  return ui_params_.title_text;
+}
+
 void SaveCardAndVirtualCardEnrollConfirmationBubbleViews::WindowClosing() {
   if (!controller_hide_callback_.is_null()) {
     std::move(controller_hide_callback_)
@@ -42,6 +74,20 @@
   }
 }
 
+void SaveCardAndVirtualCardEnrollConfirmationBubbleViews::Init() {
+  SetLayoutManager(std::make_unique<views::BoxLayout>(
+      views::BoxLayout::Orientation::kVertical));
+  set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
+      views::DialogContentType::kText, views::DialogContentType::kText));
+  auto description = std::make_unique<views::Label>(
+      ui_params_.description_text, views::style::CONTEXT_DIALOG_BODY_TEXT,
+      views::style::STYLE_SECONDARY);
+  description->SetID(DialogViewId::DESCRIPTION_LABEL);
+  description->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  description->SetMultiLine(true);
+  AddChildView(std::move(description));
+}
+
 SaveCardAndVirtualCardEnrollConfirmationBubbleViews::
     ~SaveCardAndVirtualCardEnrollConfirmationBubbleViews() = default;
 
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views.h b/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views.h
index f0ad4aa1..ae69fde 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views.h
+++ b/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_SAVE_CARD_AND_VIRTUAL_CARD_ENROLL_CONFIRMATION_BUBBLE_VIEWS_H_
 #define CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_SAVE_CARD_AND_VIRTUAL_CARD_ENROLL_CONFIRMATION_BUBBLE_VIEWS_H_
 
-#include "base/gtest_prod_util.h"
 #include "chrome/browser/ui/autofill/autofill_bubble_base.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
 #include "components/autofill/core/browser/ui/payments/payments_bubble_closed_reasons.h"
@@ -35,18 +34,15 @@
   void Hide() override;
 
   // LocationBarBubbleDelegateView:
+  void AddedToWidget() override;
+  std::u16string GetWindowTitle() const override;
   void WindowClosing() override;
 
  private:
   ~SaveCardAndVirtualCardEnrollConfirmationBubbleViews() override;
 
-  // TODO(crbug.com/1499264): FRIEND_TEST is only temporary and should be
-  // removed after the UI elements are actually implemented into the view and
-  // can be tested.
-  FRIEND_TEST_ALL_PREFIXES(SaveCardConfirmationBubbleViewsInteractiveUiTest,
-                           ShowSuccessBubbleViewThenHideBubbleView);
-  FRIEND_TEST_ALL_PREFIXES(SaveCardConfirmationBubbleViewsInteractiveUiTest,
-                           ShowFailureBubbleViewThenHideBubbleView);
+  // LocationBarBubbleDelegateView:
+  void Init() override;
 
   base::OnceCallback<void(PaymentsBubbleClosedReason)>
       controller_hide_callback_;
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views_interactive_uitest.cc b/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views_interactive_uitest.cc
index a7a6ecf..1ad532c7 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views_interactive_uitest.cc
+++ b/chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views_interactive_uitest.cc
@@ -3,10 +3,14 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h"
+
+#include "chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_test_api.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/views/autofill/payments/dialog_view_ids.h"
 #include "chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views.h"
 #include "chrome/browser/ui/views/autofill/payments/save_card_bubble_views.h"
 #include "chrome/browser/ui/views/autofill/payments/save_payment_icon_view.h"
+#include "chrome/browser/ui/views/autofill/payments/virtual_card_enroll_icon_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -38,7 +42,7 @@
     CHECK(save_card_controller);
   }
 
-  SaveCardBubbleControllerImpl* Controller() {
+  SaveCardBubbleControllerImpl* GetController() {
     if (!browser() || !browser()->tab_strip_model() ||
         !browser()->tab_strip_model()->GetActiveWebContents()) {
       return nullptr;
@@ -50,7 +54,7 @@
 
   SaveCardAndVirtualCardEnrollConfirmationBubbleViews* BubbleView() {
     return static_cast<SaveCardAndVirtualCardEnrollConfirmationBubbleViews*>(
-        Controller()->GetPaymentBubbleView());
+        GetController()->GetPaymentBubbleView());
   }
 
   SavePaymentIconView* IconView() {
@@ -64,7 +68,7 @@
   }
 
   void ShowBubble(bool card_saved) {
-    Controller()->ShowConfirmationBubbleView(card_saved);
+    GetController()->ShowConfirmationBubbleView(card_saved);
   }
 
   void HideBubble(views::Widget::ClosedReason closed_reason) {
@@ -83,19 +87,27 @@
 IN_PROC_BROWSER_TEST_F(SaveCardConfirmationBubbleViewsInteractiveUiTest,
                        ShowSuccessBubbleViewThenHideBubbleView) {
   ShowBubble(/*card_saved=*/true);
-  EXPECT_NE(BubbleView(), nullptr);
-  EXPECT_TRUE(IconView()->GetVisible());
 
-  SaveCardAndVirtualCardEnrollConfirmationUiParams ui_params =
-      BubbleView()->ui_params_;
-  EXPECT_TRUE(ui_params.is_success);
-  EXPECT_EQ(ui_params.title_text,
+  EXPECT_NE(BubbleView(), nullptr);
+
+  EXPECT_TRUE(BubbleView()->ShouldShowCloseButton());
+  EXPECT_TRUE(BubbleView()
+                  ->GetBubbleFrameView()
+                  ->GetHeaderViewForTesting()
+                  ->GetVisible());
+  EXPECT_NE(BubbleView()->GetBubbleFrameView()->title(), nullptr);
+  EXPECT_EQ(BubbleView()->GetWindowTitle(),
             l10n_util::GetStringUTF16(
                 IDS_AUTOFILL_SAVE_CARD_CONFIRMATION_SUCCESS_TITLE_TEXT));
-  EXPECT_EQ(ui_params.description_text,
+  EXPECT_TRUE(
+      BubbleView()->GetViewByID(DialogViewId::DESCRIPTION_LABEL)->GetVisible());
+  EXPECT_EQ(static_cast<views::Label*>(
+                BubbleView()->GetViewByID(DialogViewId::DESCRIPTION_LABEL))
+                ->GetText(),
             l10n_util::GetStringUTF16(
                 IDS_AUTOFILL_SAVE_CARD_CONFIRMATION_SUCCESS_DESCRIPTION_TEXT));
-  EXPECT_TRUE(ui_params.failure_button_text.empty());
+  EXPECT_EQ(BubbleView()->GetDialogButtons(), ui::DIALOG_BUTTON_NONE);
+  EXPECT_TRUE(IconView()->GetVisible());
 
   HideBubble(views::Widget::ClosedReason::kLostFocus);
   EXPECT_EQ(BubbleView(), nullptr);
@@ -105,26 +117,160 @@
 IN_PROC_BROWSER_TEST_F(SaveCardConfirmationBubbleViewsInteractiveUiTest,
                        ShowFailureBubbleViewThenHideBubbleView) {
   ShowBubble(/*card_saved=*/false);
-  EXPECT_NE(BubbleView(), nullptr);
-  EXPECT_TRUE(IconView()->GetVisible());
 
-  SaveCardAndVirtualCardEnrollConfirmationUiParams ui_params =
-      BubbleView()->ui_params_;
-  EXPECT_FALSE(ui_params.is_success);
-  EXPECT_EQ(ui_params.title_text,
+  EXPECT_NE(BubbleView(), nullptr);
+  EXPECT_FALSE(BubbleView()->ShouldShowCloseButton());
+  EXPECT_EQ(BubbleView()->GetBubbleFrameView()->GetHeaderViewForTesting(),
+            nullptr);
+  EXPECT_NE(BubbleView()->GetBubbleFrameView()->title(), nullptr);
+  EXPECT_EQ(BubbleView()->GetWindowTitle(),
             l10n_util::GetStringUTF16(
                 IDS_AUTOFILL_SAVE_CARD_CONFIRMATION_FAILURE_TITLE_TEXT));
-  EXPECT_EQ(ui_params.description_text,
+  EXPECT_TRUE(
+      BubbleView()->GetViewByID(DialogViewId::DESCRIPTION_LABEL)->GetVisible());
+  EXPECT_EQ(static_cast<views::Label*>(
+                BubbleView()->GetViewByID(DialogViewId::DESCRIPTION_LABEL))
+                ->GetText(),
             l10n_util::GetStringUTF16(
                 IDS_AUTOFILL_SAVE_CARD_CONFIRMATION_FAILURE_DESCRIPTION_TEXT));
+  EXPECT_EQ(BubbleView()->GetDialogButtons(), ui::DIALOG_BUTTON_OK);
   EXPECT_EQ(
-      ui_params.failure_button_text,
+      BubbleView()->GetDialogButtonLabel(ui::DIALOG_BUTTON_OK),
       l10n_util::GetStringUTF16(
           IDS_AUTOFILL_SAVE_CARD_AND_VIRTUAL_CARD_ENROLL_CONFIRMATION_FAILURE_BUTTON_TEXT));
+  EXPECT_TRUE(IconView()->GetVisible());
 
   HideBubble(views::Widget::ClosedReason::kLostFocus);
   EXPECT_EQ(BubbleView(), nullptr);
   EXPECT_FALSE(IconView()->GetVisible());
 }
 
+class VirtualCardEnrollConfirmationBubbleViewsInteractiveUiTest
+    : public InProcessBrowserTest {
+ public:
+  VirtualCardEnrollConfirmationBubbleViewsInteractiveUiTest() = default;
+  ~VirtualCardEnrollConfirmationBubbleViewsInteractiveUiTest() override =
+      default;
+  VirtualCardEnrollConfirmationBubbleViewsInteractiveUiTest(
+      const VirtualCardEnrollConfirmationBubbleViewsInteractiveUiTest&) =
+      delete;
+  VirtualCardEnrollConfirmationBubbleViewsInteractiveUiTest& operator=(
+      const VirtualCardEnrollConfirmationBubbleViewsInteractiveUiTest&) =
+      delete;
+
+  // InProcessBrowserTest:
+  void SetUpOnMainThread() override {
+    VirtualCardEnrollBubbleControllerImpl* virtual_card_enroll_controller =
+        static_cast<VirtualCardEnrollBubbleControllerImpl*>(
+            VirtualCardEnrollBubbleControllerImpl::GetOrCreate(
+                browser()->tab_strip_model()->GetActiveWebContents()));
+    CHECK(virtual_card_enroll_controller);
+  }
+
+  VirtualCardEnrollBubbleControllerImpl* GetController() {
+    if (!browser() || !browser()->tab_strip_model() ||
+        !browser()->tab_strip_model()->GetActiveWebContents()) {
+      return nullptr;
+    }
+
+    return VirtualCardEnrollBubbleControllerImpl::FromWebContents(
+        browser()->tab_strip_model()->GetActiveWebContents());
+  }
+
+  SaveCardAndVirtualCardEnrollConfirmationBubbleViews* BubbleView() {
+    return static_cast<SaveCardAndVirtualCardEnrollConfirmationBubbleViews*>(
+        GetController()->GetVirtualCardBubbleView());
+  }
+
+  VirtualCardEnrollIconView* IconView() {
+    BrowserView* browser_view =
+        BrowserView::GetBrowserViewForBrowser(browser());
+    PageActionIconView* icon =
+        browser_view->toolbar_button_provider()->GetPageActionIconView(
+            PageActionIconType::kVirtualCardEnroll);
+    CHECK(icon);
+    return static_cast<VirtualCardEnrollIconView*>(icon);
+  }
+
+  void ShowBubble(bool is_vcn_enrolled) {
+    GetController()->ShowConfirmationBubbleView(is_vcn_enrolled);
+  }
+
+ private:
+  test::AutofillBrowserTestEnvironment autofill_test_environment_;
+  base::test::ScopedFeatureList feature_list_{
+      features::kAutofillEnableVcnEnrollLoadingAndConfirmation};
+};
+
+IN_PROC_BROWSER_TEST_F(
+    VirtualCardEnrollConfirmationBubbleViewsInteractiveUiTest,
+    ShowSuccessBubbleViewThenHideBubbleView) {
+  ShowBubble(/*is_vcn_enrolled=*/true);
+
+  EXPECT_NE(BubbleView(), nullptr);
+  EXPECT_TRUE(BubbleView()->ShouldShowCloseButton());
+  EXPECT_TRUE(BubbleView()
+                  ->GetBubbleFrameView()
+                  ->GetHeaderViewForTesting()
+                  ->GetVisible());
+  EXPECT_NE(BubbleView()->GetBubbleFrameView()->title(), nullptr);
+  EXPECT_EQ(
+      BubbleView()->GetWindowTitle(),
+      l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CONFIRMATION_SUCCESS_TITLE_TEXT));
+  EXPECT_TRUE(
+      BubbleView()->GetViewByID(DialogViewId::DESCRIPTION_LABEL)->GetVisible());
+  EXPECT_EQ(
+      static_cast<views::Label*>(
+          BubbleView()->GetViewByID(DialogViewId::DESCRIPTION_LABEL))
+          ->GetText(),
+      l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CONFIRMATION_SUCCESS_DESCRIPTION_TEXT));
+  EXPECT_EQ(BubbleView()->GetDialogButtons(), ui::DIALOG_BUTTON_NONE);
+  EXPECT_TRUE(IconView()->GetVisible());
+
+  GetController()->HideIconAndBubble();
+  EXPECT_EQ(BubbleView(), nullptr);
+  EXPECT_FALSE(IconView()->GetVisible());
+}
+
+IN_PROC_BROWSER_TEST_F(
+    VirtualCardEnrollConfirmationBubbleViewsInteractiveUiTest,
+    ShowFailureBubbleViewThenHideBubbleView) {
+  CreditCard card = test::GetCreditCard();
+  VirtualCardEnrollmentFields enrollment_fields;
+  enrollment_fields.credit_card = card;
+  test_api(GetController()).SetFields(enrollment_fields);
+  ShowBubble(/*is_vcn_enrolled=*/false);
+
+  EXPECT_NE(BubbleView(), nullptr);
+  EXPECT_FALSE(BubbleView()->ShouldShowCloseButton());
+  EXPECT_EQ(BubbleView()->GetBubbleFrameView()->GetHeaderViewForTesting(),
+            nullptr);
+  EXPECT_NE(BubbleView()->GetBubbleFrameView()->title(), nullptr);
+  EXPECT_EQ(
+      BubbleView()->GetWindowTitle(),
+      l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CONFIRMATION_FAILURE_TITLE_TEXT));
+  EXPECT_TRUE(
+      BubbleView()->GetViewByID(DialogViewId::DESCRIPTION_LABEL)->GetVisible());
+  EXPECT_EQ(
+      static_cast<views::Label*>(
+          BubbleView()->GetViewByID(DialogViewId::DESCRIPTION_LABEL))
+          ->GetText(),
+      l10n_util::GetStringFUTF16(
+          IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CONFIRMATION_FAILURE_DESCRIPTION_TEXT,
+          card.NetworkAndLastFourDigits()));
+  EXPECT_EQ(BubbleView()->GetDialogButtons(), ui::DIALOG_BUTTON_OK);
+  EXPECT_EQ(
+      BubbleView()->GetDialogButtonLabel(ui::DIALOG_BUTTON_OK),
+      l10n_util::GetStringUTF16(
+          IDS_AUTOFILL_SAVE_CARD_AND_VIRTUAL_CARD_ENROLL_CONFIRMATION_FAILURE_BUTTON_TEXT));
+  EXPECT_TRUE(IconView()->GetVisible());
+
+  GetController()->HideIconAndBubble();
+  EXPECT_EQ(BubbleView(), nullptr);
+  EXPECT_FALSE(IconView()->GetVisible());
+}
+
 }  // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc
index 2e0cb61..0843bba 100644
--- a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc
+++ b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc
@@ -132,7 +132,7 @@
     }
 
     return static_cast<VirtualCardEnrollBubbleViews*>(
-        controller->GetVirtualCardEnrollBubbleView());
+        controller->GetVirtualCardBubbleView());
   }
 
   void ClickLearnMoreLink() { GetBubbleViews()->LearnMoreLinkClicked(); }
diff --git a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_icon_view.cc b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_icon_view.cc
index 35648f4fb..0d9a0a4 100644
--- a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_icon_view.cc
+++ b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_icon_view.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/view_ids.h"
+#include "chrome/browser/ui/views/autofill/payments/save_card_and_virtual_card_enroll_confirmation_bubble_views.h"
 #include "chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h"
@@ -45,8 +46,19 @@
     return nullptr;
   }
 
+  // Checking controller's `enrollment_status_` is `kCompleted` ensures that
+  // the bubble view returned is of the type
+  // `SaveCardAndVirtualCardEnrollConfirmationBubbleViews` since controller
+  // hides the `VirtualCardEnrollBubbleViews` once the enrollment completes to
+  // show the confirmation bubble.
+  if (controller->IsEnrollmentComplete()) {
+    return static_cast<
+        autofill::SaveCardAndVirtualCardEnrollConfirmationBubbleViews*>(
+        controller->GetVirtualCardBubbleView());
+  }
+
   return static_cast<autofill::VirtualCardEnrollBubbleViews*>(
-      controller->GetVirtualCardEnrollBubbleView());
+      controller->GetVirtualCardBubbleView());
 }
 
 void VirtualCardEnrollIconView::UpdateImpl() {
diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
index abd54f3c..6cda02b 100644
--- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
+++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
@@ -337,13 +337,15 @@
       sheet_view = std::make_unique<AuthenticatorGpmPinSheetView>(
           std::make_unique<AuthenticatorGPMPinSheetModel>(
               dialog_model, kPinDigitCount,
-              AuthenticatorGPMPinSheetModel::Mode::kPinCreate));
+              AuthenticatorGPMPinSheetModel::Mode::kPinCreate,
+              dialog_model->gpm_pin_error()));
       break;
     case Step::kGPMEnterPin:
       sheet_view = std::make_unique<AuthenticatorGpmPinSheetView>(
           std::make_unique<AuthenticatorGPMPinSheetModel>(
               dialog_model, kPinDigitCount,
-              AuthenticatorGPMPinSheetModel::Mode::kPinEntry));
+              AuthenticatorGPMPinSheetModel::Mode::kPinEntry,
+              dialog_model->gpm_pin_error()));
       break;
     case Step::kNotStarted:
     case Step::kConditionalMediation:
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc
index fbde0a3..9631aea 100644
--- a/chrome/browser/ui/webauthn/sheet_models.cc
+++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -1585,11 +1585,13 @@
 AuthenticatorGPMPinSheetModel::AuthenticatorGPMPinSheetModel(
     AuthenticatorRequestDialogModel* dialog_model,
     int pin_digits_count,
-    Mode mode)
+    Mode mode,
+    AuthenticatorRequestDialogModel::GpmPinError error)
     : AuthenticatorSheetModelBase(dialog_model,
                                   OtherMechanismButtonVisibility::kHidden),
       pin_digits_count_(pin_digits_count),
-      mode_(mode) {
+      mode_(mode),
+      error_(error) {
   // TODO(rgod): Add correct illustration.
   vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
 }
@@ -1628,6 +1630,15 @@
   }
 }
 
+std::u16string AuthenticatorGPMPinSheetModel::GetError() const {
+  switch (error_) {
+    case AuthenticatorRequestDialogModel::GpmPinError::kNone:
+      return std::u16string();
+    case AuthenticatorRequestDialogModel::GpmPinError::kWrongPin:
+      return u"Wrong PIN (UNTRANSLATED)";
+  }
+}
+
 bool AuthenticatorGPMPinSheetModel::IsAcceptButtonVisible() const {
   return true;
 }
diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h
index d561931..1f22f49 100644
--- a/chrome/browser/ui/webauthn/sheet_models.h
+++ b/chrome/browser/ui/webauthn/sheet_models.h
@@ -688,7 +688,8 @@
   explicit AuthenticatorGPMPinSheetModel(
       AuthenticatorRequestDialogModel* dialog_model,
       int pin_digits_count,
-      Mode mode);
+      Mode mode,
+      AuthenticatorRequestDialogModel::GpmPinError error);
   ~AuthenticatorGPMPinSheetModel() override;
 
   int pin_digits_count() const;
@@ -700,6 +701,7 @@
   // AuthenticatorSheetModelBase:
   std::u16string GetStepTitle() const override;
   std::u16string GetStepDescription() const override;
+  std::u16string GetError() const override;
   bool IsAcceptButtonEnabled() const override;
   bool IsAcceptButtonVisible() const override;
   std::u16string GetAcceptButtonLabel() const override;
@@ -708,6 +710,7 @@
   std::u16string pin_;
   const int pin_digits_count_;
   const Mode mode_;
+  const AuthenticatorRequestDialogModel::GpmPinError error_;
 };
 
 #endif  // CHROME_BROWSER_UI_WEBAUTHN_SHEET_MODELS_H_
diff --git a/chrome/browser/ui/webui/downloads/downloads.mojom b/chrome/browser/ui/webui/downloads/downloads.mojom
index 8c882e1..861a51d 100644
--- a/chrome/browser/ui/webui/downloads/downloads.mojom
+++ b/chrome/browser/ui/webui/downloads/downloads.mojom
@@ -145,6 +145,7 @@
   Cancel(string id);
   ClearAll();
   OpenDownloadsFolderRequiringGesture();
+  OpenEsbSettings();
 
   // Opens this download with the given |id| while it is being scanned by Safe
   // Browsing. This completes the scan early. This requires a user gesture on
diff --git a/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc b/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
index 64272499..d6be3fac 100644
--- a/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
+++ b/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/hats/trust_safety_sentiment_service.h"
 #include "chrome/browser/ui/hats/trust_safety_sentiment_service_factory.h"
 #include "chrome/browser/ui/webui/downloads/downloads.mojom.h"
@@ -51,6 +52,7 @@
 #include "components/prefs/pref_service.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/safebrowsing_referral_methods.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/download_item_utils.h"
 #include "content/public/browser/download_manager.h"
@@ -776,3 +778,13 @@
   downloads.push_back(file);
   RemoveDownloads(downloads);
 }
+
+void DownloadsDOMHandler::OpenEsbSettings() {
+  Browser* browser = chrome::FindBrowserWithTab(GetWebUIWebContents());
+  if (!browser) {
+    return;
+  }
+  chrome::ShowSafeBrowsingEnhancedProtectionWithIph(
+      browser,
+      safe_browsing::SafeBrowsingSettingReferralMethod::kDownloadPageRowPromo);
+}
diff --git a/chrome/browser/ui/webui/downloads/downloads_dom_handler.h b/chrome/browser/ui/webui/downloads/downloads_dom_handler.h
index ca99647..f8c1b5b 100644
--- a/chrome/browser/ui/webui/downloads/downloads_dom_handler.h
+++ b/chrome/browser/ui/webui/downloads/downloads_dom_handler.h
@@ -74,6 +74,7 @@
   void ReviewDangerousRequiringGesture(const std::string& id) override;
   void DeepScan(const std::string& id) override;
   void BypassDeepScanRequiringGesture(const std::string& id) override;
+  void OpenEsbSettings() override;
 
  protected:
   // These methods are for mocking so that most of this class does not actually
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
index 4bb30889..2f57dcaa 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -678,10 +678,15 @@
       profile_->GetPrefs()->IsManagedPreference(prefs::kNtpModulesVisible));
   source->AddBoolean("customizeChromeEnabled",
                      customize_chrome::IsSidePanelEnabled());
-  source->AddBoolean(
-      "wallpaperSearchButtonEnabled",
+  bool wallpaper_search_button_enabled =
       base::FeatureList::IsEnabled(ntp_features::kNtpWallpaperSearchButton) &&
-          customize_chrome::IsWallpaperSearchEnabledForProfile(profile_));
+      customize_chrome::IsWallpaperSearchEnabledForProfile(profile_);
+  source->AddBoolean("wallpaperSearchButtonEnabled",
+                     wallpaper_search_button_enabled);
+  source->AddBoolean("wallpaperSearchButtonAnimationEnabled",
+                     wallpaper_search_button_enabled &&
+                         base::FeatureList::IsEnabled(
+                             ntp_features::kNtpWallpaperSearchButtonAnimation));
 
   content::URLDataSource::Add(profile_,
                               std::make_unique<SanitizedImageSource>(profile_));
diff --git a/chrome/browser/ui/webui/tab_search/tab_search.mojom b/chrome/browser/ui/webui/tab_search/tab_search.mojom
index b961f16b..c639bbdc 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search.mojom
+++ b/chrome/browser/ui/webui/tab_search/tab_search.mojom
@@ -230,6 +230,9 @@
   // Remove the tab from the tab organization.
   RemoveTabFromOrganization(int32 session_id, int32 organization_id, Tab tab);
 
+  // Reject all tab organizations in the current session.
+  RejectSession(int32 session_id);
+
   // Clear the current tab organization session state and start a new request.
   RestartSession();
 
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
index 595a28b..a0cf4701 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
@@ -484,6 +484,27 @@
   }
 }
 
+void TabSearchPageHandler::RejectSession(int32_t session_id) {
+  Browser* browser = chrome::FindLastActive();
+  if (!browser || !organization_service_) {
+    return;
+  }
+
+  TabOrganizationSession* session =
+      organization_service_->GetSessionForBrowser(browser);
+  if (!session || session->session_id() != session_id) {
+    return;
+  }
+
+  for (const std::unique_ptr<TabOrganization>& organization :
+       session->tab_organizations()) {
+    organization->Reject();
+  }
+
+  organization_service_->ResetSessionForBrowser(
+      browser, TabOrganizationEntryPoint::kTabSearch, nullptr);
+}
+
 void TabSearchPageHandler::RestartSession() {
   Browser* browser = chrome::FindLastActive();
   if (!browser) {
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
index a226651..0672952 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
+++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
@@ -86,6 +86,7 @@
   void RemoveTabFromOrganization(int32_t session_id,
                                  int32_t organization_id,
                                  tab_search::mojom::TabPtr tab) override;
+  void RejectSession(int32_t session_id) override;
   void RestartSession() override;
   void SaveRecentlyClosedExpandedPref(bool expanded) override;
   void SetTabIndex(int32_t index) override;
diff --git a/chrome/browser/ui/webui/webui_util.cc b/chrome/browser/ui/webui/webui_util.cc
index 71a6909e..89e864a 100644
--- a/chrome/browser/ui/webui/webui_util.cc
+++ b/chrome/browser/ui/webui/webui_util.cc
@@ -58,7 +58,7 @@
   if (scheme == content::kChromeUIScheme) {
     source->OverrideContentSecurityPolicy(
         network::mojom::CSPDirectiveName::ConnectSrc,
-        "connect-src chrome://resources 'self';");
+        "connect-src chrome://resources chrome://theme 'self';");
     source->OverrideContentSecurityPolicy(
         network::mojom::CSPDirectiveName::ImgSrc,
         "img-src chrome://resources chrome://theme chrome://image "
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
index cd2692a..e69d8bc 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -1269,7 +1269,7 @@
          current_step() == Step::kGPMEnterPin);
   // TODO(enclave): For kGPMCreatePin - upload pin and handle passkey creation.
   // TODO(enclave): For kGPMEnterPin - verify pin and handle sign-in or setting
-  // up biometrics (if available).
+  // up biometrics (if available) or setting `gpm_pin_error_`.
 }
 
 void AuthenticatorRequestDialogModel::AddAuthenticator(
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h
index f1b63cc..be14ac81 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.h
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -286,6 +286,12 @@
     kReady,
   };
 
+  // Possible error states during GPM pin entry / creation.
+  enum class GpmPinError {
+    kNone,
+    kWrongPin,
+  };
+
   explicit AuthenticatorRequestDialogModel(
       content::RenderFrameHost* render_frame_host);
 
@@ -728,6 +734,8 @@
   void set_allow_icloud_keychain(bool);
   void set_should_create_in_icloud_keychain(bool);
 
+  GpmPinError gpm_pin_error() const { return gpm_pin_error_; }
+
 #if BUILDFLAG(IS_MAC)
   void RecordMacOsStartedHistogram();
   void RecordMacOsSuccessHistogram(device::FidoRequestType,
@@ -982,6 +990,9 @@
   // Records the state of the primary account for the profile, if any.
   AccountState account_state_ = AccountState::kNone;
 
+  // Records the error during GPM pin entry / creation, if any.
+  GpmPinError gpm_pin_error_ = GpmPinError::kNone;
+
 #if BUILDFLAG(IS_MAC)
   // did_record_macos_start_histogram_ is set to true if a histogram record of
   // starting the current request was made. Any later successful completion will
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index b2513ad1e..0917b71 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1709229418-1d63095880705d541bde82fa1879afffe3b9eb1d-b0a7a7040e49ebde707133bb7b28d1df2acbe3f5.profdata
+chrome-android32-main-1709251103-e8d56921b9676e3c8c28dd83222f6d9af53ff132-3c4dd528ce3d74fc6fbb5168d0d0578f495ae3ac.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 3eabcec..d93ed7fe 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1709236759-a0e0102010e726c3ec9aa26f7a40a2917c462929-cb4b55eca6f33658d7073a2cc65fe5357f6b9ffb.profdata
+chrome-mac-arm-main-1709243983-50785a75cb830e0f2240fd1b19b319a71af9aaab-d13c4884812124f4acaa95b49bf2d9031dc14546.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 47a1cc5..773e267 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1709218648-e2b52b52f25d190f3daa56cd2651973155f54f21-e8dfc1f2e3fadb8df821082483dd7e98f14dd2e9.profdata
+chrome-win32-main-1709240374-c1fa17f359931ac60670f45b775a845e91cf471b-a24027fc5f6980ae3924b10ebafca851e62c9b14.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 49525b9..76dc689c 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1709218648-0864b8c6975aadc135a9a765319061552d647627-e8dfc1f2e3fadb8df821082483dd7e98f14dd2e9.profdata
+chrome-win64-main-1709240374-555542797fa7ce9ea2319c141916825658cb036a-a24027fc5f6980ae3924b10ebafca851e62c9b14.profdata
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index dde8502..9a4608e2 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -333,6 +333,8 @@
       "extensions/api/accessibility_private_hooks_delegate.h",
       "extensions/api/app_hooks_delegate.cc",
       "extensions/api/app_hooks_delegate.h",
+      "extensions/api/chrome_extensions_renderer_api_provider.cc",
+      "extensions/api/chrome_extensions_renderer_api_provider.h",
       "extensions/api/extension_hooks_delegate.cc",
       "extensions/api/extension_hooks_delegate.h",
       "extensions/api/identity_hooks_delegate.cc",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 086c1d1..5e6f1d9f 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -202,6 +202,7 @@
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 #include "chrome/common/controlled_frame/controlled_frame.h"
 #include "chrome/common/initialize_extensions_client.h"
+#include "chrome/renderer/extensions/api/chrome_extensions_renderer_api_provider.h"
 #include "chrome/renderer/extensions/chrome_extensions_renderer_client.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/context_data.h"
@@ -444,6 +445,8 @@
   chrome_extensions_renderer_client->AddAPIProvider(
       std::make_unique<
           controlled_frame::ControlledFrameExtensionsRendererAPIProvider>());
+  chrome_extensions_renderer_client->AddAPIProvider(
+      std::make_unique<extensions::ChromeExtensionsRendererAPIProvider>());
   chrome_extensions_renderer_client->RenderThreadStarted();
   WebSecurityPolicy::RegisterURLSchemeAsExtension(
       WebString::FromASCII(extensions::kExtensionScheme));
diff --git a/chrome/renderer/controlled_frame/controlled_frame_extensions_renderer_api_provider.cc b/chrome/renderer/controlled_frame/controlled_frame_extensions_renderer_api_provider.cc
index 6a9c30f..2064871 100644
--- a/chrome/renderer/controlled_frame/controlled_frame_extensions_renderer_api_provider.cc
+++ b/chrome/renderer/controlled_frame/controlled_frame_extensions_renderer_api_provider.cc
@@ -12,10 +12,10 @@
 
 namespace controlled_frame {
 
-void ControlledFrameExtensionsRendererAPIProvider::
-    EnableCustomElementAllowlist() {
-  blink::WebCustomElement::AddEmbedderCustomElementName("controlledframe");
-}
+void ControlledFrameExtensionsRendererAPIProvider::RegisterNativeHandlers(
+    extensions::ModuleSystem* module_system,
+    extensions::NativeExtensionBindingsSystem* bindings_system,
+    extensions::ScriptContext* context) {}
 
 void ControlledFrameExtensionsRendererAPIProvider::PopulateSourceMap(
     extensions::ResourceBundleSourceMap* source_map) {
@@ -28,6 +28,11 @@
                              IDR_CONTROLLED_FRAME_API_METHODS_JS);
 }
 
+void ControlledFrameExtensionsRendererAPIProvider::
+    EnableCustomElementAllowlist() {
+  blink::WebCustomElement::AddEmbedderCustomElementName("controlledframe");
+}
+
 bool ControlledFrameExtensionsRendererAPIProvider::RequireWebViewModules(
     extensions::ScriptContext* context) {
   if (context->GetAvailability("controlledFrameInternal").is_available()) {
diff --git a/chrome/renderer/controlled_frame/controlled_frame_extensions_renderer_api_provider.h b/chrome/renderer/controlled_frame/controlled_frame_extensions_renderer_api_provider.h
index fd15b49..9cb7eef7 100644
--- a/chrome/renderer/controlled_frame/controlled_frame_extensions_renderer_api_provider.h
+++ b/chrome/renderer/controlled_frame/controlled_frame_extensions_renderer_api_provider.h
@@ -28,9 +28,13 @@
   ControlledFrameExtensionsRendererAPIProvider& operator=(
       const ControlledFrameExtensionsRendererAPIProvider&) = delete;
 
-  void EnableCustomElementAllowlist() override;
+  void RegisterNativeHandlers(
+      extensions::ModuleSystem* module_system,
+      extensions::NativeExtensionBindingsSystem* bindings_system,
+      extensions::ScriptContext* context) override;
   void PopulateSourceMap(
       extensions::ResourceBundleSourceMap* source_map) override;
+  void EnableCustomElementAllowlist() override;
   bool RequireWebViewModules(extensions::ScriptContext* context) override;
 };
 
diff --git a/chrome/renderer/extensions/api/chrome_extensions_renderer_api_provider.cc b/chrome/renderer/extensions/api/chrome_extensions_renderer_api_provider.cc
new file mode 100644
index 0000000..a2e605e
--- /dev/null
+++ b/chrome/renderer/extensions/api/chrome_extensions_renderer_api_provider.cc
@@ -0,0 +1,187 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/extensions/api/chrome_extensions_renderer_api_provider.h"
+
+#include "build/chromeos_buildflags.h"
+#include "chrome/grit/renderer_resources.h"
+#include "chrome/renderer/extensions/api/media_galleries_custom_bindings.h"
+#include "chrome/renderer/extensions/api/notifications_native_handler.h"
+#include "chrome/renderer/extensions/api/page_capture_custom_bindings.h"
+#include "chrome/renderer/extensions/api/sync_file_system_custom_bindings.h"
+#include "extensions/renderer/bindings/api_bindings_system.h"
+#include "extensions/renderer/lazy_background_page_native_handler.h"
+#include "extensions/renderer/module_system.h"
+#include "extensions/renderer/native_extension_bindings_system.h"
+#include "extensions/renderer/native_handler.h"
+#include "extensions/renderer/resource_bundle_source_map.h"
+
+#if BUILDFLAG(IS_CHROMEOS)
+#include "chrome/renderer/extensions/api/file_browser_handler_custom_bindings.h"
+#include "chrome/renderer/extensions/api/platform_keys_natives.h"
+#endif
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "chrome/renderer/extensions/api/file_manager_private_custom_bindings.h"
+#endif
+
+namespace extensions {
+
+void ChromeExtensionsRendererAPIProvider::RegisterNativeHandlers(
+    ModuleSystem* module_system,
+    NativeExtensionBindingsSystem* bindings_system,
+    ScriptContext* context) {
+  module_system->RegisterNativeHandler(
+      "sync_file_system",
+      std::make_unique<SyncFileSystemCustomBindings>(context));
+#if BUILDFLAG(IS_CHROMEOS)
+  module_system->RegisterNativeHandler(
+      "file_browser_handler",
+      std::make_unique<FileBrowserHandlerCustomBindings>(context));
+  module_system->RegisterNativeHandler(
+      "platform_keys_natives", std::make_unique<PlatformKeysNatives>(context));
+#endif  // BUILDFLAG(IS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  module_system->RegisterNativeHandler(
+      "file_manager_private",
+      std::make_unique<FileManagerPrivateCustomBindings>(context));
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+  module_system->RegisterNativeHandler(
+      "notifications_private",
+      std::make_unique<NotificationsNativeHandler>(context));
+  module_system->RegisterNativeHandler(
+      "mediaGalleries",
+      std::make_unique<MediaGalleriesCustomBindings>(context));
+  module_system->RegisterNativeHandler(
+      "page_capture", std::make_unique<PageCaptureCustomBindings>(
+                          context, bindings_system->GetIPCMessageSender()));
+
+  // The following are native handlers that are defined in //extensions, but
+  // are only used for APIs defined in Chrome.
+  // TODO(devlin): We should clean this up. If an API is defined in Chrome,
+  // there's no reason to have its native handlers residing and being compiled
+  // in //extensions.
+  module_system->RegisterNativeHandler(
+      "lazy_background_page",
+      std::make_unique<LazyBackgroundPageNativeHandler>(context));
+}
+
+void ChromeExtensionsRendererAPIProvider::PopulateSourceMap(
+    ResourceBundleSourceMap* source_map) {
+  // Custom bindings.
+  source_map->RegisterSource("action", IDR_ACTION_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("browserAction",
+                             IDR_BROWSER_ACTION_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("declarativeContent",
+                             IDR_DECLARATIVE_CONTENT_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("desktopCapture",
+                             IDR_DESKTOP_CAPTURE_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("developerPrivate",
+                             IDR_DEVELOPER_PRIVATE_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("downloads", IDR_DOWNLOADS_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("gcm", IDR_GCM_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("identity", IDR_IDENTITY_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("imageWriterPrivate",
+                             IDR_IMAGE_WRITER_PRIVATE_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("input.ime", IDR_INPUT_IME_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("mediaGalleries",
+                             IDR_MEDIA_GALLERIES_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("notifications",
+                             IDR_NOTIFICATIONS_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("omnibox", IDR_OMNIBOX_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("pageAction", IDR_PAGE_ACTION_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("pageCapture",
+                             IDR_PAGE_CAPTURE_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("syncFileSystem",
+                             IDR_SYNC_FILE_SYSTEM_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("systemIndicator",
+                             IDR_SYSTEM_INDICATOR_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("tabCapture", IDR_TAB_CAPTURE_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("tts", IDR_TTS_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("ttsEngine", IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS);
+
+#if BUILDFLAG(IS_CHROMEOS)
+  source_map->RegisterSource("certificateProvider",
+                             IDR_CERTIFICATE_PROVIDER_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("enterprise.platformKeys",
+                             IDR_ENTERPRISE_PLATFORM_KEYS_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("enterprise.platformKeys.CryptoKey",
+                             IDR_ENTERPRISE_PLATFORM_KEYS_CRYPTO_KEY_JS);
+  source_map->RegisterSource("enterprise.platformKeys.SubtleCrypto",
+                             IDR_ENTERPRISE_PLATFORM_KEYS_SUBTLE_CRYPTO_JS);
+  source_map->RegisterSource("enterprise.platformKeys.Token",
+                             IDR_ENTERPRISE_PLATFORM_KEYS_TOKEN_JS);
+  source_map->RegisterSource("fileBrowserHandler",
+                             IDR_FILE_BROWSER_HANDLER_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("fileSystemProvider",
+                             IDR_FILE_SYSTEM_PROVIDER_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("platformKeys",
+                             IDR_PLATFORM_KEYS_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("platformKeys.getCryptoKeyUtil",
+                             IDR_PLATFORM_KEYS_GET_CRYPTO_KEY_UTIL_JS);
+  source_map->RegisterSource("platformKeys.Key", IDR_PLATFORM_KEYS_KEY_JS);
+  source_map->RegisterSource("platformKeys.SubtleCrypto",
+                             IDR_PLATFORM_KEYS_SUBTLE_CRYPTO_JS);
+  source_map->RegisterSource("platformKeys.utils", IDR_PLATFORM_KEYS_UTILS_JS);
+
+  // Remote Apps.
+  source_map->RegisterSource("chromeos.remote_apps.mojom-lite",
+                             IDR_REMOTE_APPS_MOJOM_LITE_JS);
+  source_map->RegisterSource("chromeos.remote_apps",
+                             IDR_REMOTE_APPS_BINDINGS_JS);
+  source_map->RegisterSource("url/mojom/url.mojom-lite",
+                             IDR_MOJO_URL_MOJOM_LITE_JS);
+#endif
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  source_map->RegisterSource("fileManagerPrivate",
+                             IDR_FILE_MANAGER_PRIVATE_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("terminalPrivate",
+                             IDR_TERMINAL_PRIVATE_CUSTOM_BINDINGS_JS);
+
+  // IME service on Chrome OS.
+  source_map->RegisterSource("ash.ime.mojom.ime_service.mojom",
+                             IDR_IME_SERVICE_MOJOM_JS);
+  source_map->RegisterSource("ash.ime.mojom.input_engine.mojom",
+                             IDR_IME_SERVICE_INPUT_ENGINE_MOJOM_JS);
+  source_map->RegisterSource("ash.ime.mojom.input_method.mojom",
+                             IDR_IME_SERVICE_INPUT_METHOD_MOJOM_JS);
+  source_map->RegisterSource("ash.ime.mojom.input_method_host.mojom",
+                             IDR_IME_SERVICE_INPUT_METHOD_HOST_MOJOM_JS);
+  source_map->RegisterSource("chromeos.ime.service",
+                             IDR_IME_SERVICE_BINDINGS_JS);
+
+  source_map->RegisterSource("chromeos.tts.mojom.google_tts_stream.mojom",
+                             IDR_GOOGLE_TTS_STREAM_MOJOM_JS);
+  source_map->RegisterSource("chromeos.tts.google_stream",
+                             IDR_GOOGLE_TTS_STREAM_BINDINGS_JS);
+
+  source_map->RegisterSource("ash.enhanced_network_tts.mojom-lite",
+                             IDR_ENHANCED_NETWORK_TTS_MOJOM_LITE_JS);
+  source_map->RegisterSource("ash.enhanced_network_tts",
+                             IDR_ENHANCED_NETWORK_TTS_BINDINGS_JS);
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
+  source_map->RegisterSource(
+      "webrtcDesktopCapturePrivate",
+      IDR_WEBRTC_DESKTOP_CAPTURE_PRIVATE_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("webrtcLoggingPrivate",
+                             IDR_WEBRTC_LOGGING_PRIVATE_CUSTOM_BINDINGS_JS);
+
+  // Platform app sources that are not API-specific..
+  source_map->RegisterSource("chromeWebViewElement",
+                             IDR_CHROME_WEB_VIEW_ELEMENT_JS);
+  source_map->RegisterSource("chromeWebViewInternal",
+                             IDR_CHROME_WEB_VIEW_INTERNAL_CUSTOM_BINDINGS_JS);
+  source_map->RegisterSource("chromeWebView", IDR_CHROME_WEB_VIEW_JS);
+}
+
+void ChromeExtensionsRendererAPIProvider::EnableCustomElementAllowlist() {}
+
+bool ChromeExtensionsRendererAPIProvider::RequireWebViewModules(
+    ScriptContext* context) {
+  return false;
+}
+
+}  // namespace extensions
diff --git a/chrome/renderer/extensions/api/chrome_extensions_renderer_api_provider.h b/chrome/renderer/extensions/api/chrome_extensions_renderer_api_provider.h
new file mode 100644
index 0000000..4263ba6
--- /dev/null
+++ b/chrome/renderer/extensions/api/chrome_extensions_renderer_api_provider.h
@@ -0,0 +1,36 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_EXTENSIONS_API_CHROME_EXTENSIONS_RENDERER_API_PROVIDER_H_
+#define CHROME_RENDERER_EXTENSIONS_API_CHROME_EXTENSIONS_RENDERER_API_PROVIDER_H_
+
+#include "extensions/renderer/extensions_renderer_api_provider.h"
+
+namespace extensions {
+class ResourceBundleSourceMap;
+class ScriptContext;
+
+// Provides capabilities for extension APIs defined at the //chrome layer.
+class ChromeExtensionsRendererAPIProvider
+    : public ExtensionsRendererAPIProvider {
+ public:
+  ChromeExtensionsRendererAPIProvider() = default;
+  ChromeExtensionsRendererAPIProvider(
+      const ChromeExtensionsRendererAPIProvider&) = delete;
+  ChromeExtensionsRendererAPIProvider& operator=(
+      const ChromeExtensionsRendererAPIProvider&) = delete;
+  ~ChromeExtensionsRendererAPIProvider() override = default;
+
+  // ExtensionsRendererAPIProvider:
+  void RegisterNativeHandlers(ModuleSystem* module_system,
+                              NativeExtensionBindingsSystem* bindings_system,
+                              ScriptContext* context) override;
+  void PopulateSourceMap(ResourceBundleSourceMap* source_map) override;
+  void EnableCustomElementAllowlist() override;
+  bool RequireWebViewModules(ScriptContext* context) override;
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_RENDERER_EXTENSIONS_API_CHROME_EXTENSIONS_RENDERER_API_PROVIDER_H_
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
index 969b2ee..9dc7f0b29 100644
--- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
+++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -12,7 +12,6 @@
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/crash_keys.h"
-#include "chrome/grit/renderer_resources.h"
 #include "chrome/renderer/extensions/api/app_hooks_delegate.h"
 #include "chrome/renderer/extensions/api/extension_hooks_delegate.h"
 #include "chrome/renderer/extensions/api/identity_hooks_delegate.h"
@@ -35,7 +34,6 @@
 #include "extensions/renderer/lazy_background_page_native_handler.h"
 #include "extensions/renderer/native_extension_bindings_system.h"
 #include "extensions/renderer/native_handler.h"
-#include "extensions/renderer/resource_bundle_source_map.h"
 #include "extensions/renderer/script_context.h"
 #include "media/media_buildflags.h"
 #include "printing/buildflags/buildflags.h"
@@ -61,162 +59,6 @@
 
 ChromeExtensionsDispatcherDelegate::~ChromeExtensionsDispatcherDelegate() {}
 
-void ChromeExtensionsDispatcherDelegate::RegisterNativeHandlers(
-    extensions::Dispatcher* dispatcher,
-    extensions::ModuleSystem* module_system,
-    extensions::NativeExtensionBindingsSystem* bindings_system,
-    extensions::ScriptContext* context) {
-  module_system->RegisterNativeHandler(
-      "sync_file_system",
-      std::unique_ptr<NativeHandler>(
-          new extensions::SyncFileSystemCustomBindings(context)));
-#if BUILDFLAG(IS_CHROMEOS)
-  module_system->RegisterNativeHandler(
-      "file_browser_handler",
-      std::make_unique<extensions::FileBrowserHandlerCustomBindings>(context));
-  module_system->RegisterNativeHandler(
-      "platform_keys_natives",
-      std::make_unique<extensions::PlatformKeysNatives>(context));
-#endif  // BUILDFLAG(IS_CHROMEOS)
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  module_system->RegisterNativeHandler(
-      "file_manager_private",
-      std::unique_ptr<NativeHandler>(
-          new extensions::FileManagerPrivateCustomBindings(context)));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-  module_system->RegisterNativeHandler(
-      "notifications_private",
-      std::unique_ptr<NativeHandler>(
-          new extensions::NotificationsNativeHandler(context)));
-  module_system->RegisterNativeHandler(
-      "mediaGalleries",
-      std::unique_ptr<NativeHandler>(
-          new extensions::MediaGalleriesCustomBindings(context)));
-  module_system->RegisterNativeHandler(
-      "page_capture", std::make_unique<extensions::PageCaptureCustomBindings>(
-                          context, bindings_system->GetIPCMessageSender()));
-
-  // The following are native handlers that are defined in //extensions, but
-  // are only used for APIs defined in Chrome.
-  // TODO(devlin): We should clean this up. If an API is defined in Chrome,
-  // there's no reason to have its native handlers residing and being compiled
-  // in //extensions.
-  module_system->RegisterNativeHandler(
-      "lazy_background_page",
-      std::unique_ptr<NativeHandler>(
-          new extensions::LazyBackgroundPageNativeHandler(context)));
-}
-
-void ChromeExtensionsDispatcherDelegate::PopulateSourceMap(
-    extensions::ResourceBundleSourceMap* source_map) {
-  // Custom bindings.
-  source_map->RegisterSource("action", IDR_ACTION_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("browserAction",
-                             IDR_BROWSER_ACTION_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("declarativeContent",
-                             IDR_DECLARATIVE_CONTENT_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("desktopCapture",
-                             IDR_DESKTOP_CAPTURE_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("developerPrivate",
-                             IDR_DEVELOPER_PRIVATE_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("downloads", IDR_DOWNLOADS_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("gcm", IDR_GCM_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("identity", IDR_IDENTITY_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("imageWriterPrivate",
-                             IDR_IMAGE_WRITER_PRIVATE_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("input.ime", IDR_INPUT_IME_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("mediaGalleries",
-                             IDR_MEDIA_GALLERIES_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("notifications",
-                             IDR_NOTIFICATIONS_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("omnibox", IDR_OMNIBOX_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("pageAction", IDR_PAGE_ACTION_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("pageCapture",
-                             IDR_PAGE_CAPTURE_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("syncFileSystem",
-                             IDR_SYNC_FILE_SYSTEM_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("systemIndicator",
-                             IDR_SYSTEM_INDICATOR_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("tabCapture", IDR_TAB_CAPTURE_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("tts", IDR_TTS_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("ttsEngine", IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS);
-
-#if BUILDFLAG(IS_CHROMEOS)
-  source_map->RegisterSource("certificateProvider",
-                             IDR_CERTIFICATE_PROVIDER_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("enterprise.platformKeys",
-                             IDR_ENTERPRISE_PLATFORM_KEYS_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("enterprise.platformKeys.CryptoKey",
-                             IDR_ENTERPRISE_PLATFORM_KEYS_CRYPTO_KEY_JS);
-  source_map->RegisterSource("enterprise.platformKeys.SubtleCrypto",
-                             IDR_ENTERPRISE_PLATFORM_KEYS_SUBTLE_CRYPTO_JS);
-  source_map->RegisterSource("enterprise.platformKeys.Token",
-                             IDR_ENTERPRISE_PLATFORM_KEYS_TOKEN_JS);
-  source_map->RegisterSource("fileBrowserHandler",
-                             IDR_FILE_BROWSER_HANDLER_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("fileSystemProvider",
-                             IDR_FILE_SYSTEM_PROVIDER_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("platformKeys",
-                             IDR_PLATFORM_KEYS_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("platformKeys.getCryptoKeyUtil",
-                             IDR_PLATFORM_KEYS_GET_CRYPTO_KEY_UTIL_JS);
-  source_map->RegisterSource("platformKeys.Key", IDR_PLATFORM_KEYS_KEY_JS);
-  source_map->RegisterSource("platformKeys.SubtleCrypto",
-                             IDR_PLATFORM_KEYS_SUBTLE_CRYPTO_JS);
-  source_map->RegisterSource("platformKeys.utils", IDR_PLATFORM_KEYS_UTILS_JS);
-
-  // Remote Apps.
-  source_map->RegisterSource("chromeos.remote_apps.mojom-lite",
-                             IDR_REMOTE_APPS_MOJOM_LITE_JS);
-  source_map->RegisterSource("chromeos.remote_apps",
-                             IDR_REMOTE_APPS_BINDINGS_JS);
-  source_map->RegisterSource("url/mojom/url.mojom-lite",
-                             IDR_MOJO_URL_MOJOM_LITE_JS);
-#endif
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  source_map->RegisterSource("fileManagerPrivate",
-                             IDR_FILE_MANAGER_PRIVATE_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("terminalPrivate",
-                             IDR_TERMINAL_PRIVATE_CUSTOM_BINDINGS_JS);
-
-  // IME service on Chrome OS.
-  source_map->RegisterSource("ash.ime.mojom.ime_service.mojom",
-                             IDR_IME_SERVICE_MOJOM_JS);
-  source_map->RegisterSource("ash.ime.mojom.input_engine.mojom",
-                             IDR_IME_SERVICE_INPUT_ENGINE_MOJOM_JS);
-  source_map->RegisterSource("ash.ime.mojom.input_method.mojom",
-                             IDR_IME_SERVICE_INPUT_METHOD_MOJOM_JS);
-  source_map->RegisterSource("ash.ime.mojom.input_method_host.mojom",
-                             IDR_IME_SERVICE_INPUT_METHOD_HOST_MOJOM_JS);
-  source_map->RegisterSource("chromeos.ime.service",
-                             IDR_IME_SERVICE_BINDINGS_JS);
-
-  source_map->RegisterSource("chromeos.tts.mojom.google_tts_stream.mojom",
-                             IDR_GOOGLE_TTS_STREAM_MOJOM_JS);
-  source_map->RegisterSource("chromeos.tts.google_stream",
-                             IDR_GOOGLE_TTS_STREAM_BINDINGS_JS);
-
-  source_map->RegisterSource("ash.enhanced_network_tts.mojom-lite",
-                             IDR_ENHANCED_NETWORK_TTS_MOJOM_LITE_JS);
-  source_map->RegisterSource("ash.enhanced_network_tts",
-                             IDR_ENHANCED_NETWORK_TTS_BINDINGS_JS);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
-  source_map->RegisterSource(
-      "webrtcDesktopCapturePrivate",
-      IDR_WEBRTC_DESKTOP_CAPTURE_PRIVATE_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("webrtcLoggingPrivate",
-                             IDR_WEBRTC_LOGGING_PRIVATE_CUSTOM_BINDINGS_JS);
-
-  // Platform app sources that are not API-specific..
-  source_map->RegisterSource("chromeWebViewElement",
-                             IDR_CHROME_WEB_VIEW_ELEMENT_JS);
-  source_map->RegisterSource("chromeWebViewInternal",
-                             IDR_CHROME_WEB_VIEW_INTERNAL_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("chromeWebView", IDR_CHROME_WEB_VIEW_JS);
-}
-
 void ChromeExtensionsDispatcherDelegate::RequireWebViewModules(
     extensions::ScriptContext* context) {
   DCHECK(context->GetAvailability("webViewInternal").is_available());
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.h b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.h
index a939f33..a0560d3 100644
--- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.h
+++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.h
@@ -21,13 +21,6 @@
 
  private:
   // extensions::DispatcherDelegate implementation.
-  void RegisterNativeHandlers(
-      extensions::Dispatcher* dispatcher,
-      extensions::ModuleSystem* module_system,
-      extensions::NativeExtensionBindingsSystem* bindings_system,
-      extensions::ScriptContext* context) override;
-  void PopulateSourceMap(
-      extensions::ResourceBundleSourceMap* source_map) override;
   void RequireWebViewModules(extensions::ScriptContext* context) override;
   void OnActiveExtensionsUpdated(
       const std::set<std::string>& extensions_ids) override;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 0e038a6..585049f 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1830,6 +1830,7 @@
       "//components/history/content/browser",
       "//components/history/core/common",
       "//components/history_clusters/core:core",
+      "//components/history_embeddings",
       "//components/image_fetcher/core",
       "//components/infobars/content",
       "//components/invalidation/impl",
@@ -2096,7 +2097,6 @@
       "//components/policy/proto",
       "//testing:test_scripts_shared",
       "//testing/buildbot/filters:browser_tests_filters",
-      "//testing/buildbot/filters:cr23_pixel_browser_tests_filters",
       "//testing/buildbot/filters:linux_trusty_rel_browser_tests_filters",
       "//third_party/mesa_headers",
       "//third_party/private_membership:private_membership_proto",
@@ -2317,6 +2317,7 @@
       "../browser/history/history_browsertest.cc",
       "../browser/history/redirect_browsertest.cc",
       "../browser/history_clusters/history_clusters_metrics_browsertest.cc",
+      "../browser/history_embeddings/history_embeddings_service_browsertest.cc",
       "../browser/icon_loader_browsertest.cc",
       "../browser/icon_transcoder/svg_icon_transcoder_browsertest.cc",
       "../browser/idle/idle_browsertest.cc",
@@ -4816,7 +4817,6 @@
         "../browser/policy/login_policy_test_base_browsertest.cc",
         "../browser/policy/restricted_mgs_policy_provider_ash_browsertest.cc",
         "../browser/process_singleton_browsertest.cc",
-        "../browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc",
         "../browser/sessions/session_restore_browsertest_chromeos.cc",
         "../browser/signin/chromeos_mirror_account_consistency_browsertest.cc",
         "../browser/speech/extension_api/tts_extension_api_ash_browsertest.cc",
@@ -4884,6 +4884,7 @@
         "../browser/ui/quick_answers/quick_answers_browsertest.cc",
         "../browser/ui/quick_answers/quick_answers_browsertest_base.cc",
         "../browser/ui/quick_answers/quick_answers_browsertest_base.h",
+        "../browser/ui/quick_answers/quick_answers_controller_browsertest.cc",
         "../browser/ui/settings_window_manager_browsertest_chromeos.cc",
         "../browser/ui/views/apps/app_dialog/app_dialog_view_browsertest.cc",
         "../browser/ui/views/apps/app_dialog/app_uninstall_dialog_view_browsertest.cc",
@@ -8335,7 +8336,7 @@
       "../browser/performance_manager/policies/oom_score_policy_chromeos_unittest.cc",
       "../browser/performance_manager/policies/report_page_processes_policy_unittest.cc",
       "../browser/policy/system_features_disable_list_policy_handler_unittest.cc",
-      "../browser/renderer_context_menu/quick_answers_menu_observer_unittest.cc",
+      "../browser/renderer_context_menu/read_write_card_observer_unittest.cc",
       "../browser/speech/tts_crosapi_util_unittest.cc",
       "../browser/ui/webui/certificate_provisioning_ui_handler_unittest.cc",
       "../browser/usb/usb_pinned_notification_unittest.cc",
diff --git a/chrome/test/data/webui/chromeos/print_preview_cros/fake_print_preview_page_handler_test.ts b/chrome/test/data/webui/chromeos/print_preview_cros/fake_print_preview_page_handler_test.ts
index 323010b..182363b1 100644
--- a/chrome/test/data/webui/chromeos/print_preview_cros/fake_print_preview_page_handler_test.ts
+++ b/chrome/test/data/webui/chromeos/print_preview_cros/fake_print_preview_page_handler_test.ts
@@ -7,6 +7,7 @@
 import {FAKE_PRINT_REQUEST_FAILURE_INVALID_SETTINGS_ERROR, FAKE_PRINT_REQUEST_SUCCESSFUL, FakePrintPreviewPageHandler} from 'chrome://os-print/js/fakes/fake_print_preview_page_handler.js';
 import {assert} from 'chrome://resources/js/assert.js';
 import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {MockController} from 'chrome://webui-test/chromeos/mock_controller.m.js';
 
 suite('PrintPreviewCrosApp', () => {
   let printPreviewPageHandler: FakePrintPreviewPageHandler;
@@ -46,4 +47,37 @@
     printPreviewPageHandler.cancel();
     assertEquals(1, printPreviewPageHandler.getCallCount('cancel'));
   });
+
+  // Verify the fake PrintPreviewPageHandler method uses 0ms delay resolve
+  // method by default.
+  test('default delay is 0ms', async () => {
+    const mockController = new MockController();
+    const methods = printPreviewPageHandler.getMethodsForTesting();
+    const resolveNoDelay =
+        mockController.createFunctionMock(methods, 'resolveMethodWithDelay');
+    const delay = 0;
+    resolveNoDelay.addExpectation('print', delay);
+    await printPreviewPageHandler.print();
+
+    mockController.verifyMocks();
+    mockController.reset();
+  });
+
+  // Verify the fake PrintPreviewPageHandler use resolve method with delay when
+  // a delay is configured.
+  test(
+      'uses delayed resolver when testDelayMs is greater than zero',
+      async () => {
+        const mockController = new MockController();
+        const methods = printPreviewPageHandler.getMethodsForTesting();
+        const resolveWithDelay = mockController.createFunctionMock(
+            methods, 'resolveMethodWithDelay');
+        const delay = 1;
+        resolveWithDelay.addExpectation('print', delay);
+        printPreviewPageHandler.useTestDelay(delay);
+        await printPreviewPageHandler.print();
+
+        mockController.verifyMocks();
+        mockController.reset();
+      });
 });
diff --git a/chrome/test/data/webui/chromeos/print_preview_cros/print_ticket_manager_test.ts b/chrome/test/data/webui/chromeos/print_preview_cros/print_ticket_manager_test.ts
index 30d866d..8d37dfd1 100644
--- a/chrome/test/data/webui/chromeos/print_preview_cros/print_ticket_manager_test.ts
+++ b/chrome/test/data/webui/chromeos/print_preview_cros/print_ticket_manager_test.ts
@@ -4,22 +4,31 @@
 
 import 'chrome://os-print/js/data/print_ticket_manager.js';
 
-import {PrintTicketManager} from 'chrome://os-print/js/data/print_ticket_manager.js';
+import {PRINT_REQUEST_FINISHED_EVENT, PRINT_REQUEST_STARTED_EVENT, PrintTicketManager} from 'chrome://os-print/js/data/print_ticket_manager.js';
 import {FakePrintPreviewPageHandler} from 'chrome://os-print/js/fakes/fake_print_preview_page_handler.js';
 import {setPrintPreviewPageHandlerForTesting} from 'chrome://os-print/js/utils/mojo_data_providers.js';
-import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {MockTimer} from 'chrome://webui-test/mock_timer.js';
+import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
 suite('PrintTicketManager', () => {
   let printPreviewPageHandler: FakePrintPreviewPageHandler;
+  let mockTimer: MockTimer;
 
   setup(() => {
     PrintTicketManager.resetInstanceForTesting();
 
     // Setup fakes for testing.
+    mockTimer = new MockTimer();
+    mockTimer.install();
     printPreviewPageHandler = new FakePrintPreviewPageHandler();
     setPrintPreviewPageHandlerForTesting(printPreviewPageHandler);
   });
 
+  teardown(() => {
+    mockTimer.uninstall();
+  });
+
   test('is a singleton', () => {
     const instance1 = PrintTicketManager.getInstance();
     const instance2 = PrintTicketManager.getInstance();
@@ -49,4 +58,117 @@
     instance.cancelPrintRequest();
     assertEquals(1, printPreviewPageHandler.getCallCount(method));
   });
+
+  // Verify PRINT_REQUEST_STARTED_EVENT is dispatched when sentPrintRequest is
+  // called and PRINT_REQUEST_FINISHED_EVENT is called when
+  // PrintPreviewPageHandler.print resolves.
+  test(
+      'PRINT_REQUEST_STARTED_EVENT and PRINT_REQUEST_FINISHED_EVENT are ' +
+          ' invoked when sentPrintRequest called',
+      async () => {
+        const delay = 1;
+        printPreviewPageHandler.useTestDelay(delay);
+        const instance = PrintTicketManager.getInstance();
+        let startCount = 0;
+        instance.addEventListener(PRINT_REQUEST_STARTED_EVENT, () => {
+          ++startCount;
+        });
+        let finishCount = 0;
+        instance.addEventListener(PRINT_REQUEST_FINISHED_EVENT, () => {
+          ++finishCount;
+        });
+        const startEvent =
+            eventToPromise(PRINT_REQUEST_STARTED_EVENT, instance);
+        const finishEvent =
+            eventToPromise(PRINT_REQUEST_FINISHED_EVENT, instance);
+
+        assertEquals(0, startCount, 'Start should have zero calls');
+        assertEquals(0, finishCount, 'Finish should have zero calls');
+
+        instance.sendPrintRequest();
+
+        await startEvent;
+
+        assertEquals(1, startCount, 'Start should have one call');
+        assertEquals(0, finishCount, 'Finish should have zero calls');
+
+        // Advance time by test delay to trigger method resolver.
+        mockTimer.tick(delay);
+        await finishEvent;
+
+        assertEquals(1, startCount, 'Start should have one call');
+        assertEquals(1, finishCount, 'Finish should have one call');
+      });
+
+  // Verify isPrintRequestInProgress is false until sentPrintRequest is called
+  // and returns to false when PrintPreviewPageHandler.print resolves.
+  test(
+      'isPrintRequestInProgress updates based on sendPrintRequest progress',
+      async () => {
+        const delay = 1;
+        printPreviewPageHandler.useTestDelay(delay);
+        const instance = PrintTicketManager.getInstance();
+        const startEvent =
+            eventToPromise(PRINT_REQUEST_STARTED_EVENT, instance);
+        const finishEvent =
+            eventToPromise(PRINT_REQUEST_FINISHED_EVENT, instance);
+
+        assertFalse(instance.isPrintRequestInProgress(), 'Request not started');
+
+        instance.sendPrintRequest();
+
+        await startEvent;
+
+        assertTrue(instance.isPrintRequestInProgress(), 'Request started');
+
+        mockTimer.tick(delay);
+        await finishEvent;
+
+        assertFalse(instance.isPrintRequestInProgress(), 'Request finished');
+      });
+
+  // Verify PrintTicketManger ensures that PrintPreviewPageHandler.print is only
+  // called if print request is not in progress.
+  test('ensure only one print request triggered at a time', async () => {
+    const delay = 1;
+    printPreviewPageHandler.useTestDelay(delay);
+    const instance = PrintTicketManager.getInstance();
+    const startEvent = eventToPromise(PRINT_REQUEST_STARTED_EVENT, instance);
+    const finishEvent = eventToPromise(PRINT_REQUEST_FINISHED_EVENT, instance);
+
+    const method = 'print';
+    let expectedCallCount = 0;
+    assertEquals(
+        expectedCallCount, printPreviewPageHandler.getCallCount(method),
+        'No request sent');
+    assertFalse(instance.isPrintRequestInProgress(), 'Request not started');
+
+    instance.sendPrintRequest();
+
+    // After calling `sendPrintRequest` the call count should increment.
+    ++expectedCallCount;
+    await startEvent;
+
+    assertEquals(
+        expectedCallCount, printPreviewPageHandler.getCallCount(method),
+        'One request sent');
+    assertTrue(instance.isPrintRequestInProgress(), 'Request started');
+
+    // While request is in progress additional `sendPrintRequest` should not
+    // call `PrintPreviewPageHandler.print`.
+    instance.sendPrintRequest();
+    instance.sendPrintRequest();
+    instance.sendPrintRequest();
+    assertEquals(
+        expectedCallCount, printPreviewPageHandler.getCallCount(method),
+        'One request sent');
+
+    mockTimer.tick(delay);
+    await finishEvent;
+
+    assertEquals(
+        expectedCallCount, printPreviewPageHandler.getCallCount(method),
+        'One request sent');
+    assertFalse(instance.isPrintRequestInProgress(), 'Request finished');
+  });
 });
diff --git a/chrome/test/data/webui/chromeos/print_preview_cros/summary_panel_controller_test.ts b/chrome/test/data/webui/chromeos/print_preview_cros/summary_panel_controller_test.ts
index d7e1bfb4..7c37f6c 100644
--- a/chrome/test/data/webui/chromeos/print_preview_cros/summary_panel_controller_test.ts
+++ b/chrome/test/data/webui/chromeos/print_preview_cros/summary_panel_controller_test.ts
@@ -4,25 +4,37 @@
 
 import 'chrome://os-print/js/summary_panel.js';
 
-import {PrintTicketManager} from 'chrome://os-print/js/data/print_ticket_manager.js';
+import {PRINT_REQUEST_FINISHED_EVENT, PRINT_REQUEST_STARTED_EVENT, PrintTicketManager} from 'chrome://os-print/js/data/print_ticket_manager.js';
+import {FakePrintPreviewPageHandler} from 'chrome://os-print/js/fakes/fake_print_preview_page_handler.js';
 import {SummaryPanelController} from 'chrome://os-print/js/summary_panel_controller.js';
+import {setPrintPreviewPageHandlerForTesting} from 'chrome://os-print/js/utils/mojo_data_providers.js';
 import {assert} from 'chrome://resources/js/assert.js';
-import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {MockController} from 'chrome://webui-test/chromeos/mock_controller.m.js';
+import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
 suite('SummaryPanelController', () => {
   let controller: SummaryPanelController|null = null;
   let mockController: MockController;
+  let printPreviewPageHandler: FakePrintPreviewPageHandler;
+  let printTicketManger: PrintTicketManager;
 
   setup(() => {
     mockController = new MockController();
 
+    PrintTicketManager.resetInstanceForTesting();
+    // Setup fakes.
+    printPreviewPageHandler = new FakePrintPreviewPageHandler();
+    setPrintPreviewPageHandlerForTesting(printPreviewPageHandler);
+    printTicketManger = PrintTicketManager.getInstance();
+
     controller = new SummaryPanelController();
     assertTrue(!!controller);
   });
 
   teardown(() => {
     mockController.reset();
+    PrintTicketManager.resetInstanceForTesting();
     controller = null;
   });
 
@@ -67,4 +79,60 @@
         controller!.handleCancelClicked();
         mockController.verifyMocks();
       });
+
+  // Verify handler called when PRINT_REQUEST_STARTED_EVENT triggered.
+  test('PRINT_REQUEST_STARTED_EVENT calls onPrintRequestStarted', async () => {
+    assert(controller);
+    const handlerFn =
+        mockController.createFunctionMock(controller, 'onPrintRequestStarted');
+    const testEvent = new CustomEvent<void>(
+        PRINT_REQUEST_STARTED_EVENT, {bubbles: true, composed: true});
+    const startRequest =
+        eventToPromise(PRINT_REQUEST_STARTED_EVENT, printTicketManger);
+    handlerFn.addExpectation(testEvent);
+
+    printTicketManger.dispatchEvent(testEvent);
+    await startRequest;
+
+    mockController.verifyMocks();
+  });
+
+  // Verify handler called when PRINT_REQUEST_FINISHED_EVENT triggered.
+  test(
+      'PRINT_REQUEST_FINISHED_EVENT calls onPrintRequestFinished', async () => {
+        assert(controller);
+        const handlerFn = mockController.createFunctionMock(
+            controller, 'onPrintRequestFinished');
+        const testEvent = new CustomEvent<void>(
+            PRINT_REQUEST_FINISHED_EVENT, {bubbles: true, composed: true});
+        const finishRequest =
+            eventToPromise(PRINT_REQUEST_FINISHED_EVENT, printTicketManger);
+        handlerFn.addExpectation(testEvent);
+
+        printTicketManger.dispatchEvent(testEvent);
+        await finishRequest;
+
+        mockController.verifyMocks();
+      });
+
+  // Verify shouldDisablePrintButton is true when print request is in progress.
+  test(
+      'shouldDisablePrintButton true while print request is in progress',
+      () => {
+        const printRequestInProgressFn = mockController.createFunctionMock(
+            printTicketManger, 'isPrintRequestInProgress');
+        printRequestInProgressFn.returnValue = true;
+        assertTrue(controller!.shouldDisablePrintButton());
+      });
+
+  // Verify shouldDisablePrintButton is false when print request is not in
+  // progress.
+  test(
+      'shouldDisablePrintButton true while print request is in progress',
+      () => {
+        const printRequestInProgressFn = mockController.createFunctionMock(
+            printTicketManger, 'isPrintRequestInProgress');
+        printRequestInProgressFn.returnValue = false;
+        assertFalse(controller!.shouldDisablePrintButton());
+      });
 });
diff --git a/chrome/test/data/webui/chromeos/print_preview_cros/summary_panel_test.ts b/chrome/test/data/webui/chromeos/print_preview_cros/summary_panel_test.ts
index 68f8dec..6b6d33b7b 100644
--- a/chrome/test/data/webui/chromeos/print_preview_cros/summary_panel_test.ts
+++ b/chrome/test/data/webui/chromeos/print_preview_cros/summary_panel_test.ts
@@ -4,14 +4,18 @@
 
 import 'chrome://os-print/js/summary_panel.js';
 
+import {PrintTicketManager} from 'chrome://os-print/js/data/print_ticket_manager.js';
+import {FakePrintPreviewPageHandler} from 'chrome://os-print/js/fakes/fake_print_preview_page_handler.js';
 import {SummaryPanelElement} from 'chrome://os-print/js/summary_panel.js';
-import {SHEETS_USED_CHANGED_EVENT, SummaryPanelController} from 'chrome://os-print/js/summary_panel_controller.js';
+import {PRINT_BUTTON_DISABLED_CHANGED_EVENT, SHEETS_USED_CHANGED_EVENT, SummaryPanelController} from 'chrome://os-print/js/summary_panel_controller.js';
+import {setPrintPreviewPageHandlerForTesting} from 'chrome://os-print/js/utils/mojo_data_providers.js';
 import {strictQuery} from 'chrome://resources/ash/common/typescript_utils/strict_query.js';
 import {Button} from 'chrome://resources/cros_components/button/button.js';
 import {assert} from 'chrome://resources/js/assert.js';
-import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {MockController} from 'chrome://webui-test/chromeos/mock_controller.m.js';
-import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
+import {MockTimer} from 'chrome://webui-test/mock_timer.js';
 import {eventToPromise, isChildVisible, isVisible} from 'chrome://webui-test/test_util.js';
 
 suite('SummaryPanel', () => {
@@ -22,10 +26,18 @@
   let element: SummaryPanelElement|null = null;
   let controller: SummaryPanelController|null = null;
   let mockController: MockController|null = null;
+  let printPreviewPageHandler: FakePrintPreviewPageHandler;
+  let mockTimer: MockTimer;
 
   setup(async () => {
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
+    // Configure mocks and fakes.
     mockController = new MockController();
+    mockTimer = new MockTimer();
+    mockTimer.install();
+    PrintTicketManager.resetInstanceForTesting();
+    printPreviewPageHandler = new FakePrintPreviewPageHandler();
+    setPrintPreviewPageHandlerForTesting(printPreviewPageHandler);
     element =
         document.createElement(SummaryPanelElement.is) as SummaryPanelElement;
     assertTrue(!!element);
@@ -37,10 +49,11 @@
 
     // CrOS components are async and require flushTasks before they are
     // available.
-    await flushTasks();
+    flush();
   });
 
   teardown(() => {
+    mockTimer.uninstall();
     if (element) {
       element.remove();
     }
@@ -48,6 +61,7 @@
     controller = null;
     mockController?.reset();
     mockController = null;
+    PrintTicketManager.resetInstanceForTesting();
   });
 
   // Sets sheets used in controller and wait for UI to update.
@@ -57,7 +71,7 @@
         eventToPromise(SHEETS_USED_CHANGED_EVENT, controller);
     controller.setSheetsUsedForTesting(sheetsUsed);
     await sheetsUsedEvent;
-    await flushTasks();
+    flush();
   }
 
   // Verify the summary-panel element can be rendered, contains print, cancel,
@@ -150,4 +164,42 @@
     // Verify controller is listening to click event.
     mockController.verifyMocks();
   });
+
+  // Verify print button disabled when print button clicked and re-enabled when
+  // PrintPreviewPageHandler.print resolves.
+  test('Print button disabled while print request in progress', async () => {
+    assert(controller);
+    const printDisabledEvent1 =
+        eventToPromise(PRINT_BUTTON_DISABLED_CHANGED_EVENT, controller);
+    const delay = 10;
+    printPreviewPageHandler.useTestDelay(delay);
+
+    const printButton =
+        strictQuery<Button>(printButtonSelector, element!.shadowRoot, Button);
+    assertFalse(
+        printButton.disabled, 'Print should be enabled before request sent');
+
+    printButton.click();
+    await printDisabledEvent1;
+
+    const printTicketManger = PrintTicketManager.getInstance();
+    assertTrue(
+        printTicketManger.isPrintRequestInProgress(),
+        'Print request in progress');
+    assertTrue(
+        printButton.disabled,
+        'Print should be disabled while request in progress');
+
+    const printDisabledEvent2 =
+        eventToPromise(PRINT_BUTTON_DISABLED_CHANGED_EVENT, controller);
+    mockTimer.tick(delay);
+    await printDisabledEvent2;
+
+    assertFalse(
+        printTicketManger.isPrintRequestInProgress(),
+        'Print request is complete');
+    assertFalse(
+        printButton.disabled,
+        'Print should be enabled after request completes');
+  });
 });
diff --git a/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_view_test.ts b/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_view_test.ts
index 9adae58..f9a59bb9 100644
--- a/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_view_test.ts
+++ b/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_view_test.ts
@@ -597,8 +597,8 @@
 
     const viewContainer =
         viewElement.shadowRoot!.querySelector('#container') as HTMLDivElement;
-    // The icon name is 'overview' in keyToIconNameMap.
-    const regex = /^(search|launcher) alt shift overview$/;
+    // The icon label is 'show windows'.
+    const regex = /^(search|launcher) alt shift show windows$/;
     assertTrue(!!viewContainer.ariaLabel);
     assertTrue(regex.test(viewContainer.ariaLabel));
   });
diff --git a/chrome/test/data/webui/downloads/test_support.ts b/chrome/test/data/webui/downloads/test_support.ts
index b232eabb..4ef6fd9 100644
--- a/chrome/test/data/webui/downloads/test_support.ts
+++ b/chrome/test/data/webui/downloads/test_support.ts
@@ -85,6 +85,7 @@
   reviewDangerousRequiringGesture(_id: string) {}
   deepScan(_id: string) {}
   bypassDeepScanRequiringGesture(_id: string) {}
+  openEsbSettings() {}
 }
 
 export class TestIconLoader extends TestBrowserProxy implements IconLoader {
diff --git a/chrome/test/data/webui/new_tab_page/app_test.ts b/chrome/test/data/webui/new_tab_page/app_test.ts
index f2c49b29..524c3b3 100644
--- a/chrome/test/data/webui/new_tab_page/app_test.ts
+++ b/chrome/test/data/webui/new_tab_page/app_test.ts
@@ -1175,6 +1175,7 @@
       suiteSetup(() => {
         loadTimeData.overrideValues({
           wallpaperSearchButtonEnabled: true,
+          wallpaperSearchButtonAnimationEnabled: true,
         });
       });
 
@@ -1183,6 +1184,18 @@
         assertTrue(!!app.shadowRoot!.querySelector('#wallpaperSearchButton'));
       });
 
+      test('button has animation if the flag is enabled', () => {
+        assertNotStyle(
+            $$(app, '#wallpaperSearchButtonContainer')!, 'animation-name',
+            'none');
+        assertNotStyle(
+            $$(app, '#wallpaperSearchButton .customize-icon')!,
+            'animation-name', 'none');
+        assertNotStyle(
+            $$(app, '#wallpaperSearchButton .customize-text')!,
+            'animation-name', 'none');
+      });
+
       ([
         ['#customizeButton', NtpElement.CUSTOMIZE_BUTTON],
         ['#wallpaperSearchButton', NtpElement.WALLPAPER_SEARCH_BUTTON],
@@ -1358,5 +1371,25 @@
                 $$<HTMLElement>(app, '#customizeButtonContainer')!.offsetWidth);
           });
     });
+
+    suite('AnimationDisabled', () => {
+      suiteSetup(() => {
+        loadTimeData.overrideValues({
+          wallpaperSearchButtonAnimationEnabled: false,
+        });
+      });
+
+      test('button has no animation if the flag is disabled', () => {
+        assertStyle(
+            $$(app, '#wallpaperSearchButtonContainer')!, 'animation-name',
+            'none');
+        assertStyle(
+            $$(app, '#wallpaperSearchButton .customize-icon')!,
+            'animation-name', 'none');
+        assertStyle(
+            $$(app, '#wallpaperSearchButton .customize-text')!,
+            'animation-name', 'none');
+      });
+    });
   });
 });
diff --git a/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_landing_page_test.ts b/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_landing_page_test.ts
index 504faea7..0d7590d7 100644
--- a/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_landing_page_test.ts
+++ b/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_landing_page_test.ts
@@ -1389,11 +1389,11 @@
     // connected to a network.
     assertTrue(!!page.shadowRoot!.querySelector('#cloudOffIcon'));
     assertTrue(!!page.shadowRoot!.querySelector('#connectionMessage'));
-    const addManualPrinterButtonRevamp =
+    const addManualPrinterButton =
         page.shadowRoot!.querySelector<HTMLButtonElement>(
-            '#addManualPrinterButtonRevamp');
-    assertTrue(!!addManualPrinterButtonRevamp);
-    assertTrue(addManualPrinterButtonRevamp.disabled);
+            '#addManualPrinterButton');
+    assertTrue(!!addManualPrinterButton);
+    assertTrue(addManualPrinterButton.disabled);
   });
 
   test('checkNetworkConnection', async () => {
@@ -1407,11 +1407,11 @@
     // connected.
     assertTrue(!!page.shadowRoot!.querySelector('#cloudOffIcon'));
     assertTrue(!!page.shadowRoot!.querySelector('#connectionMessage'));
-    const addManualPrinterButtonRevamp =
+    const addManualPrinterButton =
         page.shadowRoot!.querySelector<HTMLButtonElement>(
-            '#addManualPrinterButtonRevamp');
-    assertTrue(!!addManualPrinterButtonRevamp);
-    assertTrue(addManualPrinterButtonRevamp.disabled);
+            '#addManualPrinterButton');
+    assertTrue(!!addManualPrinterButton);
+    assertTrue(addManualPrinterButton.disabled);
     // Simulate connecting to a network with connectivity.
     wifi1.connectionState = ConnectionStateType.kOnline;
     page.onActiveNetworksChanged([wifi1]);
diff --git a/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_page_test.ts b/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_page_test.ts
index b648e035..9b0ffee 100644
--- a/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_page_test.ts
+++ b/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_page_test.ts
@@ -160,7 +160,7 @@
 
     await flushTasks();
     const icon = page.shadowRoot!.querySelector<HTMLButtonElement>(
-        '#addManualPrinterButtonRevamp');
+        '#addManualPrinterButton');
     assertTrue(!!icon);
     icon.click();
     assertEquals(
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.cc b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.cc
index a87d605..e4182f8d 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.cc
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.cc
@@ -1750,18 +1750,23 @@
   RunSettingsTest("os_people_page/account_manager_settings_card_test.js");
 }
 
-class OSSettingsPeopleTestLacrosOnlyDisabled : public OSSettingsMochaTest {
+class OSSettingsMochaTestRevampAndLacrosOnlyDisabled
+    : public OSSettingsMochaTest {
  protected:
-  OSSettingsPeopleTestLacrosOnlyDisabled() {
-    scoped_feature_list_.InitAndDisableFeature(
-        ash::standalone_browser::features::kLacrosOnly);
+  OSSettingsMochaTestRevampAndLacrosOnlyDisabled() {
+    scoped_feature_list_.InitWithFeatures(
+        /*enabled=*/{},
+        /*disabled=*/{
+            ash::standalone_browser::features::kLacrosOnly,
+            ash::features::kOsSettingsRevampWayfinding,
+        });
   }
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-IN_PROC_BROWSER_TEST_F(OSSettingsPeopleTestLacrosOnlyDisabled,
+IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestRevampAndLacrosOnlyDisabled,
                        OsPeoplePageAccountManagerSubpage) {
   RunSettingsTest("os_people_page/account_manager_subpage_test.js");
 }
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
index dec9555..079bb38a 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -36,6 +36,10 @@
       'ash::standalone_browser::features::kLacrosOnly',
       'ash::standalone_browser::features::kLacrosProfileMigrationForceOff',
     ],
+    disabled: [
+      // The account manager subpage does not exist under the revamp.
+      'ash::features::kOsSettingsRevampWayfinding',
+    ],
   },
 ],
 ].forEach(test => registerTest(...test));
diff --git a/chrome/test/data/webui/tab_search/tab_organization_page_test.ts b/chrome/test/data/webui/tab_search/tab_organization_page_test.ts
index 579d0e8..0bbdfe773f 100644
--- a/chrome/test/data/webui/tab_search/tab_organization_page_test.ts
+++ b/chrome/test/data/webui/tab_search/tab_organization_page_test.ts
@@ -100,6 +100,42 @@
         override);
   }
 
+  function createMultiOrganizationSession(
+      count: number, override: Partial<TabOrganizationSession> = {}) {
+    const organizations: Object[] = [];
+    for (let i = 0; i < count; i++) {
+      organizations.push(
+          {
+            organizationId: i,
+            name: stringToMojoString16('Organization ' + i),
+            tabs: [
+              createTab({
+                title: 'Tab 1 Organization ' + i,
+                url: {url: 'https://tab-1.com/'},
+              }),
+              createTab({
+                title: 'Tab 2 Organization ' + i,
+                url: {url: 'https://tab-2.com/'},
+              }),
+              createTab({
+                title: 'Tab 3 Organization ' + i,
+                url: {url: 'https://tab-3.com/'},
+              }),
+            ],
+          },
+      );
+    }
+
+    return Object.assign(
+        {
+          sessionId: 1,
+          state: TabOrganizationState.kSuccess,
+          organizations: organizations,
+          error: TabOrganizationError.kNone,
+        },
+        override);
+  }
+
   test('Organize tabs starts request', async () => {
     await tabOrganizationPageSetup();
     assertEquals(0, testApiProxy.getCallCount('requestTabOrganization'));
@@ -264,7 +300,7 @@
     assertFalse(focusableElement2.matches(':focus'));
   });
 
-  test('Create group accepts organization', async () => {
+  test('Single organization create group accepts organization', async () => {
     await tabOrganizationPageSetup();
 
     testApiProxy.getCallbackRouterRemote().tabOrganizationSessionUpdated(
@@ -288,6 +324,39 @@
     assertEquals(1, testApiProxy.getCallCount('acceptTabOrganization'));
   });
 
+  test(
+      'Multi organization create groups accepts all organizations',
+      async () => {
+        loadTimeData.overrideValues({
+          multiTabOrganizationEnabled: true,
+        });
+
+        await tabOrganizationPageSetup();
+
+        const organizationCount = 3;
+        testApiProxy.getCallbackRouterRemote().tabOrganizationSessionUpdated(
+            createMultiOrganizationSession(organizationCount));
+        await flushTasks();
+
+        assertEquals(0, testApiProxy.getCallCount('acceptTabOrganization'));
+
+        const results = tabOrganizationPage.shadowRoot!.querySelector(
+            'tab-organization-results');
+        assertTrue(!!results);
+        const actions = results.shadowRoot!.querySelector(
+            'tab-organization-results-actions');
+        assertTrue(!!actions);
+        const createGroupsButton =
+            actions.shadowRoot!.querySelector<HTMLElement>('#createButton');
+        assertTrue(!!createGroupsButton);
+        createGroupsButton.click();
+        await flushTasks();
+
+        assertEquals(
+            organizationCount,
+            testApiProxy.getCallCount('acceptTabOrganization'));
+      });
+
   test('Group cancel button rejects organization', async () => {
     loadTimeData.overrideValues({
       multiTabOrganizationEnabled: true,
@@ -315,7 +384,7 @@
     assertEquals(1, testApiProxy.getCallCount('rejectTabOrganization'));
   });
 
-  test('Refresh rejects organization', async () => {
+  test('Single organization refresh rejects organization', async () => {
     const rejectFinalSuggestion = 'Clear';
 
     loadTimeData.overrideValues({
@@ -349,6 +418,34 @@
     assertEquals(1, testApiProxy.getCallCount('rejectTabOrganization'));
   });
 
+  test('Multi organization refresh rejects session', async () => {
+    loadTimeData.overrideValues({
+      multiTabOrganizationEnabled: true,
+    });
+
+    await tabOrganizationPageSetup();
+
+    testApiProxy.getCallbackRouterRemote().tabOrganizationSessionUpdated(
+        createSession({state: TabOrganizationState.kSuccess}));
+    await flushTasks();
+
+    assertEquals(0, testApiProxy.getCallCount('rejectSession'));
+
+    const results = tabOrganizationPage.shadowRoot!.querySelector(
+        'tab-organization-results');
+    assertTrue(!!results);
+    const actions =
+        results.shadowRoot!.querySelector('tab-organization-results-actions');
+    assertTrue(!!actions);
+    const refreshButton =
+        actions.shadowRoot!.querySelector<HTMLElement>('#refreshButton');
+    assertTrue(!!refreshButton);
+    refreshButton.click();
+    await flushTasks();
+
+    assertEquals(1, testApiProxy.getCallCount('rejectSession'));
+  });
+
   test(
       'Refresh button has different label for multiple suggestions',
       async () => {
@@ -362,34 +459,10 @@
 
         await tabOrganizationPageSetup();
 
-        const multiOrganizationSession = {
-          sessionId: 1,
-          state: TabOrganizationState.kSuccess,
-          organizations: [
-            {
-              organizationId: 1,
-              name: stringToMojoString16('foo'),
-              tabs: [
-                createTab({title: 'Tab 1', url: {url: 'https://tab-1.com/'}}),
-                createTab({title: 'Tab 2', url: {url: 'https://tab-2.com/'}}),
-                createTab({title: 'Tab 3', url: {url: 'https://tab-3.com/'}}),
-              ],
-            },
-            {
-              organizationId: 2,
-              name: stringToMojoString16('bar'),
-              tabs: [
-                createTab({title: 'Tab 4', url: {url: 'https://tab-4.com/'}}),
-                createTab({title: 'Tab 5', url: {url: 'https://tab-5.com/'}}),
-                createTab({title: 'Tab 6', url: {url: 'https://tab-6.com/'}}),
-              ],
-            },
-          ],
-          error: TabOrganizationError.kNone,
-        };
+
 
         testApiProxy.getCallbackRouterRemote().tabOrganizationSessionUpdated(
-            multiOrganizationSession);
+            createMultiOrganizationSession(2));
         await flushTasks();
 
         const results = tabOrganizationPage.shadowRoot!.querySelector(
diff --git a/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.ts b/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.ts
index 9609b68..36be767 100644
--- a/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.ts
+++ b/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.ts
@@ -23,6 +23,7 @@
       'openRecentlyClosedEntry',
       'requestTabOrganization',
       'removeTabFromOrganization',
+      'rejectSession',
       'restartSession',
       'switchToTab',
       'saveRecentlyClosedExpandedPref',
@@ -84,6 +85,10 @@
         'removeTabFromOrganization', sessionId, organizationId, tab);
   }
 
+  rejectSession() {
+    this.methodCalled('rejectSession');
+  }
+
   restartSession() {
     this.methodCalled('restartSession');
   }
diff --git a/chrome/updater/net/network_fetcher_win.cc b/chrome/updater/net/network_fetcher_win.cc
index 7ae4a9e2..9b44987a 100644
--- a/chrome/updater/net/network_fetcher_win.cc
+++ b/chrome/updater/net/network_fetcher_win.cc
@@ -43,7 +43,7 @@
         policy_service_proxy_configuration) {
   if (policy_service_proxy_configuration) {
     return base::MakeRefCounted<winhttp::ProxyConfiguration>(winhttp::ProxyInfo{
-        policy_service_proxy_configuration->proxy_auto_detect.value_or(true),
+        policy_service_proxy_configuration->proxy_auto_detect,
         base::SysUTF8ToWide(
             policy_service_proxy_configuration->proxy_pac_url.value_or("")),
         base::SysUTF8ToWide(
@@ -192,6 +192,9 @@
     ScopedImpersonation impersonate;
     if (IsSystemInstall()) {
       HResultOr<ScopedKernelHANDLE> token = GetLoggedOnUserToken();
+      VLOG_IF(2, !token.has_value())
+          << __func__ << ": GetLoggedOnUserToken failed: " << std::hex
+          << token.error();
       if (token.has_value()) {
         const HRESULT hr = impersonate.Impersonate(token.value().get());
         VLOG(2)
diff --git a/chrome/updater/policy/service.cc b/chrome/updater/policy/service.cc
index ad7604f..7e393301 100644
--- a/chrome/updater/policy/service.cc
+++ b/chrome/updater/policy/service.cc
@@ -710,6 +710,8 @@
     }
   } else if (proxy_mode.policy().compare(kProxyModeAutoDetect) == 0) {
     policy_service_proxy_configuration.proxy_auto_detect = true;
+  } else {
+    is_policy_config_valid = false;
   }
 
   if (!is_policy_config_valid) {
diff --git a/chrome/updater/policy/service.h b/chrome/updater/policy/service.h
index 0f68715b..bd2d6c1 100644
--- a/chrome/updater/policy/service.h
+++ b/chrome/updater/policy/service.h
@@ -199,7 +199,10 @@
   static std::optional<PolicyServiceProxyConfiguration> Get(
       scoped_refptr<PolicyService> policy_service);
 
-  std::optional<bool> proxy_auto_detect;
+  // Note `Get()` returns a nullopt when there's no proxy policies. Otherwise
+  // `proxy_auto_detect` must have a value, and is only set to true when the
+  // policy chooses "auto-detect".
+  bool proxy_auto_detect = false;
   std::optional<std::string> proxy_pac_url;
   std::optional<std::string> proxy_url;
 };
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 40f6092..80dc386f 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-15790.0.0
\ No newline at end of file
+15803.0.0
\ No newline at end of file
diff --git a/clank b/clank
index 5ac8fb2..eadffcd 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 5ac8fb250ea25c91a12158f768d4f5c03976f15e
+Subproject commit eadffcd4b5ec79ec69e29f75c6695edf9c69aff1
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index 8e165954..1dc84c1 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -87,9 +87,7 @@
 // Returns true if the scheme given by |url| is one for which autofill is
 // allowed to activate. By default this only returns true for HTTP and HTTPS.
 bool HasAllowedScheme(const GURL& url) {
-  return url.SchemeIsHTTPOrHTTPS() ||
-         base::FeatureList::IsEnabled(
-             features::test::kAutofillAllowNonHttpActivation);
+  return url.SchemeIsHTTPOrHTTPS();
 }
 
 std::string ServerTypesToString(const AutofillField* field) {
diff --git a/components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h b/components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h
index 22f859a9..c819661b 100644
--- a/components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h
+++ b/components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h
@@ -44,9 +44,9 @@
   virtual VirtualCardEnrollmentBubbleSource
   GetVirtualCardEnrollmentBubbleSource() const = 0;
 
-  // Returns the currently active virtual card enroll bubble view. Can be
-  // nullptr if no bubble is visible.
-  virtual AutofillBubbleBase* GetVirtualCardEnrollBubbleView() const = 0;
+  // Returns the currently active virtual card enroll or confirmation bubble
+  // view. Can be nullptr if no bubble is visible.
+  virtual AutofillBubbleBase* GetVirtualCardBubbleView() const = 0;
 
 #if !BUILDFLAG(IS_ANDROID)
   // Hides the bubble and icon if it is showing.
@@ -55,6 +55,9 @@
   // Returns true if bubble is already accepted and the virtual card enrollment
   // process is in progress.
   virtual bool IsEnrollmentInProgress() const = 0;
+
+  // Returns true if server request for virtual card enrollment is complete.
+  virtual bool IsEnrollmentComplete() const = 0;
 #endif
 
   // Virtual card enroll button takes card information to enroll into a VCN.
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index a4d3ba1..ffd5124 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -677,13 +677,6 @@
 
 namespace test {
 
-// Controls whether autofill activates on non-HTTP(S) pages. Useful for
-// automated tests with data URLS in cases where it's too difficult to use the
-// embedded test server. Generally avoid using.
-BASE_FEATURE(kAutofillAllowNonHttpActivation,
-             "AutofillAllowNonHttpActivation",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 // Testing tool that collects metrics during a run of the captured site tests
 // and dumps the collected metrics into a specified output directory.
 // For each test, a file named {test-name}.txt is created. It contains all the
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index aec4638b..5c4b3fc 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -236,8 +236,6 @@
 namespace test {
 
 COMPONENT_EXPORT(AUTOFILL)
-BASE_DECLARE_FEATURE(kAutofillAllowNonHttpActivation);
-COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillCapturedSiteTestsMetricsScraper);
 COMPONENT_EXPORT(AUTOFILL)
 extern const base::FeatureParam<std::string>
diff --git a/components/history/core/browser/sync/history_sync_bridge.cc b/components/history/core/browser/sync/history_sync_bridge.cc
index 9b6c772..128d582 100644
--- a/components/history/core/browser/sync/history_sync_bridge.cc
+++ b/components/history/core/browser/sync/history_sync_bridge.cc
@@ -175,6 +175,11 @@
   // Definitionally, any visit from Sync is known to sync.
   row.is_known_to_sync = true;
 
+  // Transfer app_id if present.
+  if (specifics.has_app_id()) {
+    row.app_id = specifics.app_id();
+  }
+
   // Reconstruct the page transition - first get the core type.
   int page_transition = syncer::FromSyncPageTransition(
       specifics.page_transition().core_transition());
@@ -300,7 +305,8 @@
     const GURL& referrer_url,
     const std::vector<GURL>& favicon_urls,
     int64_t local_cluster_id,
-    std::vector<VisitID>* included_visit_ids) {
+    std::vector<VisitID>* included_visit_ids,
+    std::optional<std::string> app_id) {
   DCHECK(!local_cache_guid.empty());
   DCHECK(!redirect_visits.empty());
 
@@ -442,6 +448,9 @@
   }
 
   history->set_originator_cluster_id(local_cluster_id);
+  if (app_id) {
+    history->set_app_id(*app_id);
+  }
 
   // The entity name is used for debugging purposes; choose something that's a
   // decent tradeoff between "unique" and "readable".
@@ -1064,9 +1073,10 @@
     // should be the same (except potentially in unit tests).
     int64_t local_cluster_id = history_backend_->GetClusterIdContainingVisit(
         redirect_visits.front().visit_id);
-    entities.push_back(MakeEntityData(
-        GetLocalCacheGuid(), annotated_visits, chain_middle_trimmed,
-        referrer_url, favicon_urls, local_cluster_id, included_visit_ids));
+    entities.push_back(MakeEntityData(GetLocalCacheGuid(), annotated_visits,
+                                      chain_middle_trimmed, referrer_url,
+                                      favicon_urls, local_cluster_id,
+                                      included_visit_ids, final_visit.app_id));
   }
 
   return entities;
diff --git a/components/history/core/browser/sync/history_sync_bridge_unittest.cc b/components/history/core/browser/sync/history_sync_bridge_unittest.cc
index eb35f53..ae61d15 100644
--- a/components/history/core/browser/sync/history_sync_bridge_unittest.cc
+++ b/components/history/core/browser/sync/history_sync_bridge_unittest.cc
@@ -34,6 +34,9 @@
 
 namespace history {
 
+const std::string kTestAppId = "org.chromium.dino.stegosaurus";
+const std::string kTestAppId2 = "org.chromium.dino.velociraptor";
+
 namespace {
 
 using testing::_;
@@ -48,6 +51,7 @@
     const std::string& originator_cache_guid,
     const std::vector<GURL>& urls,
     const std::vector<VisitID>& originator_visit_ids = {},
+    std::optional<std::string> app_id = std::nullopt,
     const bool has_url_keyed_image = false,
     const std::vector<VisitContentModelAnnotations::Category>& categories = {},
     const std::vector<std::string>& related_searches = {}) {
@@ -67,6 +71,9 @@
           sync_pb::SyncEnums_PageTransitionRedirectType_SERVER_REDIRECT);
     }
   }
+  if (app_id) {
+    specifics.set_app_id(*app_id);
+  }
   specifics.set_has_url_keyed_image(has_url_keyed_image);
   for (const auto& category : categories) {
     auto* category_to_sync = specifics.add_categories();
@@ -83,12 +90,13 @@
     const std::string& originator_cache_guid,
     const GURL& url,
     VisitID originator_visit_id = 0,
+    std::optional<std::string> app_id = std::nullopt,
     const bool has_url_keyed_image = false,
     const std::vector<VisitContentModelAnnotations::Category>& categories = {},
     const std::vector<std::string>& related_searches = {}) {
   return CreateSpecifics(visit_time, originator_cache_guid, std::vector{url},
-                         std::vector{originator_visit_id}, has_url_keyed_image,
-                         categories, related_searches);
+                         std::vector{originator_visit_id}, app_id,
+                         has_url_keyed_image, categories, related_searches);
 }
 
 syncer::EntityData SpecificsToEntityData(
@@ -293,7 +301,8 @@
   std::pair<URLRow, VisitRow> AddVisitToBackendAndAdvanceClock(
       const GURL& url,
       ui::PageTransition transition,
-      VisitID referring_visit = kInvalidVisitID) {
+      VisitID referring_visit = kInvalidVisitID,
+      std::optional<std::string> app_id = std::nullopt) {
     // After grabbing the visit time, advance the mock time so that the next
     // visit will get a unique time.
     base::Time visit_time = base::Time::Now();
@@ -316,6 +325,7 @@
         ui::PageTransitionFromInt(transition | ui::PAGE_TRANSITION_CHAIN_START |
                                   ui::PAGE_TRANSITION_CHAIN_END);
     visit_row.referring_visit = referring_visit;
+    visit_row.app_id = app_id;
     visit_row.visit_id = backend()->AddVisit(visit_row);
 
     return {url_row, visit_row};
@@ -475,11 +485,13 @@
   const std::vector<std::string> related_searches(
       {related_search_1, related_search_2});
 
-  AddVisitToBackendAndAdvanceClock(local_url, ui::PAGE_TRANSITION_LINK);
+  AddVisitToBackendAndAdvanceClock(local_url, ui::PAGE_TRANSITION_LINK,
+                                   /*referring_visit=*/kInvalidVisitID,
+                                   kTestAppId);
 
   sync_pb::HistorySpecifics remote_entity = CreateSpecifics(
       base::Time::Now() - base::Minutes(1), remote_cache_guid, remote_url, {},
-      has_url_keyed_image, categories, related_searches);
+      kTestAppId2, has_url_keyed_image, categories, related_searches);
 
   ApplyInitialSyncChanges({remote_entity});
 
@@ -494,6 +506,9 @@
   EXPECT_EQ(backend()->GetVisits()[1].url_id, backend()->GetURLs()[1].id());
   EXPECT_EQ(backend()->GetVisits()[1].originator_cache_guid, remote_cache_guid);
   EXPECT_TRUE(backend()->GetVisits()[1].is_known_to_sync);
+  EXPECT_EQ(backend()->GetVisits()[0].app_id, kTestAppId);
+  EXPECT_EQ(backend()->GetVisits()[1].app_id, kTestAppId2);
+
   // Check that the remote visit's annotation info got synced.
   // NOTE: Annotation info is present on the last remote visit.
   const std::vector<AnnotatedVisit> annotated_visits =
@@ -531,25 +546,29 @@
 TEST_F(HistorySyncBridgeTest, MergesRemoteChanges) {
   const GURL remote_url("https://remote.com");
 
-  sync_pb::HistorySpecifics remote_entity = CreateSpecifics(
-      base::Time::Now() - base::Minutes(1), "remote_cache_guid", remote_url);
+  sync_pb::HistorySpecifics remote_entity =
+      CreateSpecifics(base::Time::Now() - base::Minutes(1), "remote_cache_guid",
+                      remote_url, {}, kTestAppId);
 
   // Start Sync the first time, so the remote data gets written to the local DB.
   ApplyInitialSyncChanges({remote_entity});
   ASSERT_EQ(backend()->GetURLs().size(), 1u);
   ASSERT_EQ(backend()->GetVisits().size(), 1u);
   ASSERT_EQ(backend()->GetVisits()[0].visit_duration, base::TimeDelta());
+  ASSERT_EQ(backend()->GetVisits()[0].app_id, kTestAppId);
 
   // Stop Sync, then start it again so the same data gets downloaded again.
   ApplyDisableSyncChanges();
   // ...but the data has been updated in the meantime.
   remote_entity.set_visit_duration_micros(1000);
+  remote_entity.set_app_id(kTestAppId2);
   ApplyInitialSyncChanges({remote_entity});
 
   // The entries in the local DB should have been updated (*not* duplicated).
   ASSERT_EQ(backend()->GetURLs().size(), 1u);
   ASSERT_EQ(backend()->GetVisits().size(), 1u);
   EXPECT_EQ(backend()->GetVisits()[0].visit_duration, base::Microseconds(1000));
+  ASSERT_EQ(backend()->GetVisits()[0].app_id, kTestAppId2);
 }
 
 TEST_F(HistorySyncBridgeTest, DoesNotApplyUnsyncableRemoteChanges) {
diff --git a/components/history_embeddings/BUILD.gn b/components/history_embeddings/BUILD.gn
index c86e19fd..292a52d2 100644
--- a/components/history_embeddings/BUILD.gn
+++ b/components/history_embeddings/BUILD.gn
@@ -21,6 +21,10 @@
     "//components/history_embeddings/proto:history_embeddings_proto",
     "//components/keyed_service/core",
     "//components/os_crypt/sync",
+    "//content/public/browser",
+    "//content/public/common",
+    "//mojo/public/cpp/bindings",
+    "//services/service_manager",
     "//sql",
     "//third_party/zlib/google:compression_utils",
     "//url",
diff --git a/components/history_embeddings/DEPS b/components/history_embeddings/DEPS
index 22121a38..6237e997 100644
--- a/components/history_embeddings/DEPS
+++ b/components/history_embeddings/DEPS
@@ -1,7 +1,11 @@
 include_rules = [
   "+components/keyed_service/core",
   "+components/os_crypt/sync",
+  "+content/public/browser",
+  "+mojo/public/cpp/bindings",
+  "+services/service_manager/public/cpp",
   "+sql",
+  "+third_party/blink/public",
   "+third_party/zlib",
   "+url",
 ]
diff --git a/components/history_embeddings/history_embeddings_features.cc b/components/history_embeddings/history_embeddings_features.cc
index e6391c2..8a5cac0e 100644
--- a/components/history_embeddings/history_embeddings_features.cc
+++ b/components/history_embeddings/history_embeddings_features.cc
@@ -12,4 +12,9 @@
              "HistoryEmbeddings",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+const base::FeatureParam<int> kPassageExtractionMaxWordsPerAggregatePassage(
+    &kHistoryEmbeddings,
+    "PassageExtractionMaxWordsPerAggregatePassage",
+    200);
+
 }  // namespace history_embeddings
diff --git a/components/history_embeddings/history_embeddings_features.h b/components/history_embeddings/history_embeddings_features.h
index e5a1f25b..22f614d 100644
--- a/components/history_embeddings/history_embeddings_features.h
+++ b/components/history_embeddings/history_embeddings_features.h
@@ -6,11 +6,18 @@
 #define COMPONENTS_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_FEATURES_H_
 
 #include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
 
 namespace history_embeddings {
 
 BASE_DECLARE_FEATURE(kHistoryEmbeddings);
 
+// Specifies the `max_words_per_aggregate_passage` parameter for the
+// DocumentChunker passage extraction algorithm. A passage from a single
+// node can exceed this maximum, but aggregation keeps within the limit.
+extern const base::FeatureParam<int>
+    kPassageExtractionMaxWordsPerAggregatePassage;
+
 }  // namespace history_embeddings
 
 #endif  // COMPONENTS_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_FEATURES_H_
diff --git a/components/history_embeddings/history_embeddings_service.cc b/components/history_embeddings/history_embeddings_service.cc
index 4dba6e37..1ce6560e 100644
--- a/components/history_embeddings/history_embeddings_service.cc
+++ b/components/history_embeddings/history_embeddings_service.cc
@@ -4,18 +4,63 @@
 
 #include "components/history_embeddings/history_embeddings_service.h"
 
+#include <numeric>
+
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/functional/bind.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
+#include "base/time/time.h"
 #include "components/history_embeddings/history_embeddings_features.h"
 #include "components/history_embeddings/sql_database.h"
+#include "mojo/public/cpp/bindings/callback_helpers.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/mojom/content_extraction/inner_text.mojom.h"
 
 namespace history_embeddings {
 
+UrlPassages::UrlPassages() = default;
+UrlPassages::~UrlPassages() = default;
+UrlPassages::UrlPassages(UrlPassages&&) = default;
+UrlPassages& UrlPassages::operator=(UrlPassages&&) = default;
+
+void OnGotInnerText(mojo::Remote<blink::mojom::InnerTextAgent> remote,
+                    base::TimeTicks start_time,
+                    GURL url,
+                    base::OnceCallback<void(UrlPassages)> callback,
+                    blink::mojom::InnerTextFramePtr mojo_frame) {
+  const base::TimeDelta extraction_time = base::TimeTicks::Now() - start_time;
+  UrlPassages url_passages;
+  url_passages.url = std::move(url);
+  if (mojo_frame) {
+    for (const auto& segment : mojo_frame->segments) {
+      if (segment->is_text()) {
+        url_passages.passages.push_back(segment->get_text());
+      }
+    }
+    base::UmaHistogramTimes("History.Embeddings.Passages.ExtractionTime",
+                            extraction_time);
+  }
+  const size_t total_text_size =
+      std::reduce(url_passages.passages.cbegin(), url_passages.passages.cend(),
+                  0u, [](size_t acc, const std::string& passage) {
+                    return acc + passage.size();
+                  });
+  base::UmaHistogramCounts1000("History.Embeddings.Passages.PassageCount",
+                               url_passages.passages.size());
+  base::UmaHistogramCounts10M("History.Embeddings.Passages.TotalTextSize",
+                              total_text_size);
+  std::move(callback).Run(std::move(url_passages));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 HistoryEmbeddingsService::HistoryEmbeddingsService(
-    const base::FilePath& storage_dir) {
+    const base::FilePath& storage_dir)
+    : weak_ptr_factory_(this) {
   if (!base::FeatureList::IsEnabled(kHistoryEmbeddings)) {
     // If the feature flag is disabled, skip initialization. Note we don't also
     // check the pref here, because the pref can change at runtime.
@@ -31,8 +76,35 @@
 
 HistoryEmbeddingsService::~HistoryEmbeddingsService() = default;
 
+void HistoryEmbeddingsService::RetrievePassages(content::RenderFrameHost& host,
+                                                PassagesCallback callback) {
+  const base::TimeTicks start_time = base::TimeTicks::Now();
+  mojo::Remote<blink::mojom::InnerTextAgent> agent;
+  host.GetRemoteInterfaces()->GetInterface(agent.BindNewPipeAndPassReceiver());
+  auto params = blink::mojom::InnerTextParams::New();
+  params->max_words_per_aggregate_passage =
+      std::max(0, kPassageExtractionMaxWordsPerAggregatePassage.Get());
+  auto* agent_ptr = agent.get();
+  agent_ptr->GetInnerText(
+      std::move(params),
+      mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+          base::BindOnce(
+              &OnGotInnerText, std::move(agent), start_time,
+              host.GetLastCommittedURL(),
+              base::BindOnce(&HistoryEmbeddingsService::OnPassagesRetrieved,
+                             weak_ptr_factory_.GetWeakPtr(),
+                             std::move(callback))),
+          nullptr));
+}
+
 void HistoryEmbeddingsService::Shutdown() {
   database_.Reset();
 }
 
+void HistoryEmbeddingsService::OnPassagesRetrieved(PassagesCallback callback,
+                                                   UrlPassages url_passages) {
+  // TODO(orinj): Store in database. For now just notify callback for testing.
+  std::move(callback).Run(std::move(url_passages));
+}
+
 }  // namespace history_embeddings
diff --git a/components/history_embeddings/history_embeddings_service.h b/components/history_embeddings/history_embeddings_service.h
index fe24576b..ea4796f6 100644
--- a/components/history_embeddings/history_embeddings_service.h
+++ b/components/history_embeddings/history_embeddings_service.h
@@ -5,13 +5,34 @@
 #ifndef COMPONENTS_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_SERVICE_H_
 #define COMPONENTS_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_SERVICE_H_
 
+#include <string>
+#include <vector>
+
 #include "base/files/file_path.h"
+#include "base/functional/callback.h"
+#include "base/memory/weak_ptr.h"
 #include "base/threading/sequence_bound.h"
 #include "components/history_embeddings/sql_database.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "content/public/browser/render_frame_host.h"
+#include "url/gurl.h"
 
 namespace history_embeddings {
 
+struct UrlPassages {
+  UrlPassages();
+  ~UrlPassages();
+  UrlPassages(const UrlPassages&) = delete;
+  UrlPassages& operator=(const UrlPassages&) = delete;
+  UrlPassages(UrlPassages&&);
+  UrlPassages& operator=(UrlPassages&&);
+
+  GURL url;
+  std::vector<std::string> passages;
+};
+
+using PassagesCallback = base::OnceCallback<void(UrlPassages)>;
+
 class HistoryEmbeddingsService : public KeyedService {
  public:
   // `storage_dir` will generally be the Profile directory.
@@ -20,13 +41,24 @@
   HistoryEmbeddingsService& operator=(const HistoryEmbeddingsService&) = delete;
   ~HistoryEmbeddingsService() override;
 
+  // Initiate async passage extraction from given host's main frame.
+  // When extraction completes, the passages will be stored in the database
+  // and then given to the callback.
+  void RetrievePassages(content::RenderFrameHost& host,
+                        PassagesCallback callback);
+
   // KeyedService:
   void Shutdown() override;
 
  private:
+  // Called indirectly via RetrievePassages when passage extraction completes.
+  void OnPassagesRetrieved(PassagesCallback callback, UrlPassages passages);
+
   // The underlying SQL database, bound to a separate storage sequence.
   // This will be null if the feature flag is disabled.
   base::SequenceBound<SqlDatabase> database_;
+
+  base::WeakPtrFactory<HistoryEmbeddingsService> weak_ptr_factory_;
 };
 
 }  // namespace history_embeddings
diff --git a/components/lens/lens_features.cc b/components/lens/lens_features.cc
index 16df1ca..255dde51 100644
--- a/components/lens/lens_features.cc
+++ b/components/lens/lens_features.cc
@@ -175,5 +175,9 @@
   return kShouldIssueProcessPrewarmingForLens.Get();
 }
 
+bool IsLensOverlayEnabled() {
+  return base::FeatureList::IsEnabled(kLensOverlay);
+}
+
 }  // namespace features
 }  // namespace lens
diff --git a/components/lens/lens_features.h b/components/lens/lens_features.h
index c1bbfed..66e3b0c 100644
--- a/components/lens/lens_features.h
+++ b/components/lens/lens_features.h
@@ -195,6 +195,10 @@
 // is shown.
 COMPONENT_EXPORT(LENS_FEATURES)
 extern bool GetShouldIssueProcessPrewarmingForLens();
+
+// Returns whether to the Lens overlay is enabled
+COMPONENT_EXPORT(LENS_FEATURES)
+extern bool IsLensOverlayEnabled();
 }  // namespace features
 }  // namespace lens
 
diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc
index 75b56bc..970dc242 100644
--- a/components/optimization_guide/core/optimization_guide_features.cc
+++ b/components/optimization_guide/core/optimization_guide_features.cc
@@ -403,23 +403,39 @@
 }
 
 bool IsModelQualityLoggingEnabledForFeature(
-    proto::ModelExecutionFeature feature_name) {
+    proto::ModelExecutionFeature feature) {
   if (!IsModelQualityLoggingEnabled()) {
     return false;
   }
 
-  // Disable logging for test features.
-  if (feature_name ==
+  // Always disable logging for test features.
+  if (feature ==
           proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_UNSPECIFIED ||
-      feature_name ==
-          proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_TEST) {
+      feature == proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_TEST) {
     return false;
   }
 
+  bool default_logging_enabled = false;
+  switch (feature) {
+    case proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_COMPOSE:
+    case proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_TAB_ORGANIZATION:
+    case proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_WALLPAPER_SEARCH:
+      // Enable logging when you have approvals. For new features please
+      // consult with components/optimization_guide/core/model_quality/OWNERS to
+      // discuss if you need logging or not for your feature.
+      default_logging_enabled = true;
+      break;
+    case proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_UNSPECIFIED:
+    case proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_TEST:
+      // Logging disabled.
+      NOTREACHED();
+      break;
+  }
+
   std::string param_name =
-      base::ToLowerASCII(proto::ModelExecutionFeature_Name(feature_name));
+      base::ToLowerASCII(proto::ModelExecutionFeature_Name(feature));
   return GetFieldTrialParamByFeatureAsBool(kModelQualityLogging, param_name,
-                                           true);
+                                           default_logging_enabled);
 }
 
 bool IsRemoteFetchingEnabled() {
diff --git a/components/optimization_guide/core/optimization_guide_features_unittest.cc b/components/optimization_guide/core/optimization_guide_features_unittest.cc
index b61f1eb..dceccfe 100644
--- a/components/optimization_guide/core/optimization_guide_features_unittest.cc
+++ b/components/optimization_guide/core/optimization_guide_features_unittest.cc
@@ -95,6 +95,25 @@
       proto::MODEL_EXECUTION_FEATURE_UNSPECIFIED));
 }
 
+TEST(OptimizationGuideFeaturesTest,
+     ModelQualityLoggingAlwaysDisabledForTestAndUnspecifiedFeatures) {
+  base::test::ScopedFeatureList scoped_feature_list;
+
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      features::kModelQualityLogging,
+      {{"model_execution_feature_test", "true"},
+       {"model_execution_feature_unspecified", "true"}});
+
+  EXPECT_TRUE(features::IsModelQualityLoggingEnabled());
+
+  // Test and Unspecified features should have logging always disabled not
+  // allowed to be controlled via finch.
+  EXPECT_FALSE(features::IsModelQualityLoggingEnabledForFeature(
+      proto::MODEL_EXECUTION_FEATURE_TEST));
+  EXPECT_FALSE(features::IsModelQualityLoggingEnabledForFeature(
+      proto::MODEL_EXECUTION_FEATURE_UNSPECIFIED));
+}
+
 TEST(OptimizationGuideFeaturesTest, ComposeModelQualityLoggingDisabled) {
   base::test::ScopedFeatureList scoped_feature_list;
 
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
index 25672be..945b01f 100644
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
@@ -74,6 +74,10 @@
 // immersive fullscreen session.
 - (BOOL)immersiveFullscreen;
 
+// The sheet parent that should be used. In immersive fullscreen the preferred
+// sheet parent is the root window (the browser window).
+- (NSWindow*)preferredSheetParent;
+
 // Identifier for the NativeWidgetMac from which this window was created. This
 // may be used to look up the NativeWidgetMacNSWindowHost in the browser process
 // or the NativeWidgetNSWindowBridge in a display process.
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
index 568f0c2..eca5cea 100644
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
@@ -840,6 +840,10 @@
   return NO;
 }
 
+- (NSWindow*)preferredSheetParent {
+  return [self immersiveFullscreen] ? [self rootWindow] : self;
+}
+
 #ifndef NDEBUG
 - (NSString*)debugDescription {
   if (!self.title.length) {
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
index 3f4ac8e..5535f9c5 100644
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -1790,6 +1790,10 @@
   host_->OnVisibilityChanged(window_visible_);
 
   NSWindow* parent_window = parent_->ns_window();
+  if (NativeWidgetMacNSWindow* parent_widget_window =
+          base::apple::ObjCCast<NativeWidgetMacNSWindow>(parent_window)) {
+    parent_window = [parent_widget_window preferredSheetParent];
+  }
   DCHECK(parent_window);
   NSWindow* __weak weak_window = window_;
 
diff --git a/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm b/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm
index 824cfaa..a1a6a83 100644
--- a/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm
+++ b/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm
@@ -412,18 +412,12 @@
   auto ended_callback = base::BindRepeating(
       &SelectFileDialogBridge::OnPanelEnded, weak_factory_.GetWeakPtr());
 
-  // If the owning_window_ widget is currently in an immersive fullscreen
-  // session, add then remove the panel as a child. Otherwise the following
-  // -beginSheetModalForWindow:completionHandler: call will place the panel
-  // z-order behind the owning widget. See http://crbug/40282144.
-  NativeWidgetMacNSWindow* owning_window_widget =
-      base::apple::ObjCCast<NativeWidgetMacNSWindow>(owning_window_);
-  if (owning_window_widget && [owning_window_widget immersiveFullscreen]) {
-    [owning_window_ addChildWindow:panel_ ordered:NSWindowAbove];
-    [owning_window_ removeChildWindow:panel_];
+  NSWindow* sheet_parent = owning_window_;
+  if (NativeWidgetMacNSWindow* sheet_parent_widget_window =
+          base::apple::ObjCCast<NativeWidgetMacNSWindow>(sheet_parent)) {
+    sheet_parent = [sheet_parent_widget_window preferredSheetParent];
   }
-
-  [panel_ beginSheetModalForWindow:owning_window_
+  [panel_ beginSheetModalForWindow:sheet_parent
                  completionHandler:^(NSInteger result) {
                    ended_callback.Run(result != NSModalResponseOK);
                  }];
diff --git a/components/safe_browsing/content/browser/BUILD.gn b/components/safe_browsing/content/browser/BUILD.gn
index 418baef..8b9f1a9 100644
--- a/components/safe_browsing/content/browser/BUILD.gn
+++ b/components/safe_browsing/content/browser/BUILD.gn
@@ -127,6 +127,7 @@
     "//components/security_interstitials/content:security_interstitial_page",
     "//components/security_interstitials/core",
     "//components/security_interstitials/core:unsafe_resource",
+    "//components/sessions",
     "//components/signin/public/identity_manager",
     "//components/unified_consent",
     "//components/version_info",
diff --git a/components/safe_browsing/content/browser/async_check_tracker_unittest.cc b/components/safe_browsing/content/browser/async_check_tracker_unittest.cc
index cc4d0b2..5562a27 100644
--- a/components/safe_browsing/content/browser/async_check_tracker_unittest.cc
+++ b/components/safe_browsing/content/browser/async_check_tracker_unittest.cc
@@ -120,7 +120,7 @@
         /*hash_realtime_service=*/nullptr,
         /*hash_realtime_selection=*/
         hash_realtime_utils::HashRealTimeSelection::kNone,
-        /*is_async_check=*/true);
+        /*is_async_check=*/true, SessionID::InvalidValue());
     checker->AddUrlInRedirectChainForTesting(url_);
     tracker_->TransferUrlChecker(std::move(checker));
   }
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle.cc b/components/safe_browsing/content/browser/browser_url_loader_throttle.cc
index f1779883..3d78b15b 100644
--- a/components/safe_browsing/content/browser/browser_url_loader_throttle.cc
+++ b/components/safe_browsing/content/browser/browser_url_loader_throttle.cc
@@ -20,6 +20,7 @@
 #include "components/safe_browsing/core/common/features.h"
 #include "components/safe_browsing/core/common/utils.h"
 #include "components/safe_browsing/core/common/web_ui_constants.h"
+#include "components/sessions/content/session_tab_helper.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
@@ -139,6 +140,9 @@
   url_lookup_service_metric_suffix_ =
       url_real_time_lookup_enabled_ ? url_lookup_service_->GetMetricSuffix()
                                     : kNoRealTimeURLLookupService;
+  content::WebContents* web_contents = web_contents_getter_.Run();
+  tab_id_ = web_contents ? sessions::SessionTabHelper::IdForTab(web_contents)
+                         : SessionID::InvalidValue();
   skip_check_checker_ = std::make_unique<SkipCheckCheckerOnSB>(
       delegate_getter_, frame_tree_node_id);
 }
@@ -223,7 +227,7 @@
         /*hash_realtime_service=*/nullptr,
         /*hash_realtime_selection=*/
         hash_realtime_utils::HashRealTimeSelection::kNone,
-        /*is_async_check=*/false);
+        /*is_async_check=*/false, SessionID::InvalidValue());
     async_sb_checker_ = std::make_unique<UrlCheckerOnSB>(
         delegate_getter_, frame_tree_node_id_, navigation_id_,
         web_contents_getter_,
@@ -233,7 +237,7 @@
         url_real_time_lookup_enabled_, can_check_db,
         can_check_high_confidence_allowlist, url_lookup_service_metric_suffix_,
         url_lookup_service_, hash_realtime_service_, hash_realtime_selection_,
-        /*is_async_check=*/true);
+        /*is_async_check=*/true, tab_id_);
     if (on_sync_sb_checker_created_callback_for_testing_) {
       std::move(on_sync_sb_checker_created_callback_for_testing_).Run();
     }
@@ -250,7 +254,7 @@
         url_real_time_lookup_enabled_, can_check_db,
         can_check_high_confidence_allowlist, url_lookup_service_metric_suffix_,
         url_lookup_service_, hash_realtime_service_, hash_realtime_selection_,
-        /*is_async_check=*/false);
+        /*is_async_check=*/false, tab_id_);
     if (on_sync_sb_checker_created_callback_for_testing_) {
       std::move(on_sync_sb_checker_created_callback_for_testing_).Run();
     }
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle.h b/components/safe_browsing/content/browser/browser_url_loader_throttle.h
index 2124cc8..7e8d5238 100644
--- a/components/safe_browsing/content/browser/browser_url_loader_throttle.h
+++ b/components/safe_browsing/content/browser/browser_url_loader_throttle.h
@@ -213,6 +213,7 @@
   std::optional<int64_t> navigation_id_;
   UrlCheckerOnSB::GetDelegateCallback delegate_getter_;
   base::RepeatingCallback<content::WebContents*()> web_contents_getter_;
+  SessionID tab_id_ = SessionID::InvalidValue();
 
   // Checkers used to perform Safe Browsing checks. |sync_sb_checker_| may defer
   // the URL loader. |async_sb_checker_| doesn't defer the URL loader and may
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc b/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc
index 71bde29..e25d802b 100644
--- a/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc
+++ b/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc
@@ -124,10 +124,12 @@
   void StartLookup(
       const GURL& url,
       RTLookupResponseCallback response_callback,
-      scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override {}
+      scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+      SessionID tab_id) override {}
   void SendSampledRequest(
       const GURL& url,
-      scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override {}
+      scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+      SessionID tab_id) override {}
 
  private:
   GURL GetRealTimeLookupUrl() const override { return GURL(); }
@@ -140,7 +142,8 @@
   void GetAccessToken(
       const GURL& url,
       RTLookupResponseCallback response_callback,
-      scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override {}
+      scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+      SessionID tab_id) override {}
   std::optional<std::string> GetDMTokenString() const override {
     return std::nullopt;
   }
@@ -201,7 +204,8 @@
                                    url_lookup_service_on_ui,
                                    hash_realtime_service_on_ui,
                                    hash_realtime_selection,
-                                   is_async_check) {}
+                                   is_async_check,
+                                   SessionID::InvalidValue()) {}
 
   // Returns the CallbackInfo that was previously added in |AddCallbackInfo|.
   // It will crash if |AddCallbackInfo| was not called.
diff --git a/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc b/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc
index 87e8393..5a98b7d8 100644
--- a/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc
+++ b/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc
@@ -173,7 +173,7 @@
       /*hash_realtime_service_on_ui=*/nullptr,
       /*hash_realtime_selection=*/
       hash_realtime_utils::HashRealTimeSelection::kNone,
-      /*is_async_check=*/false);
+      /*is_async_check=*/false, SessionID::InvalidValue());
   auto weak_impl = checker_impl->WeakPtr();
 
   checker_impl->CheckUrl(
diff --git a/components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.cc b/components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.cc
index 2d33ed8..6bc94fe3 100644
--- a/components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.cc
+++ b/components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.cc
@@ -564,6 +564,17 @@
 }
 
 SafeBrowsingNavigationObserverManager::AttributionResult
+SafeBrowsingNavigationObserverManager::IdentifyReferrerChainByEventURL(
+    const GURL& event_url,
+    SessionID event_tab_id,
+    int user_gesture_count_limit,
+    ReferrerChain* out_referrer_chain) {
+  return IdentifyReferrerChainByEventURL(
+      event_url, event_tab_id, content::GlobalRenderFrameHostId(),
+      user_gesture_count_limit, out_referrer_chain);
+}
+
+SafeBrowsingNavigationObserverManager::AttributionResult
 SafeBrowsingNavigationObserverManager::IdentifyReferrerChainByPendingEventURL(
     const GURL& event_url,
     int user_gesture_count_limit,
diff --git a/components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.h b/components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.h
index 0000d3b..d260e395 100644
--- a/components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.h
+++ b/components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.h
@@ -269,6 +269,15 @@
       int user_gesture_count_limit,
       ReferrerChain* out_referrer_chain) override;
 
+  // Helper function to |IdentifyReferrerChainByEventURL| above in cases where
+  // |event_outermost_main_frame_id| is not available. That value will default
+  // to |content::GlobalRenderFrameHostId()|.
+  AttributionResult IdentifyReferrerChainByEventURL(
+      const GURL& event_url,
+      SessionID event_tab_id,  // Invalid if tab id is unknown or not available.
+      int user_gesture_count_limit,
+      ReferrerChain* out_referrer_chain) override;
+
   // Based on the |event_url|, traces back the observed PendingNavigationEvents
   // and NavigationEvents in navigation_event_list_ to identify the sequence of
   // navigations leading to the |event_url|, with the coverage limited to
diff --git a/components/safe_browsing/content/browser/safe_browsing_navigation_observer_unittest.cc b/components/safe_browsing/content/browser/safe_browsing_navigation_observer_unittest.cc
index 5ff5b75d..b0594e3 100644
--- a/components/safe_browsing/content/browser/safe_browsing_navigation_observer_unittest.cc
+++ b/components/safe_browsing/content/browser/safe_browsing_navigation_observer_unittest.cc
@@ -371,6 +371,54 @@
               events.NavigationEventsSize() - 1));
 }
 
+TEST_F(SBNavigationObserverTest, TestBasicReferrerChain) {
+  base::Time now = base::Time::Now();
+  base::Time one_second_ago = base::Time::FromSecondsSinceUnixEpoch(
+      now.InSecondsFSinceUnixEpoch() - 1.0);
+  base::Time two_seconds_ago = base::Time::FromSecondsSinceUnixEpoch(
+      now.InSecondsFSinceUnixEpoch() - 2.0);
+
+  std::unique_ptr<NavigationEvent> first_navigation =
+      std::make_unique<NavigationEvent>();
+  first_navigation->original_request_url = GURL("http://A.com");
+  first_navigation->last_updated = two_seconds_ago;
+  first_navigation->navigation_initiation =
+      ReferrerChainEntry::BROWSER_INITIATED;
+  navigation_event_list()->RecordNavigationEvent(std::move(first_navigation));
+
+  std::unique_ptr<NavigationEvent> second_navigation =
+      std::make_unique<NavigationEvent>();
+  second_navigation->source_url = GURL("http://A.com");
+  second_navigation->original_request_url = GURL("http://B.com");
+  second_navigation->last_updated = one_second_ago;
+  second_navigation->navigation_initiation =
+      ReferrerChainEntry::RENDERER_INITIATED_WITH_USER_GESTURE;
+  navigation_event_list()->RecordNavigationEvent(std::move(second_navigation));
+
+  std::unique_ptr<NavigationEvent> third_navigation =
+      std::make_unique<NavigationEvent>();
+  third_navigation->source_url = GURL("http://B.com");
+  third_navigation->original_request_url = GURL("http://C.com");
+  third_navigation->last_updated = now;
+  third_navigation->navigation_initiation =
+      ReferrerChainEntry::RENDERER_INITIATED_WITH_USER_GESTURE;
+  navigation_event_list()->RecordNavigationEvent(std::move(third_navigation));
+
+  ASSERT_EQ(3U, navigation_event_list()->NavigationEventsSize());
+
+  ReferrerChain referrer_chain;
+  navigation_observer_manager_->IdentifyReferrerChainByEventURL(
+      GURL("http://C.com/"), SessionID::InvalidValue(),
+      content::GlobalRenderFrameHostId(), 10, &referrer_chain);
+  ASSERT_EQ(3, referrer_chain.size());
+
+  ReferrerChain referrer_chain_without_render_frame_host;
+  navigation_observer_manager_->IdentifyReferrerChainByEventURL(
+      GURL("http://C.com/"), SessionID::InvalidValue(), 10,
+      &referrer_chain_without_render_frame_host);
+  ASSERT_EQ(3, referrer_chain_without_render_frame_host.size());
+}
+
 TEST_F(SBNavigationObserverTest, BasicNavigationAndCommit) {
   // Navigation in current tab.
   NavigateAndCommit(GURL("http://foo/1"), ui::PAGE_TRANSITION_AUTO_BOOKMARK);
diff --git a/components/safe_browsing/content/browser/url_checker_on_sb.cc b/components/safe_browsing/content/browser/url_checker_on_sb.cc
index d17f8a17..56dd2023 100644
--- a/components/safe_browsing/content/browser/url_checker_on_sb.cc
+++ b/components/safe_browsing/content/browser/url_checker_on_sb.cc
@@ -67,7 +67,8 @@
     base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service,
     base::WeakPtr<HashRealTimeService> hash_realtime_service,
     hash_realtime_utils::HashRealTimeSelection hash_realtime_selection,
-    bool is_async_check)
+    bool is_async_check,
+    SessionID tab_id)
     : delegate_getter_(std::move(delegate_getter)),
       frame_tree_node_id_(frame_tree_node_id),
       navigation_id_(navigation_id),
@@ -81,8 +82,8 @@
       hash_realtime_service_(hash_realtime_service),
       hash_realtime_selection_(hash_realtime_selection),
       creation_time_(base::TimeTicks::Now()),
-      is_async_check_(is_async_check) {
-}
+      is_async_check_(is_async_check),
+      tab_id_(tab_id) {}
 
 UrlCheckerOnSB::~UrlCheckerOnSB() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -107,7 +108,7 @@
         can_check_db_, can_check_high_confidence_allowlist_,
         url_lookup_service_metric_suffix_, content::GetUIThreadTaskRunner({}),
         url_lookup_service_, hash_realtime_service_, hash_realtime_selection_,
-        is_async_check_);
+        is_async_check_, tab_id_);
   }
 
   CheckUrl(params.url, params.method);
diff --git a/components/safe_browsing/content/browser/url_checker_on_sb.h b/components/safe_browsing/content/browser/url_checker_on_sb.h
index 1fa3322..7370d437 100644
--- a/components/safe_browsing/content/browser/url_checker_on_sb.h
+++ b/components/safe_browsing/content/browser/url_checker_on_sb.h
@@ -91,7 +91,8 @@
       base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service,
       base::WeakPtr<HashRealTimeService> hash_realtime_service,
       hash_realtime_utils::HashRealTimeSelection hash_realtime_selection,
-      bool is_async_check);
+      bool is_async_check,
+      SessionID tab_id);
 
   ~UrlCheckerOnSB();
 
@@ -163,6 +164,7 @@
       hash_realtime_utils::HashRealTimeSelection::kNone;
   base::TimeTicks creation_time_;
   bool is_async_check_ = false;
+  SessionID tab_id_;
   base::WeakPtrFactory<UrlCheckerOnSB> weak_factory_{this};
 };
 
diff --git a/components/safe_browsing/content/browser/web_api_handshake_checker.cc b/components/safe_browsing/content/browser/web_api_handshake_checker.cc
index 491d2d0..33e55da 100644
--- a/components/safe_browsing/content/browser/web_api_handshake_checker.cc
+++ b/components/safe_browsing/content/browser/web_api_handshake_checker.cc
@@ -78,7 +78,7 @@
         /*hash_realtime_service_on_ui=*/nullptr,
         /*hash_realtime_selection=*/
         hash_realtime_utils::HashRealTimeSelection::kNone,
-        /*is_async_check=*/false);
+        /*is_async_check=*/false, SessionID::InvalidValue());
     url_checker_->CheckUrl(
         url, "GET",
         base::BindOnce(&WebApiHandshakeChecker::CheckerOnSB::OnCheckUrlResult,
diff --git a/components/safe_browsing/core/browser/BUILD.gn b/components/safe_browsing/core/browser/BUILD.gn
index 03797a43..2d78c9dfb 100644
--- a/components/safe_browsing/core/browser/BUILD.gn
+++ b/components/safe_browsing/core/browser/BUILD.gn
@@ -50,6 +50,7 @@
     "//components/safe_browsing/core/common/proto:csd_proto",
     "//components/safe_browsing/core/common/proto:realtimeapi_proto",
     "//components/security_interstitials/core:unsafe_resource",
+    "//components/sessions:session_id",
     "//components/unified_consent",
     "//components/version_info",
     "//net",
@@ -91,6 +92,7 @@
     "//components/safe_browsing/core/common",
     "//components/safe_browsing/core/common/proto:csd_proto",
     "//components/security_interstitials/core:unsafe_resource",
+    "//components/sessions:session_id",
     "//net/traffic_annotation:test_support",
     "//services/network/public/cpp",
     "//services/network/public/mojom",
diff --git a/components/safe_browsing/core/browser/realtime/BUILD.gn b/components/safe_browsing/core/browser/realtime/BUILD.gn
index 2daca16..36afaed 100644
--- a/components/safe_browsing/core/browser/realtime/BUILD.gn
+++ b/components/safe_browsing/core/browser/realtime/BUILD.gn
@@ -74,6 +74,7 @@
     "//components/safe_browsing/core/common:safe_browsing_prefs",
     "//components/safe_browsing/core/common/proto:csd_proto",
     "//components/safe_browsing/core/common/proto:realtimeapi_proto",
+    "//components/sessions:session_id",
     "//services/network/public/cpp:cpp",
     "//url:url",
   ]
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service.cc b/components/safe_browsing/core/browser/realtime/url_lookup_service.cc
index f152e7b..7f946af 100644
--- a/components/safe_browsing/core/browser/realtime/url_lookup_service.cc
+++ b/components/safe_browsing/core/browser/realtime/url_lookup_service.cc
@@ -79,11 +79,12 @@
 void RealTimeUrlLookupService::GetAccessToken(
     const GURL& url,
     RTLookupResponseCallback response_callback,
-    scoped_refptr<base::SequencedTaskRunner> callback_task_runner) {
+    scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+    SessionID tab_id) {
   token_fetcher_->Start(base::BindOnce(
       &RealTimeUrlLookupService::OnGetAccessToken, weak_factory_.GetWeakPtr(),
       url, std::move(response_callback), std::move(callback_task_runner),
-      base::TimeTicks::Now()));
+      base::TimeTicks::Now(), tab_id));
 }
 
 void RealTimeUrlLookupService::OnPrefChanged() {
@@ -97,6 +98,7 @@
     RTLookupResponseCallback response_callback,
     scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
     base::TimeTicks get_token_start_time,
+    SessionID tab_id,
     const std::string& access_token) {
   if (shutting_down_)
     return;
@@ -107,7 +109,7 @@
                             !access_token.empty());
   SendRequest(url, access_token, std::move(response_callback),
               std::move(callback_task_runner),
-              /* is_sampled_report */ false);
+              /* is_sampled_report */ false, tab_id);
 }
 
 void RealTimeUrlLookupService::OnResponseUnauthorized(
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service.h b/components/safe_browsing/core/browser/realtime/url_lookup_service.h
index 70ef129e..247f211 100644
--- a/components/safe_browsing/core/browser/realtime/url_lookup_service.h
+++ b/components/safe_browsing/core/browser/realtime/url_lookup_service.h
@@ -101,7 +101,8 @@
   void GetAccessToken(
       const GURL& url,
       RTLookupResponseCallback response_callback,
-      scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override;
+      scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+      SessionID tab_id) override;
   std::optional<std::string> GetDMTokenString() const override;
   bool ShouldIncludeCredentials() const override;
   void OnResponseUnauthorized(const std::string& invalid_access_token) override;
@@ -121,6 +122,7 @@
       RTLookupResponseCallback response_callback,
       scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
       base::TimeTicks get_token_start_time,
+      SessionID tab_id,
       const std::string& access_token);
 
   // Unowned object used for getting preference settings.
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service_base.cc b/components/safe_browsing/core/browser/realtime/url_lookup_service_base.cc
index 40c8e5f..6aff3aad6 100644
--- a/components/safe_browsing/core/browser/realtime/url_lookup_service_base.cc
+++ b/components/safe_browsing/core/browser/realtime/url_lookup_service_base.cc
@@ -296,20 +296,23 @@
 
 void RealTimeUrlLookupServiceBase::SendSampledRequest(
     const GURL& url,
-    scoped_refptr<base::SequencedTaskRunner> callback_task_runner) {
+    scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+    SessionID tab_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(url.is_valid());
 
   SendRequest(url,
               /* access_token_string */ std::string(),
               /* response_callback */ base::NullCallback(),
-              std::move(callback_task_runner), /* is_sampled_report */ true);
+              std::move(callback_task_runner), /* is_sampled_report */ true,
+              tab_id);
 }
 
 void RealTimeUrlLookupServiceBase::StartLookup(
     const GURL& url,
     RTLookupResponseCallback response_callback,
-    scoped_refptr<base::SequencedTaskRunner> callback_task_runner) {
+    scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+    SessionID tab_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(url.is_valid());
 
@@ -336,12 +339,12 @@
 
   if (CanPerformFullURLLookupWithToken()) {
     GetAccessToken(url, std::move(response_callback),
-                   std::move(callback_task_runner));
+                   std::move(callback_task_runner), tab_id);
   } else {
     SendRequest(url,
                 /* access_token_string */ std::string(),
                 std::move(response_callback), std::move(callback_task_runner),
-                /* is_sampled_report */ false);
+                /* is_sampled_report */ false, tab_id);
   }
 }
 
@@ -350,10 +353,11 @@
     const std::string& access_token_string,
     RTLookupResponseCallback response_callback,
     scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
-    bool is_sampled_report) {
+    bool is_sampled_report,
+    SessionID tab_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::unique_ptr<RTLookupRequest> request =
-      FillRequestProto(url, is_sampled_report);
+      FillRequestProto(url, is_sampled_report, tab_id);
   RecordRequestPopulationWithAndWithoutSuffix(
       "SafeBrowsing.RT.Request.UserPopulation", GetMetricSuffix(),
       request->population().user_population());
@@ -534,7 +538,8 @@
 
 std::unique_ptr<RTLookupRequest> RealTimeUrlLookupServiceBase::FillRequestProto(
     const GURL& url,
-    bool is_sampled_report) {
+    bool is_sampled_report,
+    SessionID tab_id) {
   auto request = std::make_unique<RTLookupRequest>();
   request->set_url(SanitizeURL(url).spec());
   request->set_lookup_type(RTLookupRequest::NAVIGATION);
@@ -550,9 +555,28 @@
 
   *request->mutable_population() = get_user_population_callback_.Run();
   if (referrer_chain_provider_) {
-    referrer_chain_provider_->IdentifyReferrerChainByPendingEventURL(
-        SanitizeURL(url), GetReferrerUserGestureLimit(),
-        request->mutable_referrer_chain());
+    ReferrerChainProvider::AttributionResult attribution_result =
+        referrer_chain_provider_->IdentifyReferrerChainByPendingEventURL(
+            SanitizeURL(url), GetReferrerUserGestureLimit(),
+            request->mutable_referrer_chain());
+    // The navigation event may not be found for various reasons. One
+    // possibility is that with async checks, the event URL may no longer be
+    // pending if the page has already loaded. If the navigation event is not
+    // found, try to fetch the referrer chain as a regular event URL rather than
+    // a pending one.
+    if (attribution_result == ReferrerChainProvider::AttributionResult::
+                                  NAVIGATION_EVENT_NOT_FOUND &&
+        base::FeatureList::IsEnabled(
+            safe_browsing::kSafeBrowsingAsyncRealTimeCheck)) {
+      CHECK(request->referrer_chain().empty());
+      referrer_chain_provider_->IdentifyReferrerChainByEventURL(
+          SanitizeURL(url), tab_id, GetReferrerUserGestureLimit(),
+          request->mutable_referrer_chain());
+
+      RecordBooleanWithAndWithoutSuffix(
+          "SafeBrowsing.RT.EventUrlReferrerChainFetchSucceeded",
+          GetMetricSuffix(), !request->referrer_chain().empty());
+    }
     SanitizeReferrerChainEntries(request->mutable_referrer_chain(),
                                  GetMinAllowedTimestampForReferrerChains(),
                                  /*should_remove_subresource_url=*/
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service_base.h b/components/safe_browsing/core/browser/realtime/url_lookup_service_base.h
index c526a1a1..4a03f36 100644
--- a/components/safe_browsing/core/browser/realtime/url_lookup_service_base.h
+++ b/components/safe_browsing/core/browser/realtime/url_lookup_service_base.h
@@ -22,6 +22,7 @@
 #include "components/safe_browsing/core/browser/utils/backoff_operator.h"
 #include "components/safe_browsing/core/common/proto/csd.pb.h"
 #include "components/safe_browsing/core/common/proto/realtimeapi.pb.h"
+#include "components/sessions/core/session_id.h"
 #include "url/gurl.h"
 
 namespace net {
@@ -107,13 +108,15 @@
   virtual void StartLookup(
       const GURL& url,
       RTLookupResponseCallback response_callback,
-      scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
+      scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+      SessionID tab_id);
 
   // Similar to the function StartLookup above,
   // but to send Protego sampled request specifically.
   virtual void SendSampledRequest(
       const GURL& url,
-      scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
+      scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+      SessionID tab_id);
 
   // Helper function to return a weak pointer.
   base::WeakPtr<RealTimeUrlLookupServiceBase> GetWeakPtr();
@@ -159,7 +162,8 @@
       const std::string& access_token_string,
       RTLookupResponseCallback response_callback,
       scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
-      bool is_sampled_report);
+      bool is_sampled_report,
+      SessionID tab_id);
 
  private:
   using PendingRTLookupRequests =
@@ -193,7 +197,8 @@
   virtual void GetAccessToken(
       const GURL& url,
       RTLookupResponseCallback response_callback,
-      scoped_refptr<base::SequencedTaskRunner> callback_task_runner) = 0;
+      scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+      SessionID tab_id) = 0;
 
   // Called when the response from the server is unauthorized, so child classes
   // can add extra handling when this happens.
@@ -264,9 +269,9 @@
       std::unique_ptr<std::string> response_body);
 
   // Fills in fields in |RTLookupRequest|.
-  std::unique_ptr<RTLookupRequest> FillRequestProto(
-      const GURL& url,
-      bool is_sampled_report);
+  std::unique_ptr<RTLookupRequest> FillRequestProto(const GURL& url,
+                                                    bool is_sampled_report,
+                                                    SessionID tab_id);
 
   // Logs |request| and |oauth_token| on any open
   // chrome://safe-browsing pages. Returns a token that can be passed
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service_unittest.cc b/components/safe_browsing/core/browser/realtime/url_lookup_service_unittest.cc
index 8ed7b962..739bbd6 100644
--- a/components/safe_browsing/core/browser/realtime/url_lookup_service_unittest.cc
+++ b/components/safe_browsing/core/browser/realtime/url_lookup_service_unittest.cc
@@ -62,6 +62,11 @@
                                      event_outermost_main_frame_id,
                                  int user_gesture_count_limit,
                                  ReferrerChain* out_referrer_chain));
+  MOCK_METHOD4(IdentifyReferrerChainByEventURL,
+               AttributionResult(const GURL& event_url,
+                                 SessionID event_tab_id,
+                                 int user_gesture_count_limit,
+                                 ReferrerChain* out_referrer_chain));
   MOCK_METHOD3(IdentifyReferrerChainByPendingEventURL,
                AttributionResult(const GURL& event_url,
                                  int user_gesture_count_limit,
@@ -181,7 +186,8 @@
   std::unique_ptr<RTLookupRequest> FillRequestProto(
       const GURL& url,
       bool is_sampled_report) {
-    return rt_service_->FillRequestProto(url, is_sampled_report);
+    return rt_service_->FillRequestProto(url, is_sampled_report,
+                                         SessionID::InvalidValue());
   }
   std::unique_ptr<RTLookupResponse> GetCachedRealTimeUrlVerdict(
       const GURL& url) {
@@ -333,7 +339,8 @@
     EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ false,
                                        /* is_cached_response */ false, _));
     rt_service()->StartLookup(url, response_callback.Get(),
-                              base::SequencedTaskRunner::GetCurrentDefault());
+                              base::SequencedTaskRunner::GetCurrentDefault(),
+                              SessionID::InvalidValue());
     task_environment_.RunUntilIdle();
   }
 
@@ -488,7 +495,8 @@
 
   base::MockCallback<RTLookupResponseCallback> response_callback;
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ true,
                                      /* is_cached_response */ true, _));
@@ -515,7 +523,8 @@
                         RTLookupResponse::ThreatInfo::COVERING_MATCH);
 
   rt_service()->StartLookup(url, base::DoNothing(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   FulfillAccessTokenRequest("access_token_string");
   task_environment_.RunUntilIdle();
@@ -539,7 +548,8 @@
                         RTLookupResponse::ThreatInfo::COVERING_MATCH);
 
   rt_service()->StartLookup(url, base::DoNothing(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   task_environment_.RunUntilIdle();
 
@@ -563,7 +573,8 @@
   task_environment_.RunUntilIdle();
 
   rt_service()->StartLookup(url, base::DoNothing(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   task_environment_.RunUntilIdle();
 
@@ -588,7 +599,8 @@
   task_environment_.RunUntilIdle();
 
   rt_service()->StartLookup(url, base::DoNothing(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   task_environment_.RunUntilIdle();
 
@@ -611,7 +623,8 @@
                         RTLookupResponse::ThreatInfo::COVERING_MATCH);
 
   rt_service()->StartLookup(url, base::DoNothing(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   FulfillAccessTokenRequest("access_token_string");
   task_environment_.RunUntilIdle();
@@ -635,7 +648,8 @@
                         RTLookupResponse::ThreatInfo::COVERING_MATCH);
 
   rt_service()->StartLookup(url, base::DoNothing(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   FulfillAccessTokenRequest("access_token_string");
   task_environment_.RunUntilIdle();
@@ -678,7 +692,8 @@
   test_url_loader_factory_.SetInterceptor(interceptor.GetCallback());
 
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   EXPECT_TRUE(raw_token_fetcher()->WasStartCalled());
   FulfillAccessTokenRequest("access_token_string");
@@ -722,7 +737,8 @@
   test_url_loader_factory_.SetInterceptor(interceptor.GetCallback());
 
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   EXPECT_TRUE(raw_token_fetcher()->WasStartCalled());
   // Token fetcher returns empty string when the token is unavailable.
@@ -758,7 +774,8 @@
   test_url_loader_factory_.SetInterceptor(interceptor.GetCallback());
 
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   task_environment_.RunUntilIdle();
 
@@ -784,7 +801,8 @@
                                      /* is_cached_response */ false, _));
 
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   FulfillAccessTokenRequest("invalid_token_string");
   EXPECT_CALL(*raw_token_fetcher(),
@@ -805,7 +823,8 @@
                                      /* is_cached_response */ false, _));
 
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   FulfillAccessTokenRequest("invalid_token_string");
   EXPECT_CALL(*raw_token_fetcher(), OnInvalidAccessToken(_)).Times(0);
@@ -839,10 +858,15 @@
                   url, /*user_gesture_count_limit=*/2, _))
       .WillOnce(DoAll(SetArgPointee<2>(returned_referrer_chain),
                       Return(ReferrerChainProvider::SUCCESS)));
+  EXPECT_CALL(*referrer_chain_provider_,
+              IdentifyReferrerChainByEventURL(
+                  url, _, /*user_gesture_count_limit=*/2, _))
+      .Times(0);
 
   base::MockCallback<RTLookupResponseCallback> response_callback;
   EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ true,
                                      /* is_cached_response */ false, _));
+  bool request_validated;
   MustRunInterceptor interceptor(
       base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
         RTLookupRequest request_proto;
@@ -854,13 +878,16 @@
         EXPECT_EQ(kTestUrl, request_proto.referrer_chain().Get(0).url());
         EXPECT_EQ(kTestReferrerUrl,
                   request_proto.referrer_chain().Get(1).url());
+        request_validated = true;
       }));
   test_url_loader_factory_.SetInterceptor(interceptor.GetCallback());
 
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   task_environment_.RunUntilIdle();
+  EXPECT_TRUE(request_validated);
 }
 
 TEST_F(RealTimeUrlLookupServiceTest,
@@ -890,7 +917,12 @@
                   url, /*user_gesture_count_limit=*/2, _))
       .WillOnce(DoAll(SetArgPointee<2>(returned_referrer_chain),
                       Return(ReferrerChainProvider::SUCCESS)));
+  EXPECT_CALL(*referrer_chain_provider_,
+              IdentifyReferrerChainByEventURL(
+                  url, _, /*user_gesture_count_limit=*/2, _))
+      .Times(0);
 
+  bool request_validated;
   base::MockCallback<RTLookupResponseCallback> response_callback;
   MustRunInterceptor interceptor(
       base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
@@ -923,6 +955,8 @@
         EXPECT_FALSE(request_proto.referrer_chain()
                          .Get(1)
                          .is_subframe_referrer_url_removed());
+
+        request_validated = true;
       }));
   test_url_loader_factory_.SetInterceptor(interceptor.GetCallback());
 
@@ -930,9 +964,11 @@
                                      /* is_cached_response */ false, _));
 
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   task_environment_.RunUntilIdle();
+  EXPECT_TRUE(request_validated);
 }
 
 TEST_F(RealTimeUrlLookupServiceTest,
@@ -965,7 +1001,12 @@
                   url, /*user_gesture_count_limit=*/2, _))
       .WillOnce(DoAll(SetArgPointee<2>(returned_referrer_chain),
                       Return(ReferrerChainProvider::SUCCESS)));
+  EXPECT_CALL(*referrer_chain_provider_,
+              IdentifyReferrerChainByEventURL(
+                  url, _, /*user_gesture_count_limit=*/2, _))
+      .Times(0);
 
+  bool request_validated;
   base::MockCallback<RTLookupResponseCallback> response_callback;
   MustRunInterceptor interceptor(
       base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
@@ -992,6 +1033,8 @@
                   request_proto.referrer_chain().Get(1).url());
         EXPECT_FALSE(
             request_proto.referrer_chain().Get(1).is_subframe_url_removed());
+
+        request_validated = true;
       }));
   test_url_loader_factory_.SetInterceptor(interceptor.GetCallback());
 
@@ -999,9 +1042,11 @@
                                      /* is_cached_response */ false, _));
 
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   task_environment_.RunUntilIdle();
+  EXPECT_TRUE(request_validated);
 }
 
 TEST_F(RealTimeUrlLookupServiceTest,
@@ -1034,11 +1079,16 @@
                   url, /*user_gesture_count_limit=*/2, _))
       .WillOnce(DoAll(SetArgPointee<2>(returned_referrer_chain),
                       Return(ReferrerChainProvider::SUCCESS)));
+  EXPECT_CALL(*referrer_chain_provider_,
+              IdentifyReferrerChainByEventURL(
+                  url, _, /*user_gesture_count_limit=*/2, _))
+      .Times(0);
 
   base::MockCallback<RTLookupResponseCallback> response_callback;
   EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ true,
                                      /* is_cached_response */ false, _));
 
+  bool request_validated;
   MustRunInterceptor interceptor(
       base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
         RTLookupRequest request_proto;
@@ -1070,13 +1120,122 @@
             request_proto.referrer_chain().Get(1).is_subframe_url_removed());
         EXPECT_FALSE(
             request_proto.referrer_chain().Get(1).is_url_removed_by_policy());
+
+        request_validated = true;
       }));
   test_url_loader_factory_.SetInterceptor(interceptor.GetCallback());
 
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   task_environment_.RunUntilIdle();
+  EXPECT_TRUE(request_validated);
+}
+
+// Tests that when a call to IdentifyReferrerChainByPendingEventURL does not
+// identify the referrer chain, the service falls back to
+// IdentifyReferrerChainByEventURL.
+TEST_F(RealTimeUrlLookupServiceTest,
+       TestReferrerChain_FallbackToEventUrlReferrerChain) {
+  base::HistogramTester histogram_tester;
+  EnableRealTimeUrlLookup({kSafeBrowsingAsyncRealTimeCheck}, {});
+  GURL url(kTestUrl);
+  SetUpRTLookupResponse(RTLookupResponse::ThreatInfo::DANGEROUS,
+                        RTLookupResponse::ThreatInfo::SOCIAL_ENGINEERING, 60,
+                        "example.test/",
+                        RTLookupResponse::ThreatInfo::COVERING_MATCH);
+  ReferrerChain returned_referrer_chain;
+  double navigation_time_msec =
+      base::Time::Now().InMillisecondsSinceUnixEpoch();
+  returned_referrer_chain.Add()->Swap(
+      CreateReferrerChainEntry(kTestUrl, /*main_frame_url=*/"",
+                               /*referrer_url=*/"",
+                               /*referrer_main_frame_url=*/"",
+                               navigation_time_msec)
+          .get());
+  returned_referrer_chain.Add()->Swap(
+      CreateReferrerChainEntry(kTestReferrerUrl, /*main_frame_url=*/"",
+                               /*referrer_url=*/"",
+                               /*referrer_main_frame_url=*/"",
+                               navigation_time_msec)
+          .get());
+  EXPECT_CALL(*referrer_chain_provider_,
+              IdentifyReferrerChainByPendingEventURL(
+                  url, /*user_gesture_count_limit=*/2, _))
+      .WillOnce(Return(ReferrerChainProvider::NAVIGATION_EVENT_NOT_FOUND));
+  EXPECT_CALL(*referrer_chain_provider_,
+              IdentifyReferrerChainByEventURL(
+                  url, _, /*user_gesture_count_limit=*/2, _))
+      .WillOnce(DoAll(SetArgPointee<3>(returned_referrer_chain),
+                      Return(ReferrerChainProvider::SUCCESS)));
+
+  base::MockCallback<RTLookupResponseCallback> response_callback;
+  EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ true,
+                                     /* is_cached_response */ false, _));
+  bool request_validated;
+  MustRunInterceptor interceptor(
+      base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
+        RTLookupRequest request_proto;
+        ASSERT_TRUE(GetRequestProto(request, &request_proto));
+        // Check referrer chain is attached.
+        EXPECT_EQ(2, request_proto.referrer_chain().size());
+        EXPECT_EQ(kTestUrl, request_proto.referrer_chain().Get(0).url());
+        EXPECT_EQ(kTestReferrerUrl,
+                  request_proto.referrer_chain().Get(1).url());
+        request_validated = true;
+      }));
+  test_url_loader_factory_.SetInterceptor(interceptor.GetCallback());
+
+  rt_service()->StartLookup(url, response_callback.Get(),
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
+  task_environment_.RunUntilIdle();
+  EXPECT_TRUE(request_validated);
+
+  histogram_tester.ExpectUniqueSample(
+      "SafeBrowsing.RT.EventUrlReferrerChainFetchSucceeded",
+      /*sample=*/true,
+      /*expected_bucket_count=*/1);
+}
+
+TEST_F(
+    RealTimeUrlLookupServiceTest,
+    TestReferrerChain_NoFallbackToEventUrlReferrerChain_AsyncChecksDisabled) {
+  EnableRealTimeUrlLookup({}, {kSafeBrowsingAsyncRealTimeCheck});
+  GURL url(kTestUrl);
+  SetUpRTLookupResponse(RTLookupResponse::ThreatInfo::DANGEROUS,
+                        RTLookupResponse::ThreatInfo::SOCIAL_ENGINEERING, 60,
+                        "example.test/",
+                        RTLookupResponse::ThreatInfo::COVERING_MATCH);
+  EXPECT_CALL(*referrer_chain_provider_,
+              IdentifyReferrerChainByPendingEventURL(
+                  url, /*user_gesture_count_limit=*/2, _))
+      .WillOnce(Return(ReferrerChainProvider::NAVIGATION_EVENT_NOT_FOUND));
+  EXPECT_CALL(*referrer_chain_provider_,
+              IdentifyReferrerChainByEventURL(
+                  url, _, /*user_gesture_count_limit=*/2, _))
+      .Times(0);
+
+  base::MockCallback<RTLookupResponseCallback> response_callback;
+  EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ true,
+                                     /* is_cached_response */ false, _));
+  bool request_validated;
+  MustRunInterceptor interceptor(
+      base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
+        RTLookupRequest request_proto;
+        ASSERT_TRUE(GetRequestProto(request, &request_proto));
+        // Check no referrer chain is attached.
+        EXPECT_TRUE(request_proto.referrer_chain().empty());
+        request_validated = true;
+      }));
+  test_url_loader_factory_.SetInterceptor(interceptor.GetCallback());
+
+  rt_service()->StartLookup(url, response_callback.Get(),
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
+  task_environment_.RunUntilIdle();
+  EXPECT_TRUE(request_validated);
 }
 
 TEST_F(RealTimeUrlLookupServiceTest, TestShutdown_CallbackNotPostedOnShutdown) {
@@ -1093,7 +1252,8 @@
   EXPECT_CALL(response_callback, Run(_, _, _)).Times(0);
 
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   rt_service()->Shutdown();
 
@@ -1134,7 +1294,8 @@
   EXPECT_CALL(response_callback, Run(_, _, _)).Times(0);
 
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   rt_service()->Shutdown();
 
@@ -1159,7 +1320,8 @@
   test_url_loader_factory_.SetInterceptor(interceptor.GetCallback());
 
   rt_service()->SendSampledRequest(
-      url, base::SequencedTaskRunner::GetCurrentDefault());
+      url, base::SequencedTaskRunner::GetCurrentDefault(),
+      SessionID::InvalidValue());
   rt_service()->Shutdown();
 
   task_environment_.RunUntilIdle();
@@ -1190,7 +1352,8 @@
     EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ !make_fail,
                                        /* is_cached_response */ false, _));
     rt_service()->StartLookup(url, response_callback.Get(),
-                              base::SequencedTaskRunner::GetCurrentDefault());
+                              base::SequencedTaskRunner::GetCurrentDefault(),
+                              SessionID::InvalidValue());
     task_environment_.RunUntilIdle();
   };
   auto perform_failing_lookup = [perform_lookup]() { perform_lookup(true); };
@@ -1240,7 +1403,8 @@
     EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ false,
                                        /* is_cached_response */ false, _));
     rt_service()->StartLookup(url, response_callback.Get(),
-                              base::SequencedTaskRunner::GetCurrentDefault());
+                              base::SequencedTaskRunner::GetCurrentDefault(),
+                              SessionID::InvalidValue());
     task_environment_.RunUntilIdle();
   };
 
@@ -1280,7 +1444,8 @@
                                      /* is_cached_response */ true, _));
   test_url_loader_factory_.SetInterceptor(request_callback.Get());
   rt_service()->StartLookup(cached_url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   task_environment_.RunUntilIdle();
 }
@@ -1305,7 +1470,8 @@
                                      /* is_cached_response */ false, _));
   test_url_loader_factory_.SetInterceptor(request_callback.Get());
   rt_service()->StartLookup(url, response_callback.Get(),
-                            base::SequencedTaskRunner::GetCurrentDefault());
+                            base::SequencedTaskRunner::GetCurrentDefault(),
+                            SessionID::InvalidValue());
 
   task_environment_.RunUntilIdle();
 }
@@ -1325,7 +1491,8 @@
     EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ false,
                                        /* is_cached_response */ false, _));
     rt_service()->StartLookup(url, response_callback.Get(),
-                              base::SequencedTaskRunner::GetCurrentDefault());
+                              base::SequencedTaskRunner::GetCurrentDefault(),
+                              SessionID::InvalidValue());
     task_environment_.RunUntilIdle();
   };
 
diff --git a/components/safe_browsing/core/browser/referrer_chain_provider.h b/components/safe_browsing/core/browser/referrer_chain_provider.h
index fa50d9e7..d35ca11 100644
--- a/components/safe_browsing/core/browser/referrer_chain_provider.h
+++ b/components/safe_browsing/core/browser/referrer_chain_provider.h
@@ -46,6 +46,12 @@
       int user_gesture_count_limit,
       ReferrerChain* out_referrer_chain) = 0;
 
+  virtual AttributionResult IdentifyReferrerChainByEventURL(
+      const GURL& event_url,
+      SessionID event_tab_id,
+      int user_gesture_count_limit,
+      ReferrerChain* out_referrer_chain) = 0;
+
   virtual AttributionResult IdentifyReferrerChainByPendingEventURL(
       const GURL& event_url,
       int user_gesture_count_limit,
diff --git a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc
index bb031353..70cb27ff 100644
--- a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc
+++ b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc
@@ -123,7 +123,8 @@
     base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui,
     base::WeakPtr<HashRealTimeService> hash_realtime_service_on_ui,
     HashRealTimeSelection hash_realtime_selection,
-    bool is_async_check)
+    bool is_async_check,
+    SessionID tab_id)
     : headers_(headers),
       load_flags_(load_flags),
       request_destination_(request_destination),
@@ -144,7 +145,8 @@
       url_lookup_service_on_ui_(url_lookup_service_on_ui),
       hash_realtime_service_on_ui_(hash_realtime_service_on_ui),
       hash_realtime_selection_(hash_realtime_selection),
-      is_async_check_(is_async_check) {
+      is_async_check_(is_async_check),
+      tab_id_(tab_id) {
   DCHECK(url_real_time_lookup_enabled_ || can_check_db_);
 
   // This object is used exclusively on the IO thread but may be constructed on
@@ -469,7 +471,8 @@
         url, url_checker_delegate_->GetThreatTypes(), database_manager_,
         can_check_db_, can_check_high_confidence_allowlist_,
         url_lookup_service_metric_suffix_, ui_task_runner_,
-        url_lookup_service_on_ui_, url_checker_delegate_, web_contents_getter_);
+        url_lookup_service_on_ui_, url_checker_delegate_, web_contents_getter_,
+        tab_id_);
   } else if (!can_check_db_) {
     return KickOffLookupMechanismResult(
         SafeBrowsingLookupMechanism::StartCheckResult(
diff --git a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h
index d57a440c..f00ec13 100644
--- a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h
+++ b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h
@@ -124,7 +124,8 @@
       base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui,
       base::WeakPtr<HashRealTimeService> hash_realtime_service_on_ui,
       hash_realtime_utils::HashRealTimeSelection hash_realtime_selection,
-      bool is_async_check);
+      bool is_async_check,
+      SessionID tab_id);
 
   SafeBrowsingUrlCheckerImpl(const SafeBrowsingUrlCheckerImpl&) = delete;
   SafeBrowsingUrlCheckerImpl& operator=(const SafeBrowsingUrlCheckerImpl&) =
@@ -343,6 +344,10 @@
   // If this check allows navigation to commit before it completes.
   const bool is_async_check_;
 
+  // The current tab ID. Used sometimes for identifying the referrer chain for
+  // URL real-time lookups. Can be |SessionID::InvalidValue()|.
+  SessionID tab_id_;
+
   base::WeakPtrFactory<SafeBrowsingUrlCheckerImpl> weak_factory_{this};
 };
 
diff --git a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc
index e2ffa49..600ca734 100644
--- a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc
+++ b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc
@@ -24,6 +24,7 @@
 #include "components/safe_browsing/core/common/features.h"
 #include "components/safe_browsing/core/common/proto/csd.pb.h"
 #include "components/security_interstitials/core/unsafe_resource.h"
+#include "components/sessions/core/session_id.h"
 #include "net/http/http_request_headers.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -239,7 +240,8 @@
   void StartLookup(
       const GURL& gurl,
       RTLookupResponseCallback response_callback,
-      scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override {
+      scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+      SessionID tab_id) override {
     std::string url = gurl.spec();
     DCHECK(base::Contains(url_details_, url));
     auto response = std::make_unique<RTLookupResponse>();
@@ -288,7 +290,8 @@
 
   void SendSampledRequest(
       const GURL& gurl,
-      scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override {}
+      scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+      SessionID tab_id) override {}
 
   // |should_complete_lookup| should generally be true, unless you specifically
   // want to test time-sensitive things like timeouts. Setting it to false will
@@ -330,7 +333,8 @@
   void GetAccessToken(
       const GURL& url,
       RTLookupResponseCallback response_callback,
-      scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override {}
+      scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+      SessionID tab_id) override {}
   std::optional<std::string> GetDMTokenString() const override {
     return std::nullopt;
   }
@@ -435,7 +439,7 @@
                                      : nullptr,
         /*hash_realtime_service=*/hash_realtime_service_->GetWeakPtr(),
         hash_real_time_selection,
-        /*is_async_check=*/false);
+        /*is_async_check=*/false, SessionID::InvalidValue());
   }
 
  protected:
diff --git a/components/safe_browsing/core/browser/url_realtime_mechanism.cc b/components/safe_browsing/core/browser/url_realtime_mechanism.cc
index 5dadbaf1..48e635f68 100644
--- a/components/safe_browsing/core/browser/url_realtime_mechanism.cc
+++ b/components/safe_browsing/core/browser/url_realtime_mechanism.cc
@@ -45,7 +45,8 @@
     scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
     base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui,
     scoped_refptr<UrlCheckerDelegate> url_checker_delegate,
-    const base::RepeatingCallback<content::WebContents*()>& web_contents_getter)
+    const base::RepeatingCallback<content::WebContents*()>& web_contents_getter,
+    SessionID tab_id)
     : SafeBrowsingLookupMechanism(url, threat_types, database_manager),
       can_check_db_(can_check_db),
       can_check_high_confidence_allowlist_(can_check_high_confidence_allowlist),
@@ -53,7 +54,8 @@
       ui_task_runner_(ui_task_runner),
       url_lookup_service_on_ui_(url_lookup_service_on_ui),
       url_checker_delegate_(url_checker_delegate),
-      web_contents_getter_(web_contents_getter) {}
+      web_contents_getter_(web_contents_getter),
+      tab_id_(tab_id) {}
 
 UrlRealTimeMechanism::~UrlRealTimeMechanism() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -94,7 +96,7 @@
         FROM_HERE,
         base::BindOnce(&UrlRealTimeMechanism::MaybeSendSampleRequest,
                        weak_factory_.GetWeakPtr(), url_,
-                       url_lookup_service_on_ui_,
+                       url_lookup_service_on_ui_, tab_id_,
                        base::SequencedTaskRunner::GetCurrentDefault()));
     // If the URL matches the high-confidence allowlist, still do the hash based
     // checks.
@@ -107,7 +109,7 @@
         FROM_HERE,
         base::BindOnce(&UrlRealTimeMechanism::StartLookupOnUIThread,
                        weak_factory_.GetWeakPtr(), url_,
-                       url_lookup_service_on_ui_,
+                       url_lookup_service_on_ui_, tab_id_,
                        base::SequencedTaskRunner::GetCurrentDefault()));
   }
 }
@@ -117,6 +119,7 @@
     base::WeakPtr<UrlRealTimeMechanism> weak_ptr_on_io,
     const GURL& url,
     base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui,
+    SessionID tab_id,
     scoped_refptr<base::SequencedTaskRunner> io_task_runner) {
   bool is_lookup_service_found = !!url_lookup_service_on_ui;
   base::UmaHistogramBoolean("SafeBrowsing.RT.IsLookupServiceFound",
@@ -132,13 +135,14 @@
       base::BindOnce(&UrlRealTimeMechanism::OnLookupResponse, weak_ptr_on_io);
 
   url_lookup_service_on_ui->StartLookup(url, std::move(response_callback),
-                                        std::move(io_task_runner));
+                                        std::move(io_task_runner), tab_id);
 }
 
 void UrlRealTimeMechanism::MaybeSendSampleRequest(
     base::WeakPtr<UrlRealTimeMechanism> weak_ptr_on_io,
     const GURL& url,
     base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui,
+    SessionID tab_id,
     scoped_refptr<base::SequencedTaskRunner> io_task_runner) {
   bool can_send_protego_sampled_ping =
       url_lookup_service_on_ui &&
@@ -150,8 +154,8 @@
   bool is_lookup_service_available =
       !url_lookup_service_on_ui->IsInBackoffMode();
   if (is_lookup_service_available) {
-    url_lookup_service_on_ui->SendSampledRequest(url,
-                                                 std::move(io_task_runner));
+    url_lookup_service_on_ui->SendSampledRequest(url, std::move(io_task_runner),
+                                                 tab_id);
   }
 }
 
diff --git a/components/safe_browsing/core/browser/url_realtime_mechanism.h b/components/safe_browsing/core/browser/url_realtime_mechanism.h
index 1118165..49b2a9d 100644
--- a/components/safe_browsing/core/browser/url_realtime_mechanism.h
+++ b/components/safe_browsing/core/browser/url_realtime_mechanism.h
@@ -17,6 +17,7 @@
 #include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism.h"
 #include "components/safe_browsing/core/browser/url_checker_delegate.h"
 #include "components/safe_browsing/core/common/proto/realtimeapi.pb.h"
+#include "components/sessions/core/session_id.h"
 #include "url/gurl.h"
 
 namespace safe_browsing {
@@ -35,7 +36,8 @@
       base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui,
       scoped_refptr<UrlCheckerDelegate> url_checker_delegate,
       const base::RepeatingCallback<content::WebContents*()>&
-          web_contents_getter);
+          web_contents_getter,
+      SessionID tab_id);
   UrlRealTimeMechanism(const UrlRealTimeMechanism&) = delete;
   UrlRealTimeMechanism& operator=(const UrlRealTimeMechanism&) = delete;
   ~UrlRealTimeMechanism() override;
@@ -56,6 +58,7 @@
       base::WeakPtr<UrlRealTimeMechanism> weak_ptr_on_io,
       const GURL& url,
       base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui,
+      SessionID tab_id,
       scoped_refptr<base::SequencedTaskRunner> io_task_runner);
 
   // Checks the eligibility of sending a sampled ping first;
@@ -64,6 +67,7 @@
       base::WeakPtr<UrlRealTimeMechanism> weak_ptr_on_io,
       const GURL& url,
       base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui,
+      SessionID tab_id,
       scoped_refptr<base::SequencedTaskRunner> io_task_runner);
 
   // Called when the |response| from the real-time lookup service is received.
@@ -129,6 +133,10 @@
   // back to the hash-based checks.
   std::unique_ptr<DatabaseManagerMechanism> hash_database_mechanism_ = nullptr;
 
+  // The current tab ID. Used sometimes for identifying the referrer chain. Can
+  // be |SessionID::InvalidValue()|.
+  SessionID tab_id_;
+
   base::WeakPtrFactory<UrlRealTimeMechanism> weak_factory_{this};
 };
 
diff --git a/components/safe_browsing/core/common/safebrowsing_referral_methods.h b/components/safe_browsing/core/common/safebrowsing_referral_methods.h
index e4c9591..2a627c8 100644
--- a/components/safe_browsing/core/common/safebrowsing_referral_methods.h
+++ b/components/safe_browsing/core/common/safebrowsing_referral_methods.h
@@ -15,7 +15,8 @@
   kPromoSlingerReferral = 2,
   kDownloadBubbleSubpage = 3,
   kDownloadButtonIphPromo = 4,
-  kMaxValue = kDownloadButtonIphPromo,
+  kDownloadPageRowPromo = 5,
+  kMaxValue = kDownloadPageRowPromo,
 };
 
 }  // namespace safe_browsing
diff --git a/components/sync/protocol/history_specifics.proto b/components/sync/protocol/history_specifics.proto
index a2ebdf7..7b90a7a9 100644
--- a/components/sync/protocol/history_specifics.proto
+++ b/components/sync/protocol/history_specifics.proto
@@ -145,4 +145,8 @@
 
   // Related search URLs for a Google SRP visit, to provide next steps to user.
   repeated string related_searches = 25;
+
+  // ID of the app (non-BrApp) this entity was generated for, if any. Only
+  // visits originating from Android devices may have this set.
+  optional string app_id = 26;
 }
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h
index aad6bcd8..ff83440 100644
--- a/components/sync/protocol/proto_visitors.h
+++ b/components/sync/protocol/proto_visitors.h
@@ -929,6 +929,7 @@
   VISIT(has_url_keyed_image);
   VISIT_REP(categories);
   VISIT_REP(related_searches);
+  VISIT(app_id);
 }
 
 VISIT_PROTO_FIELDS(
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index e26ae1e..954c87a 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -219,6 +219,7 @@
     "resources/bitmap_allocation.h",
     "resources/platform_color.h",
     "resources/release_callback.h",
+    "resources/resource_id.cc",
     "resources/resource_id.h",
     "resources/return_callback.h",
     "resources/returned_resource.cc",
diff --git a/components/viz/common/quads/compositor_frame_metadata.h b/components/viz/common/quads/compositor_frame_metadata.h
index fb78a5d..fbc373c7 100644
--- a/components/viz/common/quads/compositor_frame_metadata.h
+++ b/components/viz/common/quads/compositor_frame_metadata.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <limits>
 #include <memory>
 #include <optional>
 #include <vector>
@@ -35,10 +36,14 @@
 
 namespace viz {
 
-// A frame token value of 0 indicates an invalid or local frame token. A
+// A frame token value of 0 indicates an invalid token.
+inline constexpr uint32_t kInvalidFrameToken = 0;
+
+// A frame token value of `kLocalFrameToken` indicates a local frame token. A
 // local frame token is used inside viz when it creates its own CompositorFrame
 // for a surface.
-inline constexpr uint32_t kInvalidOrLocalFrameToken = 0;
+inline constexpr uint32_t kLocalFrameToken =
+    std::numeric_limits<uint32_t>::max();
 
 // Compares two frame tokens, handling cases where the token wraps around the
 // 32-bit max value.
@@ -51,7 +56,11 @@
 class VIZ_COMMON_EXPORT FrameTokenGenerator {
  public:
   inline uint32_t operator++() {
-    if (++frame_token_ == kInvalidOrLocalFrameToken) {
+    ++frame_token_;
+    if (frame_token_ == kLocalFrameToken) {
+      ++frame_token_;
+    }
+    if (frame_token_ == kInvalidFrameToken) {
       ++frame_token_;
     }
     return frame_token_;
@@ -60,7 +69,7 @@
   inline uint32_t operator*() const { return frame_token_; }
 
  private:
-  uint32_t frame_token_ = kInvalidOrLocalFrameToken;
+  uint32_t frame_token_ = kInvalidFrameToken;
 };
 
 class VIZ_COMMON_EXPORT CompositorFrameMetadata {
@@ -143,7 +152,7 @@
   // after the 32-bit max value.
   // TODO(crbug.com/850386): A custom type would be better to avoid incorrect
   // comparisons.
-  uint32_t frame_token = kInvalidOrLocalFrameToken;
+  uint32_t frame_token = kInvalidFrameToken;
 
   // Once the display compositor processes a frame with
   // |send_frame_token_to_embedder| flag turned on, the |frame_token| for the
diff --git a/components/viz/common/resources/resource_id.cc b/components/viz/common/resources/resource_id.cc
new file mode 100644
index 0000000..0bb5d95
--- /dev/null
+++ b/components/viz/common/resources/resource_id.cc
@@ -0,0 +1,49 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/common/resources/resource_id.h"
+
+namespace viz {
+
+ReservedResourceIdTracker::ReservedResourceIdTracker() = default;
+ReservedResourceIdTracker::~ReservedResourceIdTracker() = default;
+
+ResourceId ReservedResourceIdTracker::AllocId(int initial_ref_count) {
+  // Check we can allocate an ID.
+  CHECK_LT(id_ref_counts_.size(), kNumReservedResourceIds);
+
+  // Find the next available ID. This is guaranteed to terminate because we
+  // checked there is at least one available ID.
+  while (id_ref_counts_.contains(ResourceId(next_id_))) {
+    if (next_id_ == std::numeric_limits<uint32_t>::max()) {
+      next_id_ = kVizReservedRangeStartId.GetUnsafeValue();
+    } else {
+      ++next_id_;
+    }
+  }
+  DCHECK_GE(next_id_, kVizReservedRangeStartId.GetUnsafeValue());
+  auto id = ResourceId(next_id_);
+  id_ref_counts_[id] = initial_ref_count;
+  return id;
+}
+
+void ReservedResourceIdTracker::RefId(ResourceId id, int count) {
+  auto iter = id_ref_counts_.find(id);
+  CHECK(iter != id_ref_counts_.end());
+  iter->second += count;
+}
+
+bool ReservedResourceIdTracker::UnrefId(ResourceId id, int count) {
+  auto iter = id_ref_counts_.find(id);
+  CHECK(iter != id_ref_counts_.end());
+  CHECK_GE(iter->second, count);
+  iter->second -= count;
+  if (iter->second == 0) {
+    id_ref_counts_.erase(iter);
+    return true;
+  }
+  return false;
+}
+
+}  // namespace viz
diff --git a/components/viz/common/resources/resource_id.h b/components/viz/common/resources/resource_id.h
index ab76cb4..6ded665 100644
--- a/components/viz/common/resources/resource_id.h
+++ b/components/viz/common/resources/resource_id.h
@@ -9,10 +9,13 @@
 
 #include <functional>
 #include <limits>
+#include <map>
 
 #include "base/check_op.h"
+#include "base/containers/contains.h"
 #include "base/containers/flat_set.h"
 #include "base/types/id_type.h"
+#include "components/viz/common/viz_common_export.h"
 
 namespace viz {
 
@@ -22,11 +25,12 @@
 // ResourceIdGenerator below, since it will skip generating reserved ids.
 using ResourceId = base::IdTypeU32<ResourceIdTypeMarker>;
 using ResourceIdSet = base::flat_set<ResourceId>;
-constexpr ResourceId kInvalidResourceId(0);
-constexpr ResourceId kVizReservedRangeStartId(
-    std::numeric_limits<uint32_t>::max() - 3000u);
+inline constexpr ResourceId kInvalidResourceId(0);
+inline constexpr uint32_t kNumReservedResourceIds = 3000u;
+inline constexpr ResourceId kVizReservedRangeStartId(
+    std::numeric_limits<uint32_t>::max() - kNumReservedResourceIds);
 
-class ResourceIdGenerator {
+class VIZ_COMMON_EXPORT ResourceIdGenerator {
  public:
   explicit ResourceIdGenerator(uint32_t start_id)
       : start_id_(start_id), next_id_(start_id) {
@@ -52,12 +56,37 @@
   uint32_t next_id_ = 1u;
 };
 
-struct ResourceIdHasher {
+struct VIZ_COMMON_EXPORT ResourceIdHasher {
   size_t operator()(const ResourceId& resource_id) const {
     return std::hash<uint32_t>()(resource_id.GetUnsafeValue());
   }
 };
 
+// ReservedResourceIdTracker is used for keeping track of refcounts on viz
+// reserved resources and allocating unused resource IDs. Since the resource ID
+// space for reserved resources is much smaller than the client resource ID
+// space, we keep track of which resource IDs are used individually, so we can
+// allocate resource IDs that are no longer used and avoid reusing IDs that are
+// still in use.
+class VIZ_COMMON_EXPORT ReservedResourceIdTracker {
+ public:
+  ReservedResourceIdTracker();
+  ~ReservedResourceIdTracker();
+
+  [[nodiscard]] ResourceId AllocId(int initial_ref_count);
+  void RefId(ResourceId id, int count);
+
+  // Unrefs the given `id`. Returns true if there are no more refs to this
+  // resource id.
+  bool UnrefId(ResourceId id, int count);
+
+  void set_next_id_for_test(uint32_t next_id) { next_id_ = next_id; }
+
+ private:
+  uint32_t next_id_ = kVizReservedRangeStartId.GetUnsafeValue();
+  std::map<ResourceId, int> id_ref_counts_;
+};
+
 }  // namespace viz
 
 #endif  // COMPONENTS_VIZ_COMMON_RESOURCES_RESOURCE_ID_H_
diff --git a/components/viz/service/display/display_unittest.cc b/components/viz/service/display/display_unittest.cc
index 96bae9f1..670ce81 100644
--- a/components/viz/service/display/display_unittest.cc
+++ b/components/viz/service/display/display_unittest.cc
@@ -3629,8 +3629,8 @@
   display_->Resize(display_size);
   const gfx::Size sub_surface_size(32, 32);
 
-  uint32_t frame_token_1 = kInvalidOrLocalFrameToken;
-  uint32_t frame_token_2 = kInvalidOrLocalFrameToken;
+  uint32_t frame_token_1 = kInvalidFrameToken;
+  uint32_t frame_token_2 = kInvalidFrameToken;
   {
     CompositorFrame frame =
         CompositorFrameBuilder()
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index eaec952..b79c86f 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -25,6 +25,7 @@
 #include "components/viz/common/features.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
 #include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/common/quads/compositor_frame_metadata.h"
 #include "components/viz/common/quads/compositor_render_pass.h"
 #include "components/viz/common/resources/bitmap_allocation.h"
 #include "components/viz/common/surfaces/surface_info.h"
@@ -392,24 +393,30 @@
     base::TimeTicks draw_start_timestamp,
     const gfx::SwapTimings& swap_timings,
     const gfx::PresentationFeedback& feedback) {
-  DidPresentCompositorFrame(frame_token, draw_start_timestamp, swap_timings,
-                            feedback);
+  // If the frame was submitted locally (from inside viz), do not tell the
+  // client about it, since the client did not send it.
+  if (frame_token != kLocalFrameToken) {
+    DidPresentCompositorFrame(frame_token, draw_start_timestamp, swap_timings,
+                              feedback);
+  }
 }
 
 void CompositorFrameSinkSupport::RefResources(
     const std::vector<TransferableResource>& resources) {
-  if (surface_animation_manager_)
-    surface_animation_manager_->RefResources(resources);
+  if (reserved_resource_delegate_) {
+    reserved_resource_delegate_->RefResources(resources);
+  }
   surface_resource_holder_.RefResources(resources);
 }
 
 void CompositorFrameSinkSupport::UnrefResources(
     std::vector<ReturnedResource> resources) {
-  // |surface_animation_manager_| allocates ResourceIds in a different range
+  // `ReservedResourceDelegate` allocates ResourceIds in a different range
   // than the client so it can process returned resources before
   // |surface_resource_holder_|.
-  if (surface_animation_manager_)
-    surface_animation_manager_->UnrefResources(resources);
+  if (reserved_resource_delegate_) {
+    reserved_resource_delegate_->UnrefResources(resources);
+  }
   surface_resource_holder_.UnrefResources(std::move(resources));
 }
 
@@ -441,6 +448,9 @@
 
 void CompositorFrameSinkSupport::ReceiveFromChild(
     const std::vector<TransferableResource>& resources) {
+  if (reserved_resource_delegate_) {
+    reserved_resource_delegate_->ReceiveFromChild(resources);
+  }
   surface_resource_holder_.ReceiveFromChild(resources);
 }
 
@@ -576,6 +586,26 @@
   }
 }
 
+void CompositorFrameSinkSupport::SetSurfaceAnimationManager(
+    std::unique_ptr<SurfaceAnimationManager> surface_animation_manager) {
+  // We only support one of SurfaceAnimationManager or a custom
+  // `ReservedResourceDelegate` for the lifetime of a CFSS. If we are setting
+  // `surface_animation_manager_`, then either there is no current one and it
+  // and `reserved_resource_delegate_` should be nullptr, or we are setting a
+  // new one and the previous values should be equal.
+  CHECK_EQ(surface_animation_manager_.get(), reserved_resource_delegate_);
+  reserved_resource_delegate_ = surface_animation_manager.get();
+  surface_animation_manager_ = std::move(surface_animation_manager);
+}
+
+std::unique_ptr<SurfaceAnimationManager>
+CompositorFrameSinkSupport::TakeSurfaceAnimationManager() {
+  // See comment in `SetSurfaceAnimationManager` about this CHECK.
+  CHECK_EQ(surface_animation_manager_.get(), reserved_resource_delegate_);
+  reserved_resource_delegate_ = nullptr;
+  return std::move(surface_animation_manager_);
+}
+
 base::TimeDelta CompositorFrameSinkSupport::GetPreferredFrameInterval(
     mojom::CompositorFrameSinkType* type) const {
   if (type)
@@ -974,7 +1004,8 @@
     base::TimeTicks draw_start_timestamp,
     const gfx::SwapTimings& swap_timings,
     const gfx::PresentationFeedback& feedback) {
-  CHECK_NE(frame_token, kInvalidOrLocalFrameToken);
+  CHECK_NE(frame_token, kInvalidFrameToken);
+  CHECK_NE(frame_token, kLocalFrameToken);
   DCHECK((feedback.flags & gfx::PresentationFeedback::kFailure) ||
          (!draw_start_timestamp.is_null() && !swap_timings.is_null()));
 
@@ -1496,11 +1527,11 @@
       // Initialize this before creating the SurfaceAnimationManager since the
       // save operation may execute synchronously.
       in_flight_save_sequence_id_ = directive.sequence_id();
-      surface_animation_manager_ = SurfaceAnimationManager::CreateWithSave(
+      SetSurfaceAnimationManager(SurfaceAnimationManager::CreateWithSave(
           directive, surface, frame_sink_manager_->shared_bitmap_manager(),
           base::BindOnce(&CompositorFrameSinkSupport::
                              OnCompositorFrameTransitionDirectiveProcessed,
-                         base::Unretained(this)));
+                         base::Unretained(this))));
       break;
     case CompositorFrameTransitionDirective::Type::kAnimateRenderer:
       // The save operation must have been executed before we see an animate
@@ -1518,9 +1549,9 @@
                      << directive.navigation_id();
         }
 
-        surface_animation_manager_ =
+        SetSurfaceAnimationManager(
             frame_sink_manager_->TakeSurfaceAnimationManager(
-                directive.navigation_id());
+                directive.navigation_id()));
       }
 
       if (surface_animation_manager_)
@@ -1530,7 +1561,7 @@
 
       break;
     case CompositorFrameTransitionDirective::Type::kRelease:
-      surface_animation_manager_.reset();
+      SetSurfaceAnimationManager(nullptr);
 
       // This `surface_animation_manager_` could correspond to an in-flight
       // save, reset the tracking here.
@@ -1568,7 +1599,7 @@
     // SurfaceAnimationManager for this |navigation_id|. Should never happen
     // but handled safely because its untrusted input from the renderer.
     frame_sink_manager_->CacheSurfaceAnimationManager(
-        directive.navigation_id(), std::move(surface_animation_manager_));
+        directive.navigation_id(), TakeSurfaceAnimationManager());
   }
 
   in_flight_save_sequence_id_ = 0;
@@ -1632,6 +1663,14 @@
   return surface_animation_manager_.get();
 }
 
+void CompositorFrameSinkSupport::SetReservedResourceDelegate(
+    ReservedResourceDelegate* delegate) {
+  // We only support a custom `ReservedResourceDelegate` on root CFSS. So make
+  // sure `surface_animation_manager_` is not set.
+  CHECK(!surface_animation_manager_);
+  reserved_resource_delegate_ = delegate;
+}
+
 void CompositorFrameSinkSupport::DestroySelf() {
   // SUBTLE: We explicitly copy `frame_sink_id_` because
   // DestroyCompositorFrameSink takes the FrameSinkId by reference and may
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index 2ab23f7..d61eb30 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -273,6 +273,8 @@
     return frame_sink_type_;
   }
 
+  void SetReservedResourceDelegate(ReservedResourceDelegate* delegate);
+
  private:
   friend class CompositorFrameSinkSupportTest;
   friend class DisplayTest;
@@ -356,6 +358,10 @@
       base::flat_set<base::PlatformThreadId> thread_ids,
       bool passed_verification);
 
+  void SetSurfaceAnimationManager(
+      std::unique_ptr<SurfaceAnimationManager> surface_animation_manager);
+  std::unique_ptr<SurfaceAnimationManager> TakeSurfaceAnimationManager();
+
   const raw_ptr<mojom::CompositorFrameSinkClient> client_;
 
   const raw_ptr<FrameSinkManagerImpl> frame_sink_manager_;
@@ -508,6 +514,12 @@
   // frames may be produced by Surfaces managed by distinct
   // CompositorFrameSinks.
   std::unique_ptr<SurfaceAnimationManager> surface_animation_manager_;
+
+  // This is used for any viz side resources that are managed by viz. These
+  // resources must use the reserved resource range defined by
+  // `kVizReservedRangeStartId`.
+  raw_ptr<ReservedResourceDelegate> reserved_resource_delegate_ = nullptr;
+
   // The sequence ID for the save directive pending copy.
   uint32_t in_flight_save_sequence_id_ = 0;
 
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
index fc8cd6e3..df87632 100644
--- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
+++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
@@ -288,7 +288,7 @@
     CompositorFrame frame;
 
     auto& metadata = frame.metadata;
-    metadata.frame_token = kInvalidOrLocalFrameToken;
+    metadata.frame_token = kLocalFrameToken;
 
     // The given `surface_id` may be newer than `current_surface_id`, so use the
     // one we actually have.
diff --git a/components/viz/service/frame_sinks/surface_resource_holder.cc b/components/viz/service/frame_sinks/surface_resource_holder.cc
index d47ff53..fc44a25 100644
--- a/components/viz/service/frame_sinks/surface_resource_holder.cc
+++ b/components/viz/service/frame_sinks/surface_resource_holder.cc
@@ -4,11 +4,15 @@
 
 #include "components/viz/service/frame_sinks/surface_resource_holder.h"
 
+#include <utility>
+
 #include "base/check.h"
 #include "components/viz/service/frame_sinks/surface_resource_holder_client.h"
 
 namespace viz {
 
+ReservedResourceDelegate::~ReservedResourceDelegate() = default;
+
 SurfaceResourceHolder::SurfaceResourceHolder(
     SurfaceResourceHolderClient* client)
     : client_(client) {}
@@ -22,6 +26,16 @@
 void SurfaceResourceHolder::ReceiveFromChild(
     const std::vector<TransferableResource>& resources) {
   for (const auto& resource : resources) {
+    // We don't handle reserved resources here. CompositorFrames from clients
+    // can never contain reserved ResourceIds, but viz can pretend to submit
+    // frames from the client (see
+    // `CompositorFrameSinkSupport::SubmitCompositorFrameLocally`), e.g. for
+    // frame eviction purposes. Those CompositorFrames may contain reserved
+    // resources, so ignore them here.
+    if (resource.id >= kVizReservedRangeStartId) {
+      continue;
+    }
+
     ResourceRefs& ref = resource_id_info_map_[resource.id];
     ref.refs_holding_resource_alive++;
     ref.refs_received_from_child++;
diff --git a/components/viz/service/frame_sinks/surface_resource_holder.h b/components/viz/service/frame_sinks/surface_resource_holder.h
index 1eb14669..0a480a43 100644
--- a/components/viz/service/frame_sinks/surface_resource_holder.h
+++ b/components/viz/service/frame_sinks/surface_resource_holder.h
@@ -17,6 +17,21 @@
 namespace viz {
 class SurfaceResourceHolderClient;
 
+// ReservedResourceDelegate is an interface for tracking the lifetime of
+// resources. Code which submits resources that are managed fully on the viz
+// side (with resource IDs >= kVizReservedRangeStartId) should implement this.
+class ReservedResourceDelegate {
+ public:
+  virtual ~ReservedResourceDelegate();
+
+  virtual void ReceiveFromChild(
+      const std::vector<TransferableResource>& resources) = 0;
+  virtual void RefResources(
+      const std::vector<TransferableResource>& resources) = 0;
+  virtual void UnrefResources(
+      const std::vector<ReturnedResource>& resources) = 0;
+};
+
 // A SurfaceResourceHolder manages the lifetime of resources submitted by a
 // particular SurfaceFactory. Each resource is held by the service until
 // it is no longer referenced by any pending frames or by any
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc
index c430a718..b455c746a 100644
--- a/components/viz/service/surfaces/surface.cc
+++ b/components/viz/service/surfaces/surface.cc
@@ -76,7 +76,7 @@
     base::TimeTicks draw_start_timestamp,
     const gfx::SwapTimings& swap_timings,
     const gfx::PresentationFeedback& feedback) {
-  if (surface_client_ && frame_token_ != kInvalidOrLocalFrameToken) {
+  if (surface_client_) {
     surface_client_->OnSurfacePresented(frame_token_, draw_start_timestamp,
                                         swap_timings, feedback);
   }
diff --git a/components/viz/service/surfaces/surface_unittest.cc b/components/viz/service/surfaces/surface_unittest.cc
index 1e85538..4fd0c52 100644
--- a/components/viz/service/surfaces/surface_unittest.cc
+++ b/components/viz/service/surfaces/surface_unittest.cc
@@ -81,7 +81,7 @@
   if (BeginFrameAcksEnabled()) {
     support->SetWantsBeginFrameAcks();
   }
-  uint32_t frame_token = kInvalidOrLocalFrameToken;
+  uint32_t frame_token = kInvalidFrameToken;
   {
     CompositorFrame frame =
         CompositorFrameBuilder()
@@ -89,7 +89,7 @@
             .SetBeginFrameSourceId(kBeginFrameSourceId)
             .Build();
     frame_token = frame.metadata.frame_token;
-    ASSERT_NE(frame_token, kInvalidOrLocalFrameToken);
+    ASSERT_NE(frame_token, kInvalidFrameToken);
     EXPECT_CALL(client, DidReceiveCompositorFrameAck(testing::_))
         .Times(BeginFrameAcksEnabled() ? 0 : 1);
     support->SubmitCompositorFrame(local_surface_id, std::move(frame));
diff --git a/components/viz/service/transitions/DEPS b/components/viz/service/transitions/DEPS
index 5009321..902363c5 100644
--- a/components/viz/service/transitions/DEPS
+++ b/components/viz/service/transitions/DEPS
@@ -2,6 +2,7 @@
 
 include_rules = [
   "+components/viz/service/display/shared_bitmap_manager.h",
+  "+components/viz/service/frame_sinks",
   "+components/viz/service/surfaces",
   "+gpu/command_buffer/common",
 ]
diff --git a/components/viz/service/transitions/surface_animation_manager.cc b/components/viz/service/transitions/surface_animation_manager.cc
index 5e21393..c50ba22 100644
--- a/components/viz/service/transitions/surface_animation_manager.cc
+++ b/components/viz/service/transitions/surface_animation_manager.cc
@@ -179,6 +179,12 @@
   empty_resource_ids_.clear();
 }
 
+void SurfaceAnimationManager::ReceiveFromChild(
+    const std::vector<TransferableResource>& resources) {
+  // We don't do anything here, because resources are initially reffed via
+  // `ImportResources`.
+}
+
 void SurfaceAnimationManager::RefResources(
     const std::vector<TransferableResource>& resources) {
   if (transferable_resource_tracker_.is_empty())
diff --git a/components/viz/service/transitions/surface_animation_manager.h b/components/viz/service/transitions/surface_animation_manager.h
index c3cecb8..f2a857b 100644
--- a/components/viz/service/transitions/surface_animation_manager.h
+++ b/components/viz/service/transitions/surface_animation_manager.h
@@ -17,6 +17,7 @@
 #include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
 #include "components/viz/common/resources/resource_id.h"
 #include "components/viz/service/display/shared_bitmap_manager.h"
+#include "components/viz/service/frame_sinks/surface_resource_holder.h"
 #include "components/viz/service/surfaces/surface_saved_frame.h"
 #include "components/viz/service/transitions/transferable_resource_tracker.h"
 #include "components/viz/service/viz_service_export.h"
@@ -36,7 +37,8 @@
 //
 // This class is owned by CompositorFrameSinkSupport but can be moved between
 // CompositorFrameSinkSupports for transitions between 2 renderer CC instances.
-class VIZ_SERVICE_EXPORT SurfaceAnimationManager {
+class VIZ_SERVICE_EXPORT SurfaceAnimationManager
+    : public ReservedResourceDelegate {
  public:
   using TransitionDirectiveCompleteCallback =
       base::OnceCallback<void(const CompositorFrameTransitionDirective&)>;
@@ -47,13 +49,16 @@
       SharedBitmapManager* shared_bitmap_manager,
       TransitionDirectiveCompleteCallback sequence_id_finished_callback);
 
-  ~SurfaceAnimationManager();
+  ~SurfaceAnimationManager() override;
 
   void Animate();
 
-  // Resource ref count management.
-  void RefResources(const std::vector<TransferableResource>& resources);
-  void UnrefResources(const std::vector<ReturnedResource>& resources);
+  // ReservedResourceDelegate:
+  void ReceiveFromChild(
+      const std::vector<TransferableResource>& resources) override;
+  void RefResources(
+      const std::vector<TransferableResource>& resources) override;
+  void UnrefResources(const std::vector<ReturnedResource>& resources) override;
 
   // Replaced ViewTransitionElementResourceIds with corresponding ResourceIds if
   // necessary.
diff --git a/components/viz/service/transitions/transferable_resource_tracker.cc b/components/viz/service/transitions/transferable_resource_tracker.cc
index e852b483..203610ed 100644
--- a/components/viz/service/transitions/transferable_resource_tracker.cc
+++ b/components/viz/service/transitions/transferable_resource_tracker.cc
@@ -23,9 +23,7 @@
 
 TransferableResourceTracker::TransferableResourceTracker(
     SharedBitmapManager* shared_bitmap_manager)
-    : starting_id_(kVizReservedRangeStartId.GetUnsafeValue()),
-      next_id_(kVizReservedRangeStartId.GetUnsafeValue()),
-      shared_bitmap_manager_(shared_bitmap_manager) {}
+    : shared_bitmap_manager_(shared_bitmap_manager) {}
 
 TransferableResourceTracker::~TransferableResourceTracker() = default;
 
@@ -112,7 +110,7 @@
     }
   }
 
-  resource.id = GetNextAvailableResourceId();
+  resource.id = id_tracker_.AllocId(/*initial_ref_count=*/1);
   DCHECK(!base::Contains(managed_resources_, resource.id));
   managed_resources_.emplace(
       resource.id,
@@ -133,39 +131,15 @@
 
 void TransferableResourceTracker::RefResource(ResourceId id) {
   DCHECK(base::Contains(managed_resources_, id));
-  ++managed_resources_[id].ref_count;
+  id_tracker_.RefId(id, /*count=*/1);
 }
 
 void TransferableResourceTracker::UnrefResource(ResourceId id, int count) {
   DCHECK(base::Contains(managed_resources_, id));
-  DCHECK_LE(count, managed_resources_[id].ref_count);
-  managed_resources_[id].ref_count -= count;
-  if (managed_resources_[id].ref_count == 0)
+
+  if (id_tracker_.UnrefId(id, count)) {
     managed_resources_.erase(id);
-}
-
-ResourceId TransferableResourceTracker::GetNextAvailableResourceId() {
-  uint32_t result = next_id_;
-
-  // Since we're working with a limit range of resources, it is a lot more
-  // likely that we will loop back to the starting id after running out of
-  // resource ids. This loop ensures that `next_id_` is set to a value that is
-  // not `result` and is also available in that it's currently tracked by
-  // `managed_resources_`. Note that if we end up looping twice, we fail with a
-  // CHECK since we don't have any available resources for this request.
-  bool looped = false;
-  while (next_id_ == result ||
-         base::Contains(managed_resources_, ResourceId(next_id_))) {
-    if (next_id_ == std::numeric_limits<uint32_t>::max()) {
-      CHECK(!looped);
-      next_id_ = starting_id_;
-      looped = true;
-    } else {
-      ++next_id_;
-    }
   }
-  DCHECK_GE(result, kVizReservedRangeStartId.GetUnsafeValue());
-  return ResourceId(result);
 }
 
 TransferableResourceTracker::TransferableResourceHolder::
@@ -175,9 +149,7 @@
 TransferableResourceTracker::TransferableResourceHolder::
     TransferableResourceHolder(const TransferableResource& resource,
                                ResourceReleaseCallback release_callback)
-    : resource(resource),
-      release_callback(std::move(release_callback)),
-      ref_count(1u) {}
+    : resource(resource), release_callback(std::move(release_callback)) {}
 
 TransferableResourceTracker::TransferableResourceHolder::
     ~TransferableResourceHolder() {
diff --git a/components/viz/service/transitions/transferable_resource_tracker.h b/components/viz/service/transitions/transferable_resource_tracker.h
index 8af36c0..ff86954 100644
--- a/components/viz/service/transitions/transferable_resource_tracker.h
+++ b/components/viz/service/transitions/transferable_resource_tracker.h
@@ -89,8 +89,6 @@
  private:
   friend class TransferableResourceTrackerTest;
 
-  ResourceId GetNextAvailableResourceId();
-
   PositionedResource ImportResource(
       SurfaceSavedFrame::OutputCopyResult output_copy);
 
@@ -98,9 +96,6 @@
                              uint32_t>::value,
                 "ResourceId underlying type should be uint32_t");
 
-  const uint32_t starting_id_;
-  uint32_t next_id_;
-
   const raw_ptr<SharedBitmapManager> shared_bitmap_manager_;
 
   struct TransferableResourceHolder {
@@ -116,9 +111,10 @@
 
     TransferableResource resource;
     ResourceReleaseCallback release_callback;
-    int ref_count = 0;
   };
 
+  ReservedResourceIdTracker id_tracker_;
+
   std::map<ResourceId, TransferableResourceHolder> managed_resources_;
 };
 
diff --git a/components/viz/service/transitions/transferable_resource_tracker_unittest.cc b/components/viz/service/transitions/transferable_resource_tracker_unittest.cc
index bc70416..a7e9be24 100644
--- a/components/viz/service/transitions/transferable_resource_tracker_unittest.cc
+++ b/components/viz/service/transitions/transferable_resource_tracker_unittest.cc
@@ -34,7 +34,7 @@
 class TransferableResourceTrackerTest : public testing::Test {
  public:
   void SetNextId(TransferableResourceTracker* tracker, uint32_t id) {
-    tracker->next_id_ = id;
+    tracker->id_tracker_.set_next_id_for_test(id);
   }
 
   // Returns if there is a SharedBitmap in SharedBitmapManager for |resource|.
@@ -85,6 +85,7 @@
   SetNextId(&tracker, next_id);
 
   ResourceId last_id = kInvalidResourceId;
+  std::vector<TransferableResourceTracker::ResourceFrame> frames;
   for (int i = 0; i < 10; ++i) {
     auto frame = tracker.ImportResources(CreateFrameWithResult());
     ASSERT_EQ(frame.shared.size(), 1u);
@@ -94,8 +95,11 @@
     EXPECT_GE(resource->resource.id, kVizReservedRangeStartId);
     EXPECT_NE(resource->resource.id, last_id);
     last_id = resource->resource.id;
+    frames.push_back(std::move(frame));
+  }
+  for (auto& frame : frames) {
     tracker.ReturnFrame(frame);
-    EXPECT_FALSE(HasBitmapResource(resource->resource));
+    EXPECT_FALSE(HasBitmapResource(frame.shared.at(0)->resource));
   }
 }
 
@@ -131,6 +135,7 @@
   SetNextId(&tracker, next_id);
 
   ResourceId last_id = kInvalidResourceId;
+  std::vector<TransferableResourceTracker::ResourceFrame> frames;
   for (int i = 0; i < 10; ++i) {
     auto frame = tracker.ImportResources(CreateFrameWithResult());
     ASSERT_EQ(frame.shared.size(), 1u);
@@ -141,8 +146,11 @@
     EXPECT_NE(new_resource->resource.id, last_id);
     EXPECT_NE(new_resource->resource.id, resource->resource.id);
     last_id = new_resource->resource.id;
+    frames.push_back(std::move(frame));
+  }
+  for (auto& frame : frames) {
     tracker.ReturnFrame(frame);
-    EXPECT_FALSE(HasBitmapResource(new_resource->resource));
+    EXPECT_FALSE(HasBitmapResource(frame.shared.at(0)->resource));
   }
 }
 
diff --git a/components/viz/test/fake_host_frame_sink_client.h b/components/viz/test/fake_host_frame_sink_client.h
index 4ca2a27..827b842 100644
--- a/components/viz/test/fake_host_frame_sink_client.h
+++ b/components/viz/test/fake_host_frame_sink_client.h
@@ -29,7 +29,7 @@
   uint32_t last_frame_token_seen() const { return last_frame_token_seen_; }
 
  private:
-  uint32_t last_frame_token_seen_ = kInvalidOrLocalFrameToken;
+  uint32_t last_frame_token_seen_ = kInvalidFrameToken;
 };
 
 }  // namespace viz
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 9480a24..79e2564 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -2780,6 +2780,8 @@
       "child_process_launcher_helper_win.cc",
       "device_posture/device_posture_platform_provider_win.cc",
       "device_posture/device_posture_platform_provider_win.h",
+      "device_posture/device_posture_registry_watcher_win.cc",
+      "device_posture/device_posture_registry_watcher_win.h",
       "font_access/font_enumeration_data_source_win.cc",
       "font_access/font_enumeration_data_source_win.h",
       "installedapp/installed_app_provider_impl_win.cc",
diff --git a/content/browser/blob_storage/blob_url_browsertest.cc b/content/browser/blob_storage/blob_url_browsertest.cc
index 8102a9d..66c45bb 100644
--- a/content/browser/blob_storage/blob_url_browsertest.cc
+++ b/content/browser/blob_storage/blob_url_browsertest.cc
@@ -3,8 +3,6 @@
 // found in the LICENSE file.
 
 #include "base/strings/pattern.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/common/content_switches.h"
@@ -175,91 +173,4 @@
   EXPECT_FALSE(base::MatchPattern(window_location, "*spoof*"));
 }
 
-enum class PartitionedBlobUrlBrowserTestTestCase {
-  kSupportPartitionedBlobUrlDisabled,
-  kSupportPartitionedBlobUrlEnabled,
-};
-
-class PartitionedBlobUrlBrowserTestP
-    : public BlobUrlBrowserTest,
-      public testing::WithParamInterface<
-          PartitionedBlobUrlBrowserTestTestCase> {
- public:
-  PartitionedBlobUrlBrowserTestP() {
-    scoped_feature_list_.InitWithFeatureState(
-        net::features::kSupportPartitionedBlobUrl,
-        GetParam() == PartitionedBlobUrlBrowserTestTestCase::
-                          kSupportPartitionedBlobUrlEnabled);
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-IN_PROC_BROWSER_TEST_P(PartitionedBlobUrlBrowserTestP,
-                       BlobUrlStoreRegisterMetrics) {
-  GURL main_url(embedded_test_server()->GetURL("chromium.org", "/title1.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  base::HistogramTester histogram_tester;
-
-  EXPECT_TRUE(ExecJs(shell(), "URL.createObjectURL(new Blob(['foo']))"));
-
-  FetchHistogramsFromChildProcesses();
-
-  if (base::FeatureList::IsEnabled(net::features::kSupportPartitionedBlobUrl)) {
-    histogram_tester.ExpectTotalCount(
-        "Storage.Blob.RegisterURLTimeWithPartitioningSupport.Frame", 1);
-  } else {
-    histogram_tester.ExpectTotalCount(
-        "Storage.Blob.RegisterURLTimeWithoutPartitioningSupport", 1);
-  }
-}
-
-IN_PROC_BROWSER_TEST_P(PartitionedBlobUrlBrowserTestP,
-                       BlobUrlStoreRegisterMetricsWorker) {
-  GURL main_url(embedded_test_server()->GetURL("chromium.org", "/title1.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  base::HistogramTester histogram_tester;
-
-  EXPECT_TRUE(ExecJs(shell(), R"(
-  function workerCode() {
-    URL.createObjectURL(new Blob(['foo']));
-    postMessage(true);
-  }
-  var workerBlob = new Blob(
-    [workerCode.toString() + ';workerCode();'],
-    {type: 'application/javascript'});
-  new Promise((resolve) => {
-    var w = new Worker(URL.createObjectURL(workerBlob));
-    w.onmessage = (e) => {
-      w.terminate();
-      resolve();
-    };
-  });)"));
-
-  FetchHistogramsFromChildProcesses();
-
-  // We expect two PublicURLManager::RegisterURL calls, one from the frame when
-  // it creates the worker and another when the worker creates a blob URL.
-  if (base::FeatureList::IsEnabled(net::features::kSupportPartitionedBlobUrl)) {
-    histogram_tester.ExpectTotalCount(
-        "Storage.Blob.RegisterURLTimeWithPartitioningSupport.Frame", 1);
-    histogram_tester.ExpectTotalCount(
-        "Storage.Blob.RegisterURLTimeWithPartitioningSupport.Worker", 1);
-  } else {
-    histogram_tester.ExpectTotalCount(
-        "Storage.Blob.RegisterURLTimeWithoutPartitioningSupport", 2);
-  }
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    PartitionedBlobUrlBrowserTest,
-    PartitionedBlobUrlBrowserTestP,
-    ::testing::Values(PartitionedBlobUrlBrowserTestTestCase::
-                          kSupportPartitionedBlobUrlDisabled,
-                      PartitionedBlobUrlBrowserTestTestCase::
-                          kSupportPartitionedBlobUrlEnabled));
-
 }  // namespace content
diff --git a/content/browser/device_posture/device_posture_platform_provider_win.cc b/content/browser/device_posture/device_posture_platform_provider_win.cc
index dca66d8..718aa6b7 100644
--- a/content/browser/device_posture/device_posture_platform_provider_win.cc
+++ b/content/browser/device_posture/device_posture_platform_provider_win.cc
@@ -4,190 +4,36 @@
 
 #include "content/browser/device_posture/device_posture_platform_provider_win.h"
 
-#include <optional>
-
-#include "base/containers/contains.h"
-#include "base/containers/fixed_flat_map.h"
-#include "base/json/json_reader.h"
-#include "base/strings/string_split.h"
-#include "base/strings/utf_string_conversions.h"
-
-using blink::mojom::DevicePostureType;
-
-namespace {
-// The full specification of the registry is located over here
-// https://github.com/foldable-devices/foldable-windows-registry-specification
-// This approach is a stop gap solution until Windows gains proper APIs.
-//
-// TODO(darktears): When Windows gains the APIs we should update this code.
-// https://crbug.com/1465934
-//
-// FOLED stands for Foldable OLED.
-constexpr wchar_t kFoledRegKeyPath[] = L"Software\\Intel\\Foled";
-
-// On Windows the platform returns [left][fold][right] and so far we support
-// only one display feature in Chromium.
-constexpr int kFirstFoldInSegmentsArray = 1;
-
-}  // namespace
+#include "content/browser/device_posture/device_posture_registry_watcher_win.h"
 
 namespace content {
 
-DevicePosturePlatformProviderWin::DevicePosturePlatformProviderWin() {
-  base::win::RegKey registry_key(HKEY_CURRENT_USER, kFoledRegKeyPath,
-                                 KEY_QUERY_VALUE);
-  if (registry_key.Valid()) {
-    ComputeFoldableState(registry_key, /*notify_changes=*/false);
-  }
-}
+DevicePosturePlatformProviderWin::DevicePosturePlatformProviderWin() = default;
 
 DevicePosturePlatformProviderWin::~DevicePosturePlatformProviderWin() = default;
 
 void DevicePosturePlatformProviderWin::StartListening() {
-  if (registry_key_) {
+  if (registry_watcher_observation_.IsObserving()) {
     return;
   }
-
-  registry_key_.emplace(HKEY_CURRENT_USER, kFoledRegKeyPath,
-                        KEY_NOTIFY | KEY_QUERY_VALUE);
-  if (registry_key_->Valid()) {
-    // Start watching the registry for changes.
-    registry_key_->StartWatching(
-        base::BindOnce(&DevicePosturePlatformProviderWin::OnRegistryKeyChanged,
-                       base::Unretained(this)));
-  }
+  registry_watcher_observation_.Observe(
+      DevicePostureRegistryWatcherWin::GetInstance());
 }
 
 void DevicePosturePlatformProviderWin::StopListening() {
-  registry_key_ = std::nullopt;
+  registry_watcher_observation_.Reset();
 }
 
-std::optional<DevicePostureType> DevicePosturePlatformProviderWin::ParsePosture(
-    std::string_view posture_state) {
-  static constexpr auto kPostureStateToPostureType =
-      base::MakeFixedFlatMap<std::string_view, DevicePostureType>(
-          {{"MODE_HANDHELD", DevicePostureType::kFolded},
-           {"MODE_DUAL_ANGLE", DevicePostureType::kFolded},
-           {"MODE_LAPTOP_KB", DevicePostureType::kContinuous},
-           {"MODE_LAYFLAT_LANDSCAPE",
-            DevicePostureType::kContinuous},
-           {"MODE_LAYFLAT_PORTRAIT",
-            DevicePostureType::kContinuous},
-           {"MODE_TABLETOP", DevicePostureType::kContinuous}});
-  if (auto* iter = kPostureStateToPostureType.find(posture_state);
-      iter != kPostureStateToPostureType.end()) {
-    return iter->second;
-  }
-  DVLOG(1) << "Could not parse the posture data: " << posture_state;
-  return std::nullopt;
+void DevicePosturePlatformProviderWin::UpdateDevicePosture(
+    const blink::mojom::DevicePostureType& posture) {
+  current_posture_ = posture;
+  NotifyDevicePostureChanged(current_posture_);
 }
 
-void DevicePosturePlatformProviderWin::ComputeFoldableState(
-    const base::win::RegKey& registry_key,
-    bool notify_changes) {
-  CHECK(registry_key.Valid());
-
-  std::wstring postureData;
-  if (registry_key.ReadValue(L"PostureData", &postureData) != ERROR_SUCCESS) {
-    return;
-  }
-
-  std::optional<base::Value::Dict> dict =
-      base::JSONReader::ReadDict(base::WideToUTF8(postureData));
-  if (!dict) {
-    DVLOG(1) << "Could not read the foldable status.";
-    return;
-  }
-  const std::string* posture_state = dict->FindString("PostureState");
-  if (!posture_state) {
-    return;
-  }
-
-  const DevicePostureType old_posture = current_posture_;
-  std::optional<DevicePostureType> posture = ParsePosture(*posture_state);
-
-  if (posture) {
-    current_posture_ = posture.value();
-    if (old_posture != current_posture_ && notify_changes) {
-      NotifyDevicePostureChanged(current_posture_);
-    }
-  }
-
-  base::Value::List* viewport_segments = dict->FindList("Rectangles");
-  if (!viewport_segments) {
-    DVLOG(1) << "Could not parse the viewport segments data.";
-    return;
-  }
-
-  std::optional<std::vector<gfx::Rect>> segments =
-      ParseViewportSegments(*viewport_segments);
-  if (!segments) {
-    return;
-  }
-
-  // If there is not enough segments then the display feature is empty.
-  if (segments->size() < 2) {
-    current_display_feature_bounds_ = gfx::Rect();
-  } else {
-    // We want the first fold segment of the segment array.
-    current_display_feature_bounds_ = segments->at(kFirstFoldInSegmentsArray);
-  }
-
-  if (notify_changes) {
-    NotifyDisplayFeatureBoundsChanged(current_display_feature_bounds_);
-  }
-}
-
-std::optional<std::vector<gfx::Rect>>
-DevicePosturePlatformProviderWin::ParseViewportSegments(
-    const base::Value::List& viewport_segments) {
-  if (viewport_segments.empty()) {
-    return std::nullopt;
-  }
-
-  // Check if the list is correctly constructed. It should be a multiple of
-  // |left side|fold|right side| or 1.
-  if (viewport_segments.size() != 1 && viewport_segments.size() % 3 != 0) {
-    DVLOG(1) << "Could not parse the viewport segments data.";
-    return std::nullopt;
-  }
-
-  std::vector<gfx::Rect> segments;
-  for (const auto& segment : viewport_segments) {
-    const std::string* segment_string = segment.GetIfString();
-    if (!segment_string) {
-      DVLOG(1) << "Could not parse the viewport segments data";
-      return std::nullopt;
-    }
-    auto rectangle_dimensions = base::SplitStringPiece(
-        *segment_string, ",", base::WhitespaceHandling::TRIM_WHITESPACE,
-        base::SplitResult::SPLIT_WANT_NONEMPTY);
-    if (rectangle_dimensions.size() != 4) {
-      DVLOG(1) << "Could not parse the viewport segments data: "
-               << *segment_string;
-      return std::nullopt;
-    }
-    int x, y, width, height;
-    if (!base::StringToInt(rectangle_dimensions[0], &x) ||
-        !base::StringToInt(rectangle_dimensions[1], &y) ||
-        !base::StringToInt(rectangle_dimensions[2], &width) ||
-        !base::StringToInt(rectangle_dimensions[3], &height)) {
-      DVLOG(1) << "Could not parse the viewport segments data: "
-               << *segment_string;
-      return std::nullopt;
-    }
-    segments.emplace_back(x, y, width, height);
-  }
-  return segments;
-}
-
-void DevicePosturePlatformProviderWin::OnRegistryKeyChanged() {
-  // |OnRegistryKeyChanged| is removed as an observer when the ChangeCallback is
-  // called, so we need to re-register.
-  registry_key_->StartWatching(
-      base::BindOnce(&DevicePosturePlatformProviderWin::OnRegistryKeyChanged,
-                     base::Unretained(this)));
-  ComputeFoldableState(registry_key_.value(), /*notify_changes=*/true);
+void DevicePosturePlatformProviderWin::UpdateDisplayFeatureBounds(
+    const gfx::Rect& display_feature_bounds) {
+  current_display_feature_bounds_ = display_feature_bounds;
+  NotifyDisplayFeatureBoundsChanged(current_display_feature_bounds_);
 }
 
 }  // namespace content
diff --git a/content/browser/device_posture/device_posture_platform_provider_win.h b/content/browser/device_posture/device_posture_platform_provider_win.h
index 2aa60d1d..d48b896 100644
--- a/content/browser/device_posture/device_posture_platform_provider_win.h
+++ b/content/browser/device_posture/device_posture_platform_provider_win.h
@@ -5,19 +5,16 @@
 #ifndef CONTENT_BROWSER_DEVICE_POSTURE_DEVICE_POSTURE_PLATFORM_PROVIDER_WIN_H_
 #define CONTENT_BROWSER_DEVICE_POSTURE_DEVICE_POSTURE_PLATFORM_PROVIDER_WIN_H_
 
-#include <optional>
-#include <string_view>
-#include <vector>
-
-#include "base/strings/string_piece.h"
-#include "base/values.h"
-#include "base/win/registry.h"
+#include "base/observer_list_types.h"
+#include "base/scoped_observation.h"
 #include "content/browser/device_posture/device_posture_platform_provider.h"
-#include "content/common/content_export.h"
 
 namespace content {
 
-class DevicePosturePlatformProviderWin : public DevicePosturePlatformProvider {
+class DevicePostureRegistryWatcherWin;
+
+class DevicePosturePlatformProviderWin : public DevicePosturePlatformProvider,
+                                         public base::CheckedObserver {
  public:
   DevicePosturePlatformProviderWin();
   ~DevicePosturePlatformProviderWin() override;
@@ -27,22 +24,16 @@
   DevicePosturePlatformProviderWin& operator=(
       const DevicePosturePlatformProviderWin&) = delete;
 
- private:
-  friend class DevicePosturePlatformProviderWinTest;
+  void UpdateDevicePosture(const blink::mojom::DevicePostureType& posture);
+  void UpdateDisplayFeatureBounds(const gfx::Rect& display_feature_bounds);
 
+ private:
   void StartListening() override;
   void StopListening() override;
-  void OnRegistryKeyChanged();
-  void ComputeFoldableState(const base::win::RegKey& registry_key,
-                            bool notify_changes);
-  CONTENT_EXPORT static std::optional<std::vector<gfx::Rect>>
-  ParseViewportSegments(const base::Value::List& viewport_segments);
-  CONTENT_EXPORT static std::optional<blink::mojom::DevicePostureType>
-  ParsePosture(std::string_view posture_state);
 
-  // This member is used to watch the registry after StartListening is called.
-  // It will be destroyed when calling StopListening.
-  std::optional<base::win::RegKey> registry_key_;
+  base::ScopedObservation<DevicePostureRegistryWatcherWin,
+                          DevicePosturePlatformProviderWin>
+      registry_watcher_observation_{this};
 };
 
 }  // namespace content
diff --git a/content/browser/device_posture/device_posture_registry_watcher_win.cc b/content/browser/device_posture/device_posture_registry_watcher_win.cc
new file mode 100644
index 0000000..c0ed83d9
--- /dev/null
+++ b/content/browser/device_posture/device_posture_registry_watcher_win.cc
@@ -0,0 +1,213 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "content/browser/device_posture/device_posture_registry_watcher_win.h"
+
+#include <optional>
+
+#include "base/containers/contains.h"
+#include "base/containers/fixed_flat_map.h"
+#include "base/json/json_reader.h"
+#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
+
+using blink::mojom::DevicePostureType;
+
+namespace {
+// The full specification of the registry is located over here
+// https://github.com/foldable-devices/foldable-windows-registry-specification
+// This approach is a stop gap solution until Windows gains proper APIs.
+//
+// TODO(1465934): When Windows gains the APIs we should update this code.
+//
+// FOLED stands for Foldable OLED.
+constexpr wchar_t kFoledRegKeyPath[] = L"Software\\Intel\\Foled";
+
+// On Windows the platform returns [left][fold][right] and so far we support
+// only one display feature in Chromium.
+constexpr int kFirstFoldInSegmentsArray = 1;
+
+}  // namespace
+
+namespace content {
+// static
+DevicePostureRegistryWatcherWin*
+DevicePostureRegistryWatcherWin::GetInstance() {
+  static base::NoDestructor<DevicePostureRegistryWatcherWin> instance;
+  return instance.get();
+}
+
+DevicePostureRegistryWatcherWin::DevicePostureRegistryWatcherWin() {
+  base::win::RegKey registry_key(HKEY_CURRENT_USER, kFoledRegKeyPath,
+                                 KEY_QUERY_VALUE);
+  if (registry_key.Valid()) {
+    ComputeFoldableState(registry_key, /*notify_changes=*/false);
+  }
+}
+
+DevicePostureRegistryWatcherWin::~DevicePostureRegistryWatcherWin() = default;
+
+void DevicePostureRegistryWatcherWin::AddObserver(
+    DevicePosturePlatformProviderWin* observer) {
+  if (!observer) {
+    return;
+  }
+
+  DCHECK(!observers_.HasObserver(observer));
+  if (observers_.empty()) {
+    DCHECK(!registry_key_);
+    registry_key_.emplace(HKEY_CURRENT_USER, kFoledRegKeyPath,
+                          KEY_NOTIFY | KEY_QUERY_VALUE);
+    if (registry_key_->Valid()) {
+      // Start watching the registry for changes.
+      registry_key_->StartWatching(
+          base::BindOnce(&DevicePostureRegistryWatcherWin::OnRegistryKeyChanged,
+                         base::Unretained(this)));
+    }
+  }
+
+  observers_.AddObserver(observer);
+  // Inform the observer with the current state.
+  observer->UpdateDevicePosture(current_posture_);
+  observer->UpdateDisplayFeatureBounds(current_display_feature_bounds_);
+}
+
+void DevicePostureRegistryWatcherWin::RemoveObserver(
+    DevicePosturePlatformProviderWin* observer) {
+  observers_.RemoveObserver(observer);
+  if (observers_.empty()) {
+    registry_key_ = std::nullopt;
+  }
+}
+
+std::optional<DevicePostureType> DevicePostureRegistryWatcherWin::ParsePosture(
+    std::string_view posture_state) {
+  static constexpr auto kPostureStateToPostureType =
+      base::MakeFixedFlatMap<std::string_view, DevicePostureType>(
+          {{"MODE_HANDHELD", DevicePostureType::kFolded},
+           {"MODE_DUAL_ANGLE", DevicePostureType::kFolded},
+           {"MODE_LAPTOP_KB", DevicePostureType::kContinuous},
+           {"MODE_LAYFLAT_LANDSCAPE", DevicePostureType::kContinuous},
+           {"MODE_LAYFLAT_PORTRAIT", DevicePostureType::kContinuous},
+           {"MODE_TABLETOP", DevicePostureType::kContinuous}});
+  if (auto* iter = kPostureStateToPostureType.find(posture_state);
+      iter != kPostureStateToPostureType.end()) {
+    return iter->second;
+  }
+  DVLOG(1) << "Could not parse the posture data: " << posture_state;
+  return std::nullopt;
+}
+
+void DevicePostureRegistryWatcherWin::ComputeFoldableState(
+    const base::win::RegKey& registry_key,
+    bool notify_changes) {
+  CHECK(registry_key.Valid());
+
+  std::wstring posture_data;
+  if (registry_key.ReadValue(L"PostureData", &posture_data) != ERROR_SUCCESS) {
+    return;
+  }
+
+  std::optional<base::Value::Dict> dict =
+      base::JSONReader::ReadDict(base::WideToUTF8(posture_data));
+  if (!dict) {
+    DVLOG(1) << "Could not read the foldable status.";
+    return;
+  }
+  const std::string* posture_state = dict->FindString("PostureState");
+  if (!posture_state) {
+    return;
+  }
+
+  const DevicePostureType old_posture = current_posture_;
+  std::optional<DevicePostureType> posture = ParsePosture(*posture_state);
+
+  if (posture) {
+    current_posture_ = posture.value();
+    if (old_posture != current_posture_ && notify_changes) {
+      for (DevicePosturePlatformProviderWin& observer : observers_) {
+        observer.UpdateDevicePosture(current_posture_);
+      }
+    }
+  }
+
+  base::Value::List* viewport_segments = dict->FindList("Rectangles");
+  if (!viewport_segments) {
+    DVLOG(1) << "Could not parse the viewport segments data.";
+    return;
+  }
+
+  std::optional<std::vector<gfx::Rect>> segments =
+      ParseViewportSegments(*viewport_segments);
+  if (!segments) {
+    return;
+  }
+
+  // If there is not enough segments then the display feature is empty.
+  if (segments->size() < 2) {
+    current_display_feature_bounds_ = gfx::Rect();
+  } else {
+    // We want the first fold segment of the segment array.
+    current_display_feature_bounds_ = segments->at(kFirstFoldInSegmentsArray);
+  }
+
+  if (notify_changes) {
+    for (DevicePosturePlatformProviderWin& observer : observers_) {
+      observer.UpdateDisplayFeatureBounds(current_display_feature_bounds_);
+    }
+  }
+}
+
+std::optional<std::vector<gfx::Rect>>
+DevicePostureRegistryWatcherWin::ParseViewportSegments(
+    const base::Value::List& viewport_segments) {
+  if (viewport_segments.empty()) {
+    return std::nullopt;
+  }
+
+  // Check if the list is correctly constructed. It should be a multiple of
+  // |left side|fold|right side| or 1.
+  if (viewport_segments.size() != 1 && viewport_segments.size() % 3 != 0) {
+    DVLOG(1) << "Could not parse the viewport segments data.";
+    return std::nullopt;
+  }
+
+  std::vector<gfx::Rect> segments;
+  for (const auto& segment : viewport_segments) {
+    const std::string* segment_string = segment.GetIfString();
+    if (!segment_string) {
+      DVLOG(1) << "Could not parse the viewport segments data";
+      return std::nullopt;
+    }
+    auto rectangle_dimensions = base::SplitStringPiece(
+        *segment_string, ",", base::WhitespaceHandling::TRIM_WHITESPACE,
+        base::SplitResult::SPLIT_WANT_NONEMPTY);
+    if (rectangle_dimensions.size() != 4) {
+      DVLOG(1) << "Could not parse the viewport segments data: "
+               << *segment_string;
+      return std::nullopt;
+    }
+    int x, y, width, height;
+    if (!base::StringToInt(rectangle_dimensions[0], &x) ||
+        !base::StringToInt(rectangle_dimensions[1], &y) ||
+        !base::StringToInt(rectangle_dimensions[2], &width) ||
+        !base::StringToInt(rectangle_dimensions[3], &height)) {
+      DVLOG(1) << "Could not parse the viewport segments data: "
+               << *segment_string;
+      return std::nullopt;
+    }
+    segments.emplace_back(x, y, width, height);
+  }
+  return segments;
+}
+
+void DevicePostureRegistryWatcherWin::OnRegistryKeyChanged() {
+  // |OnRegistryKeyChanged| is removed as an observer when the ChangeCallback is
+  // called, so we need to re-register.
+  registry_key_->StartWatching(
+      base::BindOnce(&DevicePostureRegistryWatcherWin::OnRegistryKeyChanged,
+                     base::Unretained(this)));
+  ComputeFoldableState(registry_key_.value(), /*notify_changes=*/true);
+}
+
+}  // namespace content
diff --git a/content/browser/device_posture/device_posture_registry_watcher_win.h b/content/browser/device_posture/device_posture_registry_watcher_win.h
new file mode 100644
index 0000000..b2ffecb
--- /dev/null
+++ b/content/browser/device_posture/device_posture_registry_watcher_win.h
@@ -0,0 +1,64 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVICE_POSTURE_DEVICE_POSTURE_REGISTRY_WATCHER_WIN_H_
+#define CONTENT_BROWSER_DEVICE_POSTURE_DEVICE_POSTURE_REGISTRY_WATCHER_WIN_H_
+
+#include <optional>
+#include <string_view>
+#include <vector>
+
+#include "base/no_destructor.h"
+#include "base/observer_list.h"
+#include "base/strings/string_piece.h"
+#include "base/values.h"
+#include "base/win/registry.h"
+#include "content/browser/device_posture/device_posture_platform_provider_win.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// This is a singleton class that will fetch and monitor the registry to get
+// posture and display feature information.
+class DevicePostureRegistryWatcherWin {
+ public:
+  static DevicePostureRegistryWatcherWin* GetInstance();
+
+  void AddObserver(DevicePosturePlatformProviderWin* observer);
+  void RemoveObserver(DevicePosturePlatformProviderWin* observer);
+
+  DevicePostureRegistryWatcherWin(const DevicePostureRegistryWatcherWin&) =
+      delete;
+  DevicePostureRegistryWatcherWin& operator=(
+      const DevicePostureRegistryWatcherWin&) = delete;
+
+ private:
+  friend class DevicePostureRegistryWatcherWinTest;
+  friend class base::NoDestructor<DevicePostureRegistryWatcherWin>;
+
+  DevicePostureRegistryWatcherWin();
+  ~DevicePostureRegistryWatcherWin();
+
+  void OnRegistryKeyChanged();
+  void ComputeFoldableState(const base::win::RegKey& registry_key,
+                            bool notify_changes);
+  CONTENT_EXPORT static std::optional<std::vector<gfx::Rect>>
+  ParseViewportSegments(const base::Value::List& viewport_segments);
+  CONTENT_EXPORT static std::optional<blink::mojom::DevicePostureType>
+  ParsePosture(std::string_view posture_state);
+
+  base::ObserverList<DevicePosturePlatformProviderWin> observers_;
+
+  blink::mojom::DevicePostureType current_posture_ =
+      blink::mojom::DevicePostureType::kContinuous;
+  gfx::Rect current_display_feature_bounds_;
+
+  // This member is used to watch the registry after StartListening is called.
+  // It will be destroyed when calling StopListening.
+  std::optional<base::win::RegKey> registry_key_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DEVICE_POSTURE_DEVICE_POSTURE_REGISTRY_WATCHER_WIN_H_
diff --git a/content/browser/device_posture/device_posture_platform_provider_win_unittest.cc b/content/browser/device_posture/device_posture_registry_watcher_win_unittest.cc
similarity index 88%
rename from content/browser/device_posture/device_posture_platform_provider_win_unittest.cc
rename to content/browser/device_posture/device_posture_registry_watcher_win_unittest.cc
index 1a74a684..774bf38 100644
--- a/content/browser/device_posture/device_posture_platform_provider_win_unittest.cc
+++ b/content/browser/device_posture/device_posture_registry_watcher_win_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/device_posture/device_posture_platform_provider_win.h"
+#include "content/browser/device_posture/device_posture_registry_watcher_win.h"
 
 #include <string_view>
 
@@ -12,31 +12,31 @@
 
 namespace content {
 
-class DevicePosturePlatformProviderWinTest : public testing::Test {
+class DevicePostureRegistryWatcherWinTest : public testing::Test {
  protected:
-  DevicePosturePlatformProviderWinTest() = default;
+  DevicePostureRegistryWatcherWinTest() = default;
 
-  ~DevicePosturePlatformProviderWinTest() override = default;
+  ~DevicePostureRegistryWatcherWinTest() override = default;
 
   static std::optional<std::vector<gfx::Rect>> ParseViewportSegments(
       const base::Value::List& viewport_segments) {
-    return DevicePosturePlatformProviderWin::ParseViewportSegments(
+    return DevicePostureRegistryWatcherWin::ParseViewportSegments(
         viewport_segments);
   }
 
   static std::optional<blink::mojom::DevicePostureType> ParsePosture(
       std::string_view posture_state) {
-    return DevicePosturePlatformProviderWin::ParsePosture(posture_state);
+    return DevicePostureRegistryWatcherWin::ParsePosture(posture_state);
   }
 };
 
-TEST_F(DevicePosturePlatformProviderWinTest, InvalidPostureData) {
+TEST_F(DevicePostureRegistryWatcherWinTest, InvalidPostureData) {
   EXPECT_FALSE(ParsePosture(""));
   EXPECT_FALSE(ParsePosture("test"));
   EXPECT_FALSE(ParsePosture(" LAPTOP"));
 }
 
-TEST_F(DevicePosturePlatformProviderWinTest, ValidPostureData) {
+TEST_F(DevicePostureRegistryWatcherWinTest, ValidPostureData) {
   EXPECT_EQ(ParsePosture("MODE_HANDHELD"),
             blink::mojom::DevicePostureType::kFolded);
   EXPECT_EQ(ParsePosture("MODE_DUAL_ANGLE"),
@@ -51,7 +51,7 @@
             blink::mojom::DevicePostureType::kContinuous);
 }
 
-TEST_F(DevicePosturePlatformProviderWinTest, InvalidViewportSegmentsData) {
+TEST_F(DevicePostureRegistryWatcherWinTest, InvalidViewportSegmentsData) {
   base::Value::List list;
   std::optional<std::vector<gfx::Rect>> result_viewport_segments =
       ParseViewportSegments(list);
@@ -149,7 +149,7 @@
   EXPECT_FALSE(ParseViewportSegments(list));
 }
 
-TEST_F(DevicePosturePlatformProviderWinTest, ValidViewportSegmentsData) {
+TEST_F(DevicePostureRegistryWatcherWinTest, ValidViewportSegmentsData) {
   std::optional<std::vector<gfx::Rect>> result_viewport_segments;
   base::Value::List list = base::test::ParseJsonList(R"([
     "132, 123, 123, 123"
diff --git a/content/browser/indexed_db/indexed_db_bucket_context.cc b/content/browser/indexed_db/indexed_db_bucket_context.cc
index 3f9a7b4..7da02df 100644
--- a/content/browser/indexed_db/indexed_db_bucket_context.cc
+++ b/content/browser/indexed_db/indexed_db_bucket_context.cc
@@ -595,7 +595,7 @@
 }
 
 int64_t IndexedDBBucketContext::GetInMemorySize() {
-  return backing_store_->GetInMemorySize();
+  return backing_store_ ? backing_store_->GetInMemorySize() : 0;
 }
 
 void IndexedDBBucketContext::ReportOutstandingBlobs(bool blobs_outstanding) {
@@ -979,6 +979,10 @@
   // TODO(jsbell): Sort by name?
   std::vector<storage::mojom::IdbDatabaseMetadataPtr> database_list;
 
+  if (backing_store_ && backing_store_->in_memory()) {
+    info->size = GetInMemorySize();
+  }
+
   for (const auto& [name, db] : databases_) {
     storage::mojom::IdbDatabaseMetadataPtr db_info =
         storage::mojom::IdbDatabaseMetadata::New();
diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc
index a64e482..3b013f5 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -70,6 +70,25 @@
 #include "third_party/zlib/google/zip.h"
 #include "url/origin.h"
 
+// Invokes a given method on an IndexedDBBucketContext, synchronously or
+// asynchronously depending on the state of the kIndexedDBShardBackingStores
+// flag. This is a transitional helper and should be replaced by SequenceBound
+// when the feature is enabled by default.
+#define CALL_BUCKET_METHOD(bucket_id, method, ...)                           \
+  {                                                                          \
+    auto iter = bucket_contexts_.find(bucket_id);                            \
+    if (iter != bucket_contexts_.end()) {                                    \
+      auto bucket_closure =                                                  \
+          base::BindOnce(&IndexedDBBucketContext::method,                    \
+                         base::Unretained(iter->second.get()), __VA_ARGS__); \
+      if (ShardingEnabled()) {                                               \
+        IDBTaskRunner()->PostTask(FROM_HERE, std::move(bucket_closure));     \
+      } else {                                                               \
+        std::move(bucket_closure).Run();                                     \
+      }                                                                      \
+    }                                                                        \
+  }
+
 namespace content {
 
 using blink::StorageKey;
@@ -77,6 +96,10 @@
 
 namespace {
 
+bool ShardingEnabled() {
+  return base::FeatureList::IsEnabled(features::kIndexedDBShardBackingStores);
+}
+
 bool IsAllowedPath(const std::vector<base::FilePath>& allowed_paths,
                    const base::FilePath& candidate_path) {
   for (const base::FilePath& allowed_path : allowed_paths) {
@@ -253,9 +276,17 @@
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
   DCHECK_EQ(bucket_locator.type, blink::mojom::StorageType::kTemporary);
   DCHECK(!callback.is_null());
-  ForceClose(bucket_locator.id,
-             storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN,
-             base::DoNothing());
+  ForceClose(
+      bucket_locator.id,
+      storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN,
+      base::BindOnce(&IndexedDBContextImpl::DidForceCloseForDeleteBucketData,
+                     weak_factory_.GetWeakPtr(), bucket_locator,
+                     std::move(callback)));
+}
+
+void IndexedDBContextImpl::DidForceCloseForDeleteBucketData(
+    const storage::BucketLocator& bucket_locator,
+    DeleteBucketDataCallback callback) {
   if (in_memory()) {
     bucket_set_.erase(bucket_locator);
     bucket_size_map_.erase(bucket_locator);
@@ -283,13 +314,21 @@
                                       storage::mojom::ForceCloseReason reason,
                                       base::OnceClosure closure) {
   auto it = bucket_contexts_.find(bucket_id);
-  if (it != bucket_contexts_.end()) {
-    it->second->ForceClose(
-        /*doom=*/reason ==
-        storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN);
+  if (it == bucket_contexts_.end()) {
+    std::move(closure).Run();
+    return;
   }
-
-  std::move(closure).Run();
+  auto bucket_closure = base::BindOnce(
+      &IndexedDBBucketContext::ForceClose, base::Unretained(it->second.get()),
+      /*doom=*/reason ==
+          storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN);
+  if (ShardingEnabled()) {
+    IDBTaskRunner()->PostTaskAndReply(FROM_HERE, std::move(bucket_closure),
+                                      std::move(closure));
+  } else {
+    std::move(bucket_closure).Run();
+    std::move(closure).Run();
+  }
 }
 
 void IndexedDBContextImpl::DownloadBucketData(
@@ -375,7 +414,11 @@
         storage::mojom::IdbBucketMetadata::New();
     info->bucket_locator = bucket_locator;
     info->name = bucket_info.name;
-    info->size = static_cast<double>(GetBucketDiskUsage(bucket_locator));
+    if (!in_memory()) {
+      // Size for in-memory DBs will be filled in
+      // `IndexedDBBucketContext::FillInMetadata()`.
+      info->size = static_cast<double>(GetBucketDiskUsage(bucket_locator));
+    }
     info->last_modified = GetBucketLastModified(bucket_locator);
 
     if (!in_memory()) {
@@ -494,9 +537,9 @@
     const std::string& key,
     const std::string& value,
     base::OnceClosure callback) {
-  bucket_contexts_.find(bucket_locator.id)
-      ->second->WriteToIndexedDBForTesting(key, value,  // IN-TEST
-                                           std::move(callback));
+  DCHECK(base::Contains(bucket_contexts_, bucket_locator.id));
+  CALL_BUCKET_METHOD(bucket_locator.id, WriteToIndexedDBForTesting, key, value,
+                     std::move(callback));
 }
 
 void IndexedDBContextImpl::GetPathForBlobForTesting(
@@ -511,13 +554,22 @@
 void IndexedDBContextImpl::CompactBackingStoreForTesting(
     const BucketLocator& bucket_locator,
     base::OnceClosure callback) {
-  bucket_contexts_.find(bucket_locator.id)
-      ->second->CompactBackingStoreForTesting();  // IN-TEST
-  std::move(callback).Run();
+  auto it = bucket_contexts_.find(bucket_locator.id);
+  IDBTaskRunner()->PostTaskAndReply(
+      FROM_HERE,
+      base::BindOnce(&IndexedDBBucketContext::CompactBackingStoreForTesting,
+                     base::Unretained(it->second.get())),
+      std::move(callback));
 }
 
 void IndexedDBContextImpl::GetUsageForTesting(
     GetUsageForTestingCallback callback) {
+  if (in_memory()) {
+    DCHECK_EQ(1U, bucket_contexts_.size());
+    GetInMemorySize(bucket_contexts_.begin()->first, std::move(callback));
+    return;
+  }
+
   int64_t total_size = 0;
   for (const BucketLocator& bucket : bucket_set_) {
     total_size += GetBucketDiskUsage(bucket);
@@ -549,6 +601,7 @@
 int64_t IndexedDBContextImpl::GetBucketDiskUsage(
     const BucketLocator& bucket_locator) {
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
+  DCHECK(!in_memory());
   if (!LookUpBucket(bucket_locator.id))
     return 0;
 
@@ -650,9 +703,13 @@
   // other callbacks) so that `ForceClose()` below doesn't mutate
   // `bucket_contexts_` while it's being iterated.
   weak_factory_.InvalidateWeakPtrs();
-  for (const auto& [locator, context] : bucket_contexts_) {
-    context->ForceClose(/*doom=*/false);
+  for (auto& [bucket_id, context] : bucket_contexts_) {
+    CALL_BUCKET_METHOD(bucket_id, ForceClose, /*doom=*/false);
+    if (ShardingEnabled()) {
+      IDBTaskRunner()->DeleteSoon(FROM_HERE, std::move(context));
+    }
   }
+
   bucket_contexts_.clear();
 }
 
@@ -684,12 +741,13 @@
     }
 
     if (delete_bucket) {
-      auto it = bucket_contexts_.find(bucket_locator.id);
-      if (it != bucket_contexts_.end()) {
-        it->second->ForceClose(false);
-      }
-      base::ranges::for_each(GetStoragePaths(bucket_locator),
-                             &base::DeletePathRecursively);
+      ForceClose(bucket_locator.id, {},
+                 base::BindOnce(
+                     [](std::vector<base::FilePath> paths) {
+                       base::ranges::for_each(paths,
+                                              &base::DeletePathRecursively);
+                     },
+                     GetStoragePaths(bucket_locator)));
     }
   }
 }
@@ -732,9 +790,7 @@
 int64_t IndexedDBContextImpl::ReadUsageFromDisk(
     const BucketLocator& bucket_locator,
     bool write_in_progress) const {
-  if (in_memory()) {
-    return GetInMemorySize(bucket_locator);
-  }
+  DCHECK(!in_memory());
 
 #if BUILDFLAG(IS_WIN)
   // Touch all files in the LevelDB directory to update directory entry
@@ -918,13 +974,22 @@
   }
 }
 
-int64_t IndexedDBContextImpl::GetInMemorySize(
-    const BucketLocator& bucket_locator) const {
-  auto it = bucket_contexts_.find(bucket_locator.id);
+void IndexedDBContextImpl::GetInMemorySize(
+    storage::BucketId bucket_id,
+    base::OnceCallback<void(int64_t)> on_got_size) const {
+  auto it = bucket_contexts_.find(bucket_id);
   if (it == bucket_contexts_.end()) {
-    return 0;
+    std::move(on_got_size).Run(0);
+    return;
   }
-  return it->second->GetInMemorySize();
+  auto bucket_closure = base::BindOnce(&IndexedDBBucketContext::GetInMemorySize,
+                                       base::Unretained(it->second.get()));
+  if (ShardingEnabled()) {
+    IDBTaskRunner()->PostTaskAndReplyWithResult(
+        FROM_HERE, std::move(bucket_closure), std::move(on_got_size));
+  } else {
+    std::move(on_got_size).Run(std::move(bucket_closure).Run());
+  }
 }
 
 std::vector<storage::BucketId>
@@ -953,7 +1018,19 @@
   if (it == bucket_contexts_.end()) {
     std::move(result).Run(std::move(info));
   } else {
-    it->second->FillInMetadata(std::move(info), std::move(result));
+    CALL_BUCKET_METHOD(info->bucket_locator.id, FillInMetadata, std::move(info),
+                       std::move(result));
+  }
+}
+
+void IndexedDBContextImpl::DestroyBucketContext(storage::BucketId bucket_id) {
+  if (ShardingEnabled()) {
+    auto it = bucket_contexts_.find(bucket_id);
+    CHECK(it != bucket_contexts_.end());
+    IDBTaskRunner()->DeleteSoon(FROM_HERE, std::move(it->second));
+    bucket_contexts_.erase(it);
+  } else {
+    bucket_contexts_.erase(bucket_id);
   }
 }
 
@@ -968,14 +1045,9 @@
 
   const BucketLocator bucket_locator = bucket.ToBucketLocator();
   IndexedDBBucketContext::Delegate bucket_delegate;
-  bucket_delegate.on_ready_for_destruction = base::BindRepeating(
-      [](base::WeakPtr<IndexedDBContextImpl> context,
-         const BucketLocator& bucket_locator) {
-        if (context) {
-          context->bucket_contexts_.erase(bucket_locator.id);
-        }
-      },
-      weak_factory_.GetWeakPtr(), bucket_locator);
+  bucket_delegate.on_ready_for_destruction =
+      base::BindOnce(&IndexedDBContextImpl::DestroyBucketContext,
+                     weak_factory_.GetWeakPtr(), bucket_locator.id);
   bucket_delegate.on_content_changed = base::BindRepeating(
       base::BindRepeating(&IndexedDBContextImpl::NotifyIndexedDBContentChanged,
                           weak_factory_.GetWeakPtr(), bucket_locator));
@@ -985,7 +1057,7 @@
   bucket_delegate.for_each_bucket_context = base::BindRepeating(
       &IndexedDBContextImpl::ForEachBucketContext, weak_factory_.GetWeakPtr());
 
-  if (base::FeatureList::IsEnabled(features::kIndexedDBShardBackingStores)) {
+  if (ShardingEnabled()) {
     bucket_delegate.on_ready_for_destruction = base::BindPostTask(
         idb_task_runner_, std::move(bucket_delegate.on_ready_for_destruction));
     bucket_delegate.on_receiver_bounced = base::BindPostTask(
@@ -1023,8 +1095,8 @@
   it = bucket_contexts_.emplace(bucket_locator.id, std::move(bucket_context))
            .first;
   if (pending_failure_injector_) {
-    it->second->BindMockFailureSingletonForTesting(  // IN-TEST
-        std::move(pending_failure_injector_));
+    CALL_BUCKET_METHOD(bucket_locator.id, BindMockFailureSingletonForTesting,
+                       std::move(pending_failure_injector_));
   }
   bucket_set_.insert(bucket_locator);
   return *it->second;
@@ -1033,7 +1105,11 @@
 void IndexedDBContextImpl::GetBucketUsage(const BucketLocator& bucket,
                                           GetBucketUsageCallback callback) {
   DCHECK_EQ(bucket.type, blink::mojom::StorageType::kTemporary);
-  std::move(callback).Run(GetBucketDiskUsage(bucket));
+  if (in_memory()) {
+    GetInMemorySize(bucket.id, std::move(callback));
+  } else {
+    std::move(callback).Run(GetBucketDiskUsage(bucket));
+  }
 }
 
 void IndexedDBContextImpl::GetStorageKeysForType(
diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h
index dc276a3..6f5c1e3 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/content/browser/indexed_db/indexed_db_context_impl.h
@@ -219,6 +219,10 @@
   // third-party-context IDB files are stored.
   std::map<storage::BucketId, base::FilePath> FindIndexedDBFiles() const;
 
+  void DidForceCloseForDeleteBucketData(
+      const storage::BucketLocator& bucket_locator,
+      DeleteBucketDataCallback callback);
+
   void OnBucketInfoReady(
       GetAllBucketsDetailsCallback callback,
       std::vector<storage::QuotaErrorOr<storage::BucketInfo>> bucket_infos);
@@ -227,7 +231,8 @@
   void ForEachBucketContext(IndexedDBBucketContext::InstanceClosure callback);
 
   // Calculates in-memory/incognito usage for usage reporting.
-  int64_t GetInMemorySize(const storage::BucketLocator& bucket_locator) const;
+  void GetInMemorySize(storage::BucketId bucket_id,
+                       base::OnceCallback<void(int64_t)> on_got_size) const;
 
   std::vector<storage::BucketId> GetOpenBucketIdsForTesting() const;
 
@@ -262,6 +267,8 @@
       const std::u16string& database_name,
       const std::u16string& object_store_name);
 
+  void DestroyBucketContext(storage::BucketId id);
+
   std::optional<storage::BucketLocator> LookUpBucket(
       storage::BucketId bucket_id);
 
diff --git a/content/browser/media/system_media_controls_notifier.h b/content/browser/media/system_media_controls_notifier.h
index 2ad0481c..da467ac 100644
--- a/content/browser/media/system_media_controls_notifier.h
+++ b/content/browser/media/system_media_controls_notifier.h
@@ -58,6 +58,8 @@
   void MediaControllerImageChanged(
       ::media_session::mojom::MediaSessionImageType type,
       const SkBitmap& bitmap) override;
+  // There's no chapter images in the system media tray view, so we don't need
+  // to implement this method.
   void MediaControllerChapterImageChanged(int chapter_index,
                                           const SkBitmap& bitmap) override {}
 
diff --git a/content/browser/media/web_app_system_media_controls_browsertest.cc b/content/browser/media/web_app_system_media_controls_browsertest.cc
index 60d7226..6a3efebd 100644
--- a/content/browser/media/web_app_system_media_controls_browsertest.cc
+++ b/content/browser/media/web_app_system_media_controls_browsertest.cc
@@ -207,13 +207,8 @@
   base::test::ScopedFeatureList feature_list_;
 };
 
-#if BUILDFLAG(IS_WIN) && defined(ADDRESS_SANITIZER)
-#define MAYBE_SimpleOneBrowserTest DISABLED_SimpleOneBrowserTest
-#else
-#define MAYBE_SimpleOneBrowserTest SimpleOneBrowserTest
-#endif
 IN_PROC_BROWSER_TEST_F(WebAppSystemMediaControlsBrowserTest,
-                       MAYBE_SimpleOneBrowserTest) {
+                       SimpleOneBrowserTest) {
   GURL http_url(https_server()->GetURL("/media/session/media-session.html"));
   EXPECT_TRUE(NavigateToURL(shell(), http_url));
 
@@ -222,6 +217,9 @@
   // Check video is playing.
   EXPECT_TRUE(IsPlaying(shell(), "long-video-loop"));
 
+  bool is_for_pwa = WaitForStartWatchingMediaKey();
+  EXPECT_FALSE(is_for_pwa);
+
   // Hit pause via simulating SMTC pause.
   MediaKeysListenerManagerImpl* media_keys_listener_manager_impl =
       BrowserMainLoop::GetInstance()->media_keys_listener_manager();
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index fd4f8af0..96b47ec 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -5767,7 +5767,7 @@
           can_store_old_page_in_bfcache /* persisted */);
 }
 
-bool NavigationRequest::ShouldDispatchPageConcealEvent() const {
+bool NavigationRequest::ShouldDispatchPageSwapEvent() const {
   if (early_render_frame_host_swap_type_ !=
       EarlyRenderFrameHostSwapType::kNone) {
     return false;
@@ -5777,11 +5777,11 @@
     return false;
   }
 
-  if (!base::FeatureList::IsEnabled(blink::features::kPageConcealEvent)) {
+  if (!base::FeatureList::IsEnabled(blink::features::kPageSwapEvent)) {
     return false;
   }
 
-  return !did_fire_page_conceal_;
+  return !did_fire_page_swap_;
 }
 
 void NavigationRequest::CommitNavigation() {
@@ -5809,10 +5809,10 @@
   DCHECK(!blink::IsRendererDebugURL(common_params_->url));
 
   AddOldPageInfoToCommitParamsIfNeeded();
-  if (ShouldDispatchPageConcealEvent()) {
+  if (ShouldDispatchPageSwapEvent()) {
     frame_tree_node_->current_frame_host()
         ->GetAssociatedLocalFrame()
-        ->DispatchPageConceal(WillDispatchPageConceal());
+        ->DispatchPageSwap(WillDispatchPageSwap());
   }
 
   url::Origin origin_to_commit = GetOriginToCommit().value();
@@ -10316,13 +10316,12 @@
   return loader_.get() != nullptr;
 }
 
-blink::mojom::PageConcealEventParamsPtr
-NavigationRequest::WillDispatchPageConceal() {
-  CHECK(ShouldDispatchPageConcealEvent());
+blink::mojom::PageSwapEventParamsPtr NavigationRequest::WillDispatchPageSwap() {
+  CHECK(ShouldDispatchPageSwapEvent());
 
-  did_fire_page_conceal_ = true;
+  did_fire_page_swap_ = true;
 
-  // The `pageconceal` event is fired on the old Document to provide information
+  // The `pageswap` event is fired on the old Document to provide information
   // about the new Document. The information shared must be restricted to
   // same-origin Documents.
   const bool is_same_origin =
@@ -10336,24 +10335,24 @@
 
   CHECK(!frame_tree_node_->current_origin().opaque());
 
-  auto page_conceal_event_params = blink::mojom::PageConcealEventParams::New();
-  page_conceal_event_params->url = common_params_->url;
+  auto page_swap_event_params = blink::mojom::PageSwapEventParams::New();
+  page_swap_event_params->url = common_params_->url;
 
   switch (common_params_->navigation_type) {
     case blink::mojom::NavigationType::RELOAD:
     case blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE:
-      page_conceal_event_params->navigation_type =
+      page_swap_event_params->navigation_type =
           blink::mojom::NavigationTypeForNavigationApi::kReload;
       break;
 
     case blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT:
-      page_conceal_event_params->navigation_type =
+      page_swap_event_params->navigation_type =
           blink::mojom::NavigationTypeForNavigationApi::kTraverse;
-      page_conceal_event_params->page_state = commit_params_->page_state;
+      page_swap_event_params->page_state = commit_params_->page_state;
       break;
 
     case blink::mojom::NavigationType::DIFFERENT_DOCUMENT:
-      page_conceal_event_params->navigation_type =
+      page_swap_event_params->navigation_type =
           common_params_->should_replace_current_entry
               ? blink::mojom::NavigationTypeForNavigationApi::kReplace
               : blink::mojom::NavigationTypeForNavigationApi::kPush;
@@ -10367,10 +10366,10 @@
     case blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT:
     case blink::mojom::NavigationType::SAME_DOCUMENT:
       NOTREACHED_NORETURN()
-          << "Same-document navigations shouldn't fire pageconceal";
+          << "Same-document navigations shouldn't fire pageswap";
   }
 
-  return page_conceal_event_params;
+  return page_swap_event_params;
 }
 
 void NavigationRequest::MaybeRecordTraceEventsAndHistograms() {
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h
index 920d1aa..92fb7f6 100644
--- a/content/browser/renderer_host/navigation_request.h
+++ b/content/browser/renderer_host/navigation_request.h
@@ -1323,13 +1323,13 @@
   bool HasLoader() const;
 
   // Notifies that an IPC will be sent to the old Document's renderer to
-  // dispatch the `pageconceal` event. Returns the parameters which should be
+  // dispatch the `pageswap` event. Returns the parameters which should be
   // used for the event if this is a same-origin navigation.
-  blink::mojom::PageConcealEventParamsPtr WillDispatchPageConceal();
+  blink::mojom::PageSwapEventParamsPtr WillDispatchPageSwap();
 
-  // Returns true if this navigation is eligible for dispatching a `pageconceal`
+  // Returns true if this navigation is eligible for dispatching a `pageswap`
   // event on the old Document and the event has not been dispatched already.
-  bool ShouldDispatchPageConcealEvent() const;
+  bool ShouldDispatchPageSwapEvent() const;
 
  private:
   friend class NavigationRequestTest;
@@ -2852,12 +2852,12 @@
   // value is available.
   std::optional<url::Origin> tentative_data_origin_to_commit_;
 
-  // `pageconceal` can be fired at different stages of the navigation lifecycle:
+  // `pageswap` can be fired at different stages of the navigation lifecycle:
   // - ready to commit if this navigation is associated with a ViewTransition.
   // - unload old document if there is no ViewTransition opt-in.
-  // This tracks whether the pageconceal event has been fired for this
+  // This tracks whether the pageswap event has been fired for this
   // navigation.
-  bool did_fire_page_conceal_ = false;
+  bool did_fire_page_swap_ = false;
 
   base::WeakPtrFactory<NavigationRequest> weak_factory_{this};
 };
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
index 8b25c53..621dee9 100644
--- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
+++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
@@ -7791,7 +7791,7 @@
             /*ignore_outstanding_network_request=*/false);
     enabled_features.push_back(
         {blink::features::kViewTransitionOnNavigation, {{}}});
-    enabled_features.push_back({blink::features::kPageConcealEvent, {{}}});
+    enabled_features.push_back({blink::features::kPageSwapEvent, {{}}});
     enabled_features.push_back(
         {features::kInvalidateLocalSurfaceIdPreCommit, {{}}});
     scoped_feature_list_.InitWithFeaturesAndParameters(
diff --git a/content/browser/renderer_host/render_widget_host_view_ios.mm b/content/browser/renderer_host/render_widget_host_view_ios.mm
index c443a7f..57ecf421 100644
--- a/content/browser/renderer_host/render_widget_host_view_ios.mm
+++ b/content/browser/renderer_host/render_widget_host_view_ios.mm
@@ -10,6 +10,7 @@
 
 #include "base/command_line.h"
 #include "base/strings/sys_string_conversions.h"
+#include "build/ios_buildflags.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/surfaces/frame_sink_id_allocator.h"
 #include "content/browser/renderer_host/browser_compositor_ios.h"
@@ -52,7 +53,13 @@
     gfx::Size(980, 735);
 
 bool IsTesting() {
+#if BUILDFLAG(IS_IOS_APP_EXTENSION)
+  // This class shouldn't really be build with extension anyways.
+  // Fix the build to avoid building browser code in extensions.
+  return false;
+#else
   return [[UIApplication sharedApplication] isRunningTests];
+#endif
 }
 
 gfx::Rect GetDefaultSizeForTesting() {
diff --git a/content/browser/renderer_host/view_transition_commit_deferring_condition.cc b/content/browser/renderer_host/view_transition_commit_deferring_condition.cc
index 9112f40..60b6a98 100644
--- a/content/browser/renderer_host/view_transition_commit_deferring_condition.cc
+++ b/content/browser/renderer_host/view_transition_commit_deferring_condition.cc
@@ -39,7 +39,7 @@
   if (!navigation_request.IsInPrimaryMainFrame())
     return nullptr;
 
-  if (!navigation_request.ShouldDispatchPageConcealEvent()) {
+  if (!navigation_request.ShouldDispatchPageSwapEvent()) {
     return nullptr;
   }
 
@@ -89,16 +89,16 @@
   auto* render_frame_host =
       navigation_request->frame_tree_node()->current_frame_host();
 
-  blink::mojom::PageConcealEventParamsPtr page_conceal_event_params =
-      navigation_request->WillDispatchPageConceal();
-  CHECK(page_conceal_event_params);
+  blink::mojom::PageSwapEventParamsPtr page_swap_event_params =
+      navigation_request->WillDispatchPageSwap();
+  CHECK(page_swap_event_params);
 
   // TODO(crbug.com/1372584):  Implement a timeout, to avoid blocking the
   // navigation for too long.
   CHECK(render_frame_host->IsRenderFrameLive());
   render_frame_host->GetAssociatedLocalFrame()
       ->SnapshotDocumentForViewTransition(
-          std::move(page_conceal_event_params),
+          std::move(page_swap_event_params),
           base::BindOnce(&OnSnapshotAck, std::move(resume),
                          navigation_request->GetWeakPtr()));
   return Result::kDefer;
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 6da8fc7..da232cd 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -242,8 +242,7 @@
            raw_ref(blink::features::kSharedStorageAPIM118),
            kSetOnlyIfOverridden},
           {wf::EnableSharedStorageAPIM123,
-           raw_ref(blink::features::kSharedStorageAPIM123),
-           kSetOnlyIfOverridden},
+           raw_ref(blink::features::kSharedStorageAPIM123), kDefault},
           {wf::EnableFedCmMultipleIdentityProviders,
            raw_ref(features::kFedCmMultipleIdentityProviders), kDefault},
           {wf::EnableFedCmDisconnect, raw_ref(features::kFedCmDisconnect),
diff --git a/content/public/test/fake_local_frame.cc b/content/public/test/fake_local_frame.cc
index 2aeef86..1cbf984 100644
--- a/content/public/test/fake_local_frame.cc
+++ b/content/public/test/fake_local_frame.cc
@@ -202,11 +202,10 @@
     bool is_browser_initiated) {}
 
 void FakeLocalFrame::SnapshotDocumentForViewTransition(
-    blink::mojom::PageConcealEventParamsPtr,
+    blink::mojom::PageSwapEventParamsPtr,
     SnapshotDocumentForViewTransitionCallback callback) {}
 
-void FakeLocalFrame::DispatchPageConceal(
-    blink::mojom::PageConcealEventParamsPtr) {}
+void FakeLocalFrame::DispatchPageSwap(blink::mojom::PageSwapEventParamsPtr) {}
 
 void FakeLocalFrame::AddResourceTimingEntryForFailedSubframeNavigation(
     const ::blink::FrameToken& subframe_token,
diff --git a/content/public/test/fake_local_frame.h b/content/public/test/fake_local_frame.h
index 6401523..481a36c 100644
--- a/content/public/test/fake_local_frame.h
+++ b/content/public/test/fake_local_frame.h
@@ -154,9 +154,9 @@
       const std::string& page_state,
       bool is_browser_initiated) override;
   void SnapshotDocumentForViewTransition(
-      blink::mojom::PageConcealEventParamsPtr,
+      blink::mojom::PageSwapEventParamsPtr,
       SnapshotDocumentForViewTransitionCallback callback) override;
-  void DispatchPageConceal(blink::mojom::PageConcealEventParamsPtr) override;
+  void DispatchPageSwap(blink::mojom::PageSwapEventParamsPtr) override;
   void AddResourceTimingEntryForFailedSubframeNavigation(
       const ::blink::FrameToken& subframe_token,
       const GURL& initial_url,
diff --git a/content/shell/app/ios/BUILD.gn b/content/shell/app/ios/BUILD.gn
index 7684e84..97a9a397 100644
--- a/content/shell/app/ios/BUILD.gn
+++ b/content/shell/app/ios/BUILD.gn
@@ -25,6 +25,8 @@
 
   sources = [ "../shell_main.cc" ]
 
+  ldflags = [ "-Wl,--ignore-auto-link-option=CoreAudioTypes" ]
+
   deps = [
     "//content/app/ios/appex:content_process",
     "//content/public/app",
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 2815030..0dad112 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -3202,7 +3202,7 @@
     sources += [
       "../browser/accessibility/browser_accessibility_manager_win_unittest.cc",
       "../browser/accessibility/browser_accessibility_win_unittest.cc",
-      "../browser/device_posture/device_posture_platform_provider_win_unittest.cc",
+      "../browser/device_posture/device_posture_registry_watcher_win_unittest.cc",
       "../browser/renderer_host/direct_manipulation_test_helper_win.cc",
       "../browser/renderer_host/direct_manipulation_test_helper_win.h",
       "../browser/renderer_host/direct_manipulation_win_unittest.cc",
diff --git a/content/web_test/common/web_test.mojom b/content/web_test/common/web_test.mojom
index 40be113..3b6650d1 100644
--- a/content/web_test/common/web_test.mojom
+++ b/content/web_test/common/web_test.mojom
@@ -4,6 +4,7 @@
 
 module content.mojom;
 
+import "mojo/public/mojom/base/byte_string.mojom";
 import "mojo/public/mojom/base/file_path.mojom";
 import "mojo/public/mojom/base/string16.mojom";
 import "mojo/public/mojom/base/values.mojom";
@@ -44,8 +45,9 @@
   // Audio dump.
   array<uint8>? audio;
 
-  // Layout dump.
-  string? layout;
+  // Layout dump. A ByteString rather than a string because the layout dump can
+  // be supplied by the test and may contain non-UTF8 encoded text.
+  mojo_base.mojom.ByteString? layout;
 
   // Image dump.
   skia.mojom.BitmapN32? pixels;
diff --git a/docs/unsafe_buffers.md b/docs/unsafe_buffers.md
new file mode 100644
index 0000000..de80e6d
--- /dev/null
+++ b/docs/unsafe_buffers.md
@@ -0,0 +1,39 @@
+# Preventing OOB through Unsafe Buffers errors (aka Spanification)
+
+Out-of-bounds (OOB) security bugs commonly happen through pointers
+which have no bounds checks associated with them. We prevent such
+bugs by always using containers.
+
+Most pointers are unowned references into an array (or vector)
+and the most appropriate replacement for the pointer is
+base::span.
+
+When a file or directory is known to pass compilation with
+`-Wunsafe-buffer-usage`,it should be added to the
+[`//build/config/unsafe_buffers_paths.txt`](../build/config/unsafe_buffers_paths.txt)
+file to enable compiler errors if unsafe pointer usage is added to
+the file later.
+
+# Functions with array pointer parameters
+
+Functions that receive a pointer into an array may read
+or write out of bounds of the pointer if given a pointer that
+is incorrectly sized. Such functions should be marked with the
+UNSAFE_BUFFER_USAGE attribute macro.
+
+The same is true for functions that accept an iterator instead
+of a range type. Some examples of each are memcpy() and
+std::copy().
+
+Calling such functions is unsafe and should generally be avoided.
+Instead, replace such functions with an API built on base::span
+or other range types which prevents any chance of OOB memory
+access. For instance, replace `memcpy()`, `std::copy()` and
+`std::ranges::copy()` with `base::span::copy_from()`. And
+replace `memset()` with `std::ranges::fill()`.
+
+# Writing unsafe data structures with pointers
+
+TODO: Write about `UNSAFE_BUFFERS()` for rare exceptions where
+the correctness of pointer bounds can be fully explained and
+encapsulated, such as within a data structure.
diff --git a/docs/website b/docs/website
index 7918c58..f2eab19 160000
--- a/docs/website
+++ b/docs/website
@@ -1 +1 @@
-Subproject commit 7918c586771aed5e170cb5ce33fdfc38f6203063
+Subproject commit f2eab19faaecbab4992d4633704136e5778faabc
diff --git a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
index c6b35b7..0fa7721c 100644
--- a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
+++ b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
@@ -71,16 +71,6 @@
   UMA_HISTOGRAM_ENUMERATION(kLoadRulesetResultHistogram, result);
 }
 
-// Whether the `extension` has the permission to use the declarativeNetRequest
-// API.
-bool HasAPIPermission(const Extension& extension) {
-  const PermissionsData* permissions = extension.permissions_data();
-  return permissions->HasAPIPermission(
-             mojom::APIPermissionID::kDeclarativeNetRequest) ||
-         permissions->HasAPIPermission(
-             mojom::APIPermissionID::kDeclarativeNetRequestWithHostAccess);
-}
-
 // Returns whether the extension's allocation should be released. This would
 // return true for cases where we expect the extension to be unloaded for a
 // while or if the extension directory's contents changed in a reload.
@@ -141,7 +131,7 @@
 
 HostPermissionsAlwaysRequired GetHostPermissionsAlwaysRequired(
     const Extension& extension) {
-  DCHECK(HasAPIPermission(extension));
+  DCHECK(HasAnyDNRPermission(extension));
   const PermissionsData* permissions = extension.permissions_data();
 
   if (permissions->HasAPIPermission(
@@ -461,8 +451,9 @@
     const Extension* extension,
     bool is_update,
     const std::string& old_name) {
-  if (!HasAPIPermission(*extension))
+  if (!HasAnyDNRPermission(*extension)) {
     return;
+  }
 
   if (!is_update || Manifest::IsUnpackedLocation(extension->location()))
     return;
@@ -481,8 +472,9 @@
     const Extension* extension) {
   DCHECK_EQ(context_, browser_context);
 
-  if (!HasAPIPermission(*extension))
+  if (!HasAnyDNRPermission(*extension)) {
     return;
+  }
 
   LoadRequestData load_data(extension->id(), extension->version());
   int expected_ruleset_checksum;
@@ -554,8 +546,9 @@
     UnloadedExtensionReason reason) {
   DCHECK_EQ(context_, browser_context);
 
-  if (!HasAPIPermission(*extension))
+  if (!HasAnyDNRPermission(*extension)) {
     return;
+  }
 
   // If the extension is unloaded for any reason other than an update, the
   // unused rule allocation should not be kept for this extension the next
@@ -585,8 +578,9 @@
     UninstallReason reason) {
   DCHECK_EQ(context_, browser_context);
 
-  if (!HasAPIPermission(*extension))
+  if (!HasAnyDNRPermission(*extension)) {
     return;
+  }
 
   session_rules_.erase(extension->id());
 
diff --git a/extensions/browser/api/declarative_net_request/utils.cc b/extensions/browser/api/declarative_net_request/utils.cc
index 7d9e53f..af9c7aed 100644
--- a/extensions/browser/api/declarative_net_request/utils.cc
+++ b/extensions/browser/api/declarative_net_request/utils.cc
@@ -488,6 +488,14 @@
   return enabled_static_rule_count;
 }
 
+bool HasAnyDNRPermission(const Extension& extension) {
+  const PermissionsData* permissions = extension.permissions_data();
+  return permissions->HasAPIPermission(
+             mojom::APIPermissionID::kDeclarativeNetRequest) ||
+         permissions->HasAPIPermission(
+             mojom::APIPermissionID::kDeclarativeNetRequestWithHostAccess);
+}
+
 bool HasDNRFeedbackPermission(const Extension* extension,
                               const std::optional<int>& tab_id) {
   const PermissionsData* permissions_data = extension->permissions_data();
diff --git a/extensions/browser/api/declarative_net_request/utils.h b/extensions/browser/api/declarative_net_request/utils.h
index d98de5f0..1f0893c7 100644
--- a/extensions/browser/api/declarative_net_request/utils.h
+++ b/extensions/browser/api/declarative_net_request/utils.h
@@ -19,6 +19,7 @@
 #include "extensions/browser/api/web_request/web_request_resource_type.h"
 #include "extensions/common/api/declarative_net_request.h"
 #include "extensions/common/api/declarative_net_request/constants.h"
+#include "extensions/common/extension.h"
 #include "third_party/re2/src/re2/re2.h"
 
 namespace base {
@@ -169,6 +170,10 @@
 // |composite_matcher|.
 size_t GetEnabledStaticRuleCount(const CompositeMatcher* composite_matcher);
 
+// Whether the `extension` has the permission to use the declarativeNetRequest
+// API.
+bool HasAnyDNRPermission(const Extension& extension);
+
 // Returns true if |extension| has the declarativeNetRequestFeedback permission
 // for the specified |tab_id|. If |tab_is| is omitted, then non-tab specific
 // permissions are checked.
diff --git a/extensions/browser/api/web_request/extension_web_request_event_router.cc b/extensions/browser/api/web_request/extension_web_request_event_router.cc
index 90ba672..7b99af2d 100644
--- a/extensions/browser/api/web_request/extension_web_request_event_router.cc
+++ b/extensions/browser/api/web_request/extension_web_request_event_router.cc
@@ -33,6 +33,7 @@
 #include "extensions/browser/api/web_request/web_request_time_tracker.h"
 #include "extensions/browser/api_activity_monitor.h"
 #include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/browser/process_map.h"
 #include "extensions/common/api/web_request/web_request_activity_log_constants.h"
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc
index baab943..f031257 100644
--- a/extensions/browser/api/web_request/web_request_api.cc
+++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -28,6 +28,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/url_constants.h"
+#include "extensions/browser/api/declarative_net_request/utils.h"
 #include "extensions/browser/api/web_request/extension_web_request_event_router.h"
 #include "extensions/browser/api/web_request/web_request_api_constants.h"
 #include "extensions/browser/api/web_request/web_request_api_helpers.h"
@@ -240,6 +241,13 @@
                            request_id.request_id, std::move(callback));
 }
 
+void WebRequestAPI::ProxySet::OnDNRExtensionUnloaded(
+    const Extension* extension) {
+  for (const auto& proxy : proxies_) {
+    proxy->OnDNRExtensionUnloaded(extension);
+  }
+}
+
 WebRequestAPI::RequestIDGenerator::RequestIDGenerator() = default;
 WebRequestAPI::RequestIDGenerator::~RequestIDGenerator() = default;
 
@@ -630,6 +638,10 @@
     --web_request_extension_count_;
     UpdateMayHaveProxies();
   }
+
+  if (declarative_net_request::HasAnyDNRPermission(*extension)) {
+    proxies_->OnDNRExtensionUnloaded(extension);
+  }
 }
 
 void WebRequestAPI::UpdateActiveListener(
diff --git a/extensions/browser/api/web_request/web_request_api.h b/extensions/browser/api/web_request/web_request_api.h
index ff85a72..ec5cc7c 100644
--- a/extensions/browser/api/web_request/web_request_api.h
+++ b/extensions/browser/api/web_request/web_request_api.h
@@ -95,6 +95,11 @@
         scoped_refptr<net::HttpResponseHeaders> response_headers,
         int32_t request_id,
         AuthRequestCallback callback);
+
+    // Called when an extension that can execute declarativeNetRequest actions
+    // is unloaded, so orphaned DNR actions on current requests can be cleaned
+    // up.
+    virtual void OnDNRExtensionUnloaded(const Extension* extension) = 0;
   };
 
   // A ProxySet is a set of proxies used by WebRequestAPI: It holds Proxy
@@ -134,6 +139,8 @@
         const content::GlobalRequestID& request_id,
         AuthRequestCallback callback);
 
+    void OnDNRExtensionUnloaded(const Extension* extension);
+
    private:
     // Although these members are initialized on the UI thread, we expect at
     // least one memory barrier before actually calling Generate in the IO
diff --git a/extensions/browser/api/web_request/web_request_api_helpers.cc b/extensions/browser/api/web_request/web_request_api_helpers.cc
index 08b8e37..89ea7a3 100644
--- a/extensions/browser/api/web_request/web_request_api_helpers.cc
+++ b/extensions/browser/api/web_request/web_request_api_helpers.cc
@@ -38,7 +38,6 @@
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/web_request/web_request_api_constants.h"
 #include "extensions/browser/api/web_request/web_request_info.h"
-#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/common/api/declarative_net_request.h"
diff --git a/extensions/browser/api/web_request/web_request_info.cc b/extensions/browser/api/web_request/web_request_info.cc
index 3c4ba5f..c1296e13 100644
--- a/extensions/browser/api/web_request/web_request_info.cc
+++ b/extensions/browser/api/web_request/web_request_info.cc
@@ -257,4 +257,15 @@
   response_from_cache = response.was_fetched_via_cache;
 }
 
+void WebRequestInfo::EraseDNRActionsForExtension(
+    const ExtensionId& extension_id) {
+  if (dnr_actions.has_value()) {
+    std::erase_if(
+        *dnr_actions,
+        [extension_id](declarative_net_request::RequestAction& action) {
+          return action.extension_id == extension_id;
+        });
+  }
+}
+
 }  // namespace extensions
diff --git a/extensions/browser/api/web_request/web_request_info.h b/extensions/browser/api/web_request/web_request_info.h
index bcca020..c9e9c1d 100644
--- a/extensions/browser/api/web_request/web_request_info.h
+++ b/extensions/browser/api/web_request/web_request_info.h
@@ -94,6 +94,10 @@
   void AddResponseInfoFromResourceResponse(
       const network::mojom::URLResponseHead& response);
 
+  // Erases all actions in `dnr_actions` that are associated with the given
+  // `extension_id`.
+  void EraseDNRActionsForExtension(const ExtensionId& extension_id);
+
   // A unique identifier for this request.
   const uint64_t id;
 
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
index cece63a..0a5a1a9 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
@@ -1326,6 +1326,7 @@
 
   std::move(callback_pair.second).Run(net::OK);
 }
+
 void WebRequestProxyingURLLoaderFactory::InProgressRequest::OnRequestError(
     const network::URLLoaderCompletionStatus& status,
     State state) {
@@ -1434,6 +1435,13 @@
   return status;
 }
 
+void WebRequestProxyingURLLoaderFactory::InProgressRequest::
+    EraseDNRActionsForExtension(const ExtensionId& extension_id) {
+  if (info_) {
+    info_->EraseDNRActionsForExtension(extension_id);
+  }
+}
+
 WebRequestProxyingURLLoaderFactory::WebRequestProxyingURLLoaderFactory(
     content::BrowserContext* browser_context,
     int render_process_id,
@@ -1619,6 +1627,13 @@
                                         std::move(callback));
 }
 
+void WebRequestProxyingURLLoaderFactory::OnDNRExtensionUnloaded(
+    const Extension* extension) {
+  for (auto& request : requests_) {
+    request.second->EraseDNRActionsForExtension(extension->id());
+  }
+}
+
 WebRequestProxyingURLLoaderFactory::~WebRequestProxyingURLLoaderFactory() =
     default;
 
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
index fd423c5..f88e9e9 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
@@ -139,6 +139,10 @@
                            const net::IPEndPoint& endpoint,
                            OnHeadersReceivedCallback callback) override;
 
+    // Erases all DNR actions in `info_` that are associated with
+    // `extension_id`.
+    void EraseDNRActionsForExtension(const ExtensionId& extension_id);
+
    private:
     // The state of an InProgressRequest. This is reported via UMA and UKM
     // at the end of the request, so do not change enum values.
@@ -348,6 +352,7 @@
       scoped_refptr<net::HttpResponseHeaders> response_headers,
       int32_t request_id,
       WebRequestAPI::AuthRequestCallback callback) override;
+  void OnDNRExtensionUnloaded(const Extension* extension) override;
 
   content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type()
       const {
diff --git a/extensions/browser/api/web_request/web_request_proxying_websocket.cc b/extensions/browser/api/web_request/web_request_proxying_websocket.cc
index 3270bc9..75ab6bd 100644
--- a/extensions/browser/api/web_request/web_request_proxying_websocket.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_websocket.cc
@@ -285,6 +285,11 @@
   ContinueToHeadersReceived();
 }
 
+void WebRequestProxyingWebSocket::OnDNRExtensionUnloaded(
+    const Extension* extension) {
+  info_.EraseDNRActionsForExtension(extension->id());
+}
+
 void WebRequestProxyingWebSocket::StartProxying(
     WebSocketFactory factory,
     const GURL& url,
diff --git a/extensions/browser/api/web_request/web_request_proxying_websocket.h b/extensions/browser/api/web_request/web_request_proxying_websocket.h
index 301757a4..c8b4d1c 100644
--- a/extensions/browser/api/web_request/web_request_proxying_websocket.h
+++ b/extensions/browser/api/web_request/web_request_proxying_websocket.h
@@ -88,6 +88,9 @@
                          const net::IPEndPoint& endpoint,
                          OnHeadersReceivedCallback callback) override;
 
+  // WebRequestAPI::Proxy:
+  void OnDNRExtensionUnloaded(const Extension* extension) override;
+
   static void StartProxying(
       WebSocketFactory factory,
       const GURL& url,
diff --git a/extensions/browser/api/web_request/web_request_proxying_webtransport.cc b/extensions/browser/api/web_request/web_request_proxying_webtransport.cc
index 8c3d7873..0263e4b 100644
--- a/extensions/browser/api/web_request/web_request_proxying_webtransport.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_webtransport.cc
@@ -238,6 +238,11 @@
   }
 
  private:
+  // WebRequestAPI::Proxy:
+  void OnDNRExtensionUnloaded(const Extension* extension) override {
+    info_.EraseDNRActionsForExtension(extension->id());
+  }
+
   mojo::PendingRemote<WebTransportHandshakeClient> handshake_client_;
   // Weak reference to the ProxySet. This is safe as `proxies_` owns this
   // object.
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index 72722cc..ee72282 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -1474,15 +1474,16 @@
       "automationInternal", std::make_unique<AutomationInternalCustomBindings>(
                                 context, bindings_system));
 
-  delegate_->RegisterNativeHandlers(this, module_system, bindings_system,
-                                    context);
+  for (const auto& api_provider : api_providers_) {
+    api_provider->RegisterNativeHandlers(module_system, bindings_system,
+                                         context);
+  }
 }
 
 void Dispatcher::PopulateSourceMap() {
   const std::vector<JsResourceInfo> resources = GetJsResources();
   for (const auto& resource : resources)
     source_map_.RegisterSource(resource.name, resource.id);
-  delegate_->PopulateSourceMap(&source_map_);
   for (const auto& api_provider : api_providers_) {
     api_provider->PopulateSourceMap(&source_map_);
   }
diff --git a/extensions/renderer/dispatcher_delegate.h b/extensions/renderer/dispatcher_delegate.h
index 2ee9b7b..9b52227 100644
--- a/extensions/renderer/dispatcher_delegate.h
+++ b/extensions/renderer/dispatcher_delegate.h
@@ -10,9 +10,7 @@
 
 namespace extensions {
 class Dispatcher;
-class ModuleSystem;
 class NativeExtensionBindingsSystem;
-class ResourceBundleSourceMap;
 class ScriptContext;
 
 // Base class and default implementation for an extensions::Dispacher delegate.
@@ -22,16 +20,6 @@
  public:
   virtual ~DispatcherDelegate() {}
 
-  // Includes additional native handlers in a ScriptContext's ModuleSystem.
-  virtual void RegisterNativeHandlers(
-      Dispatcher* dispatcher,
-      ModuleSystem* module_system,
-      NativeExtensionBindingsSystem* bindings_system,
-      ScriptContext* context) {}
-
-  // Includes additional source resources into the resource map.
-  virtual void PopulateSourceMap(ResourceBundleSourceMap* source_map) {}
-
   // Requires modules for defining <webview> within an extension context's
   // module system.
   virtual void RequireWebViewModules(ScriptContext* context);
diff --git a/extensions/renderer/extensions_renderer_api_provider.h b/extensions/renderer/extensions_renderer_api_provider.h
index 9894492d..f57c10f9c 100644
--- a/extensions/renderer/extensions_renderer_api_provider.h
+++ b/extensions/renderer/extensions_renderer_api_provider.h
@@ -7,6 +7,8 @@
 
 namespace extensions {
 
+class ModuleSystem;
+class NativeExtensionBindingsSystem;
 class ScriptContext;
 class ResourceBundleSourceMap;
 
@@ -18,13 +20,21 @@
  public:
   virtual ~ExtensionsRendererAPIProvider() = default;
 
-  // Blink maintains an allowlist for custom element names. This method
-  // provides the delegate the ability to add more names to that allowlist.
-  virtual void EnableCustomElementAllowlist() = 0;
+  // Registers any native handlers to provide additional functionality for
+  // native bindings. Called each time a new ScriptContext is created, since
+  // native handlers are per-context.
+  virtual void RegisterNativeHandlers(
+      ModuleSystem* module_system,
+      NativeExtensionBindingsSystem* bindings_system,
+      ScriptContext* context) = 0;
 
   // Includes additional source resources into the resource map.
   virtual void PopulateSourceMap(ResourceBundleSourceMap* source_map) = 0;
 
+  // Blink maintains an allowlist for custom element names. This method
+  // provides the delegate the ability to add more names to that allowlist.
+  virtual void EnableCustomElementAllowlist() = 0;
+
   // Requires modules for defining WebView APIs within a ScriptContext's
   // ModuleSystem.
   virtual bool RequireWebViewModules(ScriptContext* context) = 0;
diff --git a/infra/config/generated/testing/mixins.pyl b/infra/config/generated/testing/mixins.pyl
index 5c1b91b..220ad86 100644
--- a/infra/config/generated/testing/mixins.pyl
+++ b/infra/config/generated/testing/mixins.pyl
@@ -247,11 +247,6 @@
       },
     },
   },
-  'chrome-refresh-2023': {
-    'args': [
-      '--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh',
-    ],
-  },
   'chrome-swarming-pool': {
     'swarming': {
       'dimensions': {
diff --git a/infra/config/generated/testing/test_suites.pyl b/infra/config/generated/testing/test_suites.pyl
index 1856283..60cf421 100644
--- a/infra/config/generated/testing/test_suites.pyl
+++ b/infra/config/generated/testing/test_suites.pyl
@@ -621,7 +621,7 @@
       'chromeos_js_code_coverage_browser_tests': {
         'test': 'browser_tests',
         'swarming': {
-          'shards': 20,
+          'shards': 32,
         },
       },
     },
@@ -1718,145 +1718,6 @@
       },
     },
 
-    'cr23_linux_gtests': {
-      'cr23_browser_tests': {
-        'test': 'browser_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 20,
-        },
-      },
-      'cr23_interactive_ui_tests': {
-        'test': 'interactive_ui_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 10,
-        },
-      },
-      'cr23_views_unittests': {
-        'test': 'views_unittests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'ci_only': True,
-      },
-    },
-
-    'cr23_mac_gtests': {
-      'cr23_browser_tests': {
-        'test': 'browser_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 20,
-        },
-      },
-      'cr23_interactive_ui_tests': {
-        'test': 'interactive_ui_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 10,
-        },
-      },
-      'cr23_views_unittests': {
-        'test': 'views_unittests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'ci_only': True,
-      },
-    },
-
-    'cr23_pixel_browser_tests_gtests': {
-      'cr23_pixel_browser_tests': {
-        'test': 'browser_tests',
-        'mixins': [
-          'skia_gold_test',
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--browser-ui-tests-verify-pixels',
-          '--enable-pixel-output-in-tests',
-          '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter',
-          '--test-launcher-jobs=1',
-        ],
-        'swarming': {
-          'shards': 3,
-        },
-      },
-      'cr23_pixel_interactive_ui_tests': {
-        'test': 'interactive_ui_tests',
-        'mixins': [
-          'skia_gold_test',
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--browser-ui-tests-verify-pixels',
-          '--enable-pixel-output-in-tests',
-          '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter',
-        ],
-      },
-    },
-
-    'cr23_win_gtests': {
-      'cr23_browser_tests': {
-        'test': 'browser_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 20,
-        },
-      },
-      'cr23_interactive_ui_tests': {
-        'test': 'interactive_ui_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 10,
-        },
-      },
-      'cr23_views_unittests': {
-        'test': 'views_unittests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'ci_only': True,
-      },
-    },
-
     'cronet_gtests': {
       'cronet_sample_test_apk': {},
       'cronet_smoketests_apk': {},
@@ -6051,22 +5912,6 @@
       'vr_platform_specific_chromium_gtests',
     ],
 
-    'chromium_linux_gtests_once': [
-      'aura_gtests',
-      'chromium_gtests',
-      'chromium_gtests_for_devices_with_graphical_output',
-      'chromium_gtests_for_linux_and_chromeos_only',
-      'chromium_gtests_for_linux_and_mac_only',
-      'chromium_gtests_for_linux_only',
-      'chromium_gtests_for_win_and_linux_only',
-      'cr23_linux_gtests',
-      'linux_flavor_specific_chromium_gtests',
-      'linux_specific_xr_gtests',
-      'non_android_and_cast_and_chromeos_chromium_gtests',
-      'non_android_chromium_gtests_no_nacl',
-      'vr_platform_specific_chromium_gtests',
-    ],
-
     'chromium_linux_rel_isolated_scripts': [
       'chromedriver_py_tests_isolated_scripts',
       'chromium_web_tests_high_dpi_isolated_scripts',
@@ -6121,15 +5966,6 @@
       'non_android_chromium_gtests_no_nacl',
     ],
 
-    'chromium_mac_gtests_no_nacl_once': [
-      'chromium_gtests',
-      'chromium_gtests_for_devices_with_graphical_output',
-      'cr23_mac_gtests',
-      'mac_specific_chromium_gtests',
-      'non_android_and_cast_and_chromeos_chromium_gtests',
-      'non_android_chromium_gtests_no_nacl',
-    ],
-
     'chromium_mac_rel_isolated_scripts': [
       'chromedriver_py_tests_isolated_scripts',
       'components_perftests_isolated_scripts',
@@ -6167,7 +6003,6 @@
       'chromium_gtests',
       'chromium_gtests_for_devices_with_graphical_output',
       'chromium_gtests_for_win_and_linux_only',
-      'cr23_pixel_browser_tests_gtests',
       'fieldtrial_browser_tests',
       'non_android_and_cast_and_chromeos_chromium_gtests',
       'non_android_chromium_gtests_no_nacl',
@@ -6181,22 +6016,6 @@
       'chromium_gtests_for_windows_multiscreen',
     ],
 
-    'chromium_win10_gtests_once': [
-      'aura_gtests',
-      'chromium_gtests',
-      'chromium_gtests_for_devices_with_graphical_output',
-      'chromium_gtests_for_win_and_linux_only',
-      'cr23_pixel_browser_tests_gtests',
-      'cr23_win_gtests',
-      'fieldtrial_browser_tests',
-      'non_android_and_cast_and_chromeos_chromium_gtests',
-      'non_android_chromium_gtests_no_nacl',
-      'non_android_chromium_gtests_skia_gold',
-      'pixel_browser_tests_gtests',
-      'vr_platform_specific_chromium_gtests',
-      'win_specific_chromium_gtests',
-    ],
-
     'chromium_win_dbg_isolated_scripts': [
       'chromedriver_py_tests_isolated_scripts',
       'components_perftests_isolated_scripts',
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl
index b216ae7..8f96eb02 100644
--- a/infra/config/generated/testing/variants.pyl
+++ b/infra/config/generated/testing/variants.pyl
@@ -323,16 +323,16 @@
   },
   'LACROS_VERSION_SKEW_DEV': {
     'identifier': 'Lacros version skew testing ash dev',
-    'description': 'Run with ash-chrome version 123.0.6312.11',
+    'description': 'Run with ash-chrome version 123.0.6312.18',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v123.0.6312.11',
-          'revision': 'version:123.0.6312.11',
+          'location': 'lacros_version_skew_tests_v123.0.6312.18',
+          'revision': 'version:123.0.6312.18',
         },
       ],
     },
diff --git a/infra/config/targets/basic_suites.star b/infra/config/targets/basic_suites.star
index 942d35c..29fd5878 100644
--- a/infra/config/targets/basic_suites.star
+++ b/infra/config/targets/basic_suites.star
@@ -631,7 +631,7 @@
     tests = {
         "chromeos_js_code_coverage_browser_tests": targets.legacy_test_config(
             swarming = targets.swarming(
-                shards = 20,
+                shards = 32,
             ),
         ),
     },
@@ -1625,109 +1625,6 @@
     },
 )
 
-# TODO(crbug.com/1444855): Delete the cr23_{linux,mac,win}_gtest suites
-# after the ChromeRefresh2023 is fully rolled out.
-targets.legacy_basic_suite(
-    name = "cr23_linux_gtests",
-    tests = {
-        "cr23_browser_tests": targets.legacy_test_config(
-            args = [
-                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter",
-            ],
-            ci_only = True,
-            swarming = targets.swarming(
-                shards = 20,
-            ),
-        ),
-        "cr23_interactive_ui_tests": targets.legacy_test_config(
-            args = [
-                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter",
-            ],
-            ci_only = True,
-            swarming = targets.swarming(
-                shards = 10,
-            ),
-        ),
-        "cr23_views_unittests": targets.legacy_test_config(
-            ci_only = True,
-        ),
-    },
-)
-
-targets.legacy_basic_suite(
-    name = "cr23_mac_gtests",
-    tests = {
-        "cr23_browser_tests": targets.legacy_test_config(
-            args = [
-                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter",
-            ],
-            ci_only = True,
-            swarming = targets.swarming(
-                shards = 20,
-            ),
-        ),
-        "cr23_interactive_ui_tests": targets.legacy_test_config(
-            args = [
-                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter",
-            ],
-            ci_only = True,
-            swarming = targets.swarming(
-                shards = 10,
-            ),
-        ),
-        "cr23_views_unittests": targets.legacy_test_config(
-            ci_only = True,
-        ),
-    },
-)
-
-targets.legacy_basic_suite(
-    name = "cr23_pixel_browser_tests_gtests",
-    tests = {
-        "cr23_pixel_browser_tests": targets.legacy_test_config(
-            args = [
-                "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter",
-                "--test-launcher-jobs=1",
-            ],
-            swarming = targets.swarming(
-                shards = 3,
-            ),
-        ),
-        "cr23_pixel_interactive_ui_tests": targets.legacy_test_config(
-            args = [
-                "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter",
-            ],
-        ),
-    },
-)
-
-targets.legacy_basic_suite(
-    name = "cr23_win_gtests",
-    tests = {
-        "cr23_browser_tests": targets.legacy_test_config(
-            args = [
-                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter",
-            ],
-            ci_only = True,
-            swarming = targets.swarming(
-                shards = 20,
-            ),
-        ),
-        "cr23_interactive_ui_tests": targets.legacy_test_config(
-            args = [
-                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter",
-            ],
-            ci_only = True,
-            swarming = targets.swarming(
-                shards = 10,
-            ),
-        ),
-        "cr23_views_unittests": targets.legacy_test_config(
-            ci_only = True,
-        ),
-    },
-)
-
 targets.legacy_basic_suite(
     name = "cronet_gtests",
     tests = {
diff --git a/infra/config/targets/compound_suites.star b/infra/config/targets/compound_suites.star
index b29d016..8b94342 100644
--- a/infra/config/targets/compound_suites.star
+++ b/infra/config/targets/compound_suites.star
@@ -299,8 +299,7 @@
 )
 
 # When changing something here, change chromium_linux_and_gl_gtests,
-# chromium_linux_and_gl_and_vulkan_gtests, and
-# chromium_linux_rel_gtests_once in the same way.
+# chromium_linux_and_gl_and_vulkan_gtests in the same way.
 targets.legacy_compound_suite(
     name = "chromium_linux_gtests",
     basic_suites = [
@@ -319,32 +318,6 @@
     ],
 )
 
-# TODO(crbug.com/1444855): This set should match chromium_linux_gtests,
-# except that it also runs tests that we can afford to run only once on
-# Linux machines (for now, this is just the cr23_linux_gtests).
-#
-# Delete this test suite after the ChromeRefresh2023 is fully rolled out
-# (assuming no other test suites are being run only once) and make sure
-# any bots go back to using chromium_linux_gtests.
-targets.legacy_compound_suite(
-    name = "chromium_linux_gtests_once",
-    basic_suites = [
-        "aura_gtests",
-        "chromium_gtests",
-        "chromium_gtests_for_devices_with_graphical_output",
-        "chromium_gtests_for_linux_and_chromeos_only",
-        "chromium_gtests_for_linux_and_mac_only",
-        "chromium_gtests_for_linux_only",
-        "chromium_gtests_for_win_and_linux_only",
-        "cr23_linux_gtests",
-        "linux_flavor_specific_chromium_gtests",
-        "linux_specific_xr_gtests",
-        "non_android_and_cast_and_chromeos_chromium_gtests",
-        "non_android_chromium_gtests_no_nacl",
-        "vr_platform_specific_chromium_gtests",
-    ],
-)
-
 targets.legacy_compound_suite(
     name = "chromium_linux_rel_isolated_scripts",
     basic_suites = [
@@ -409,7 +382,6 @@
     ],
 )
 
-# When changing something here, change
 # chromium_mac_gtests_no_nacl_once in the same way.
 # TODO(b/303417958): This no_nacl suite is identical to the normal suite, since
 # NaCl has been disabled on Mac. Replace this by the normal suite.
@@ -425,26 +397,6 @@
     ],
 )
 
-# TODO(crbug.com/1444855): This set should match
-# chromium_mac_gtests_no_nacl, except that it also runs tests that we can
-# only afford to run once on Mac machines (for now, this is just the
-# cr23_mac_gtests).
-#
-# Delete this test suite after the ChromeRefresh2023 is fully rolled out
-# and make sure any bots go back to using
-# chromium_mac_gtests_no_nacl_no_nocompile.
-targets.legacy_compound_suite(
-    name = "chromium_mac_gtests_no_nacl_once",
-    basic_suites = [
-        "chromium_gtests",
-        "chromium_gtests_for_devices_with_graphical_output",
-        "cr23_mac_gtests",
-        "mac_specific_chromium_gtests",
-        "non_android_and_cast_and_chromeos_chromium_gtests",
-        "non_android_chromium_gtests_no_nacl",
-    ],
-)
-
 targets.legacy_compound_suite(
     name = "chromium_mac_rel_isolated_scripts",
     basic_suites = [
@@ -506,7 +458,6 @@
         "chromium_gtests",
         "chromium_gtests_for_devices_with_graphical_output",
         "chromium_gtests_for_win_and_linux_only",
-        "cr23_pixel_browser_tests_gtests",
         "fieldtrial_browser_tests",
         "non_android_and_cast_and_chromeos_chromium_gtests",
         "non_android_chromium_gtests_no_nacl",
@@ -524,31 +475,6 @@
     ],
 )
 
-# TODO(crbug.com/1444855): This set should match chromium_win10_gtests,
-# except that it also runs tests that we can afford to run only once
-# on Windows machines (for now this is just the cr23_win_gtests).
-#
-# Delete this test suite after the ChromeRefresh2023 is fully rolled out
-# and make sure any bots go back to using chromium_win10_gtests.
-targets.legacy_compound_suite(
-    name = "chromium_win10_gtests_once",
-    basic_suites = [
-        "aura_gtests",
-        "chromium_gtests",
-        "chromium_gtests_for_devices_with_graphical_output",
-        "chromium_gtests_for_win_and_linux_only",
-        "cr23_pixel_browser_tests_gtests",
-        "cr23_win_gtests",
-        "fieldtrial_browser_tests",
-        "non_android_and_cast_and_chromeos_chromium_gtests",
-        "non_android_chromium_gtests_no_nacl",
-        "non_android_chromium_gtests_skia_gold",
-        "pixel_browser_tests_gtests",
-        "vr_platform_specific_chromium_gtests",
-        "win_specific_chromium_gtests",
-    ],
-)
-
 targets.legacy_compound_suite(
     name = "chromium_win_dbg_isolated_scripts",
     basic_suites = [
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json
index 2c32d4f..b5438eb 100644
--- a/infra/config/targets/lacros-version-skew-variants.json
+++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -17,16 +17,16 @@
   },
   "LACROS_VERSION_SKEW_DEV": {
     "args": [
-      "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome"
+      "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome"
     ],
-    "description": "Run with ash-chrome version 123.0.6312.11",
+    "description": "Run with ash-chrome version 123.0.6312.18",
     "identifier": "Lacros version skew testing ash dev",
     "swarming": {
       "cipd_packages": [
         {
           "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-          "location": "lacros_version_skew_tests_v123.0.6312.11",
-          "revision": "version:123.0.6312.11"
+          "location": "lacros_version_skew_tests_v123.0.6312.18",
+          "revision": "version:123.0.6312.18"
         }
       ]
     }
diff --git a/infra/config/targets/mixins.star b/infra/config/targets/mixins.star
index 239bc2b2..d2cb8de 100644
--- a/infra/config/targets/mixins.star
+++ b/infra/config/targets/mixins.star
@@ -296,15 +296,6 @@
 )
 
 targets.mixin(
-    name = "chrome-refresh-2023",
-    args = [
-        # All features to be launched under CR2023.
-        # See go/chrome-cr2023-testing-on-bots
-        "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh",
-    ],
-)
-
-targets.mixin(
     name = "chrome-swarming-pool",
     swarming = targets.swarming(
         dimensions = {
diff --git a/infra/config/targets/tests.star b/infra/config/targets/tests.star
index 255447f..d80d73e 100644
--- a/infra/config/targets/tests.star
+++ b/infra/config/targets/tests.star
@@ -733,56 +733,6 @@
 )
 
 targets.tests.gtest_test(
-    name = "cr23_browser_tests",
-    mixins = [
-        "chrome-refresh-2023",
-    ],
-    binary = "browser_tests",
-)
-
-targets.tests.gtest_test(
-    name = "cr23_interactive_ui_tests",
-    mixins = [
-        "chrome-refresh-2023",
-    ],
-    binary = "interactive_ui_tests",
-)
-
-targets.tests.gtest_test(
-    name = "cr23_pixel_browser_tests",
-    mixins = [
-        "skia_gold_test",
-        "chrome-refresh-2023",
-    ],
-    args = [
-        "--browser-ui-tests-verify-pixels",
-        "--enable-pixel-output-in-tests",
-    ],
-    binary = "browser_tests",
-)
-
-targets.tests.gtest_test(
-    name = "cr23_pixel_interactive_ui_tests",
-    mixins = [
-        "skia_gold_test",
-        "chrome-refresh-2023",
-    ],
-    args = [
-        "--browser-ui-tests-verify-pixels",
-        "--enable-pixel-output-in-tests",
-    ],
-    binary = "interactive_ui_tests",
-)
-
-targets.tests.gtest_test(
-    name = "cr23_views_unittests",
-    mixins = [
-        "chrome-refresh-2023",
-    ],
-    binary = "views_unittests",
-)
-
-targets.tests.gtest_test(
     name = "crashpad_tests",
 )
 
diff --git a/internal b/internal
index ee061f4..9f3d71f 160000
--- a/internal
+++ b/internal
@@ -1 +1 @@
-Subproject commit ee061f481382201645e2569b5cfb8bc70f5685ef
+Subproject commit 9f3d71f2b078ed96b1334c3921e47d2a2735a9c5
diff --git a/ios/components/security_interstitials/DEPS b/ios/components/security_interstitials/DEPS
index 86229b8..7498868 100644
--- a/ios/components/security_interstitials/DEPS
+++ b/ios/components/security_interstitials/DEPS
@@ -6,6 +6,7 @@
   "+components/safe_browsing/core/common",
   "+components/safe_browsing/ios",
   "+components/security_interstitials/core",
+  "+components/sessions/core",
   "+components/sync_preferences",
   "+components/keyed_service/core",
   "+components/keyed_service/ios",
diff --git a/ios/components/security_interstitials/safe_browsing/BUILD.gn b/ios/components/security_interstitials/safe_browsing/BUILD.gn
index cccba60..d743685 100644
--- a/ios/components/security_interstitials/safe_browsing/BUILD.gn
+++ b/ios/components/security_interstitials/safe_browsing/BUILD.gn
@@ -41,6 +41,7 @@
     "//components/safe_browsing/ios/browser:allow_list",
     "//components/safe_browsing/ios/browser/password_protection",
     "//components/security_interstitials/core:unsafe_resource",
+    "//components/sessions:session_id",
     "//ios/components/cookie_util",
     "//ios/components/security_interstitials/safe_browsing:util",
     "//ios/net",
diff --git a/ios/components/security_interstitials/safe_browsing/fake_safe_browsing_service.mm b/ios/components/security_interstitials/safe_browsing/fake_safe_browsing_service.mm
index 495263a9..dc21973 100644
--- a/ios/components/security_interstitials/safe_browsing/fake_safe_browsing_service.mm
+++ b/ios/components/security_interstitials/safe_browsing/fake_safe_browsing_service.mm
@@ -44,7 +44,8 @@
             /*url_lookup_service_on_ui=*/nullptr,
             /*hash_realtime_service_on_ui=*/nullptr,
             safe_browsing::hash_realtime_utils::HashRealTimeSelection::kNone,
-            /*is_async_check=*/false) {}
+            /*is_async_check=*/false,
+            SessionID::InvalidValue()) {}
   ~FakeSafeBrowsingUrlCheckerImpl() override = default;
 
   // SafeBrowsingUrlCheckerImpl:
diff --git a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm
index 22f9edd..37ab0c54 100644
--- a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm
+++ b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm
@@ -17,6 +17,7 @@
 #import "components/safe_browsing/core/browser/url_checker_delegate.h"
 #import "components/safe_browsing/core/common/features.h"
 #import "components/safe_browsing/core/common/safebrowsing_constants.h"
+#import "components/sessions/core/session_id.h"
 #import "ios/components/cookie_util/cookie_util.h"
 #import "ios/components/security_interstitials/safe_browsing/safe_browsing_client.h"
 #import "ios/components/security_interstitials/safe_browsing/url_checker_delegate_impl.h"
@@ -176,12 +177,11 @@
       security_interstitials::UnsafeResource::kNoFrameTreeNodeId,
       /*navigation_id=*/std::nullopt, can_perform_full_url_lookup,
       /*can_check_db=*/true, /*can_check_high_confidence_allowlist=*/true,
-      /*url_lookup_service_metric_suffix=*/"",
-      web::GetUIThreadTaskRunner({}),
+      /*url_lookup_service_metric_suffix=*/"", web::GetUIThreadTaskRunner({}),
       url_lookup_service ? url_lookup_service->GetWeakPtr() : nullptr,
       hash_real_time_service ? hash_real_time_service->GetWeakPtr() : nullptr,
       hash_real_time_selection,
-      /*is_async_check=*/false);
+      /*is_async_check=*/false, SessionID::InvalidValue());
 }
 
 bool SafeBrowsingServiceImpl::CanCheckUrl(const GURL& url) const {
diff --git a/media/audio/audio_output_device_unittest.cc b/media/audio/audio_output_device_unittest.cc
index 11ed572..3fb0e0e1 100644
--- a/media/audio/audio_output_device_unittest.cc
+++ b/media/audio/audio_output_device_unittest.cc
@@ -293,22 +293,29 @@
   StopAudioDevice();
 }
 
-// TODO(crbug.com/327577325) Re-enable this test
-TEST_F(AudioOutputDeviceTest, DISABLED_ErrorFiredForSocketClose) {
+TEST_F(AudioOutputDeviceTest, ErrorFiredForSocketClose) {
   StartAudioDevice();
   CallOnStreamCreated();
 
+  // Lock used to ensure Render() completes before CloseBrowserSocket() starts.
+  base::Lock send_lock_;
+
   base::RunLoop run_loop;
   EXPECT_CALL(callback_, Render(_, _, _, _))
-      .WillOnce(DoAll(base::test::RunClosure(base::BindLambdaForTesting(
-                          [&]() { CloseBrowserSocket(); })),
+      .WillOnce(DoAll(base::test::RunClosure(base::BindLambdaForTesting([&]() {
+                        base::AutoLock lock(send_lock_);
+                        CloseBrowserSocket();
+                      })),
                       Return(0)))
       .WillRepeatedly(Return(0));
 
   EXPECT_CALL(callback_, OnRenderError())
       .WillOnce(base::test::RunClosure(run_loop.QuitWhenIdleClosure()));
 
-  Render();
+  {
+    base::AutoLock lock(send_lock_);
+    Render();
+  }
   run_loop.Run();
 
   StopAudioDevice();
diff --git a/printing/test_printing_context.cc b/printing/test_printing_context.cc
index 2b6202d..0d09e99 100644
--- a/printing/test_printing_context.cc
+++ b/printing/test_printing_context.cc
@@ -160,7 +160,22 @@
   std::unique_ptr<PrintSettings> existing_settings = std::move(settings_);
   settings_ = std::make_unique<PrintSettings>(*found->second);
   settings_->set_copies(existing_settings->copies());
-  settings_->set_dpi(existing_settings->dpi());
+  // Client-supplied settings take priority over default device settings; try to
+  // transfer the non-empty ones.
+  if (existing_settings->color() != mojom::ColorModel::kUnknownColorModel) {
+    settings_->set_color(existing_settings->color());
+  }
+  settings_->set_collate(existing_settings->collate());
+  if (!existing_settings->dpi_size().IsEmpty()) {
+    settings_->set_dpi_xy(existing_settings->dpi_horizontal(),
+                          existing_settings->dpi_vertical());
+  }
+  if (!existing_settings->title().empty()) {
+    settings_->set_title(existing_settings->title());
+  }
+  if (!existing_settings->requested_media().IsDefault()) {
+    settings_->set_requested_media(existing_settings->requested_media());
+  }
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
   for (const auto& item : existing_settings->advanced_settings())
     settings_->advanced_settings().emplace(item.first, item.second.Clone());
diff --git a/testing/buildbot/chromium.cft.json b/testing/buildbot/chromium.cft.json
index 3b5d2bec..b44cdcf 100644
--- a/testing/buildbot/chromium.cft.json
+++ b/testing/buildbot/chromium.cft.json
@@ -5834,34 +5834,6 @@
         "test_id_prefix": "ninja://courgette:courgette_unittests/"
       },
       {
-        "args": [
-          "--browser-ui-tests-verify-pixels",
-          "--enable-pixel-output-in-tests",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter",
-          "--git-revision=${got_revision}",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_pixel_interactive_ui_tests",
-        "precommit_args": [
-          "--gerrit-issue=${patch_issue}",
-          "--gerrit-patchset=${patch_set}",
-          "--buildbucket-id=${buildbucket_build_id}"
-        ],
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Windows-10-19045"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "interactive_ui_tests",
-        "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
-      },
-      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 66e1909..c4e041c 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5407,9 +5407,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5419,8 +5419,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
@@ -5563,9 +5563,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5575,8 +5575,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index 3d0db5c..04cba4c 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -8329,7 +8329,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 20
+          "shards": 32
         },
         "test": "browser_tests",
         "test_id_prefix": "ninja://chrome/test:browser_tests/"
@@ -20342,9 +20342,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20354,8 +20354,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
@@ -20492,9 +20492,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20504,8 +20504,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index e8dc81a..e8fc9c2 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -40010,9 +40010,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -40021,8 +40021,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
@@ -40160,9 +40160,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -40171,8 +40171,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
@@ -41510,9 +41510,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -41522,8 +41522,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
@@ -41666,9 +41666,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -41678,8 +41678,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
@@ -42990,9 +42990,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43001,8 +43001,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
@@ -43140,9 +43140,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43151,8 +43151,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
@@ -49067,68 +49067,6 @@
         "test_id_prefix": "ninja://courgette:courgette_unittests/"
       },
       {
-        "args": [
-          "--browser-ui-tests-verify-pixels",
-          "--enable-pixel-output-in-tests",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter",
-          "--test-launcher-jobs=1",
-          "--git-revision=${got_revision}",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_pixel_browser_tests",
-        "precommit_args": [
-          "--gerrit-issue=${patch_issue}",
-          "--gerrit-patchset=${patch_set}",
-          "--buildbucket-id=${buildbucket_build_id}"
-        ],
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Windows-10-19045",
-            "pool": "chromium.tests.no-external-ip"
-          },
-          "expiration": 43200,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 3
-        },
-        "test": "browser_tests",
-        "test_id_prefix": "ninja://chrome/test:browser_tests/"
-      },
-      {
-        "args": [
-          "--browser-ui-tests-verify-pixels",
-          "--enable-pixel-output-in-tests",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter",
-          "--git-revision=${got_revision}",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_pixel_interactive_ui_tests",
-        "precommit_args": [
-          "--gerrit-issue=${patch_issue}",
-          "--gerrit-patchset=${patch_set}",
-          "--buildbucket-id=${buildbucket_build_id}"
-        ],
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Windows-10-19045",
-            "pool": "chromium.tests.no-external-ip"
-          },
-          "expiration": 43200,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "interactive_ui_tests",
-        "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
-      },
-      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 7142a85..9e63977 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -1261,67 +1261,6 @@
         "test_id_prefix": "ninja://content/test:content_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "ci_only": true,
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_browser_tests",
-        "swarming": {
-          "dimensions": {
-            "os": "Ubuntu-22.04"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 20
-        },
-        "test": "browser_tests",
-        "test_id_prefix": "ninja://chrome/test:browser_tests/"
-      },
-      {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "ci_only": true,
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_interactive_ui_tests",
-        "swarming": {
-          "dimensions": {
-            "os": "Ubuntu-22.04"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "interactive_ui_tests",
-        "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
-      },
-      {
-        "args": [
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "ci_only": true,
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_views_unittests",
-        "swarming": {
-          "dimensions": {
-            "os": "Ubuntu-22.04"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "views_unittests",
-        "test_id_prefix": "ninja://ui/views:views_unittests/"
-      },
-      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 603c20c6..78cbab9b 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -5120,70 +5120,6 @@
         "test_id_prefix": "ninja://content/test:content_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "ci_only": true,
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_browser_tests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Mac-13"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 20
-        },
-        "test": "browser_tests",
-        "test_id_prefix": "ninja://chrome/test:browser_tests/"
-      },
-      {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "ci_only": true,
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_interactive_ui_tests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Mac-13"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "interactive_ui_tests",
-        "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
-      },
-      {
-        "args": [
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "ci_only": true,
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_views_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Mac-13"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "views_unittests",
-        "test_id_prefix": "ninja://ui/views:views_unittests/"
-      },
-      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5687,6 +5623,22 @@
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "name": "openscreen_unittests",
+        "swarming": {
+          "dimensions": {
+            "cpu": "x86-64",
+            "os": "Mac-13"
+          },
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "openscreen_unittests",
+        "test_id_prefix": "ninja://chrome/browser/media/router:openscreen_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
         "name": "pdf_unittests",
         "swarming": {
           "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 8d80c96..5cb05e5 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -16376,12 +16376,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16391,8 +16391,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
@@ -16552,12 +16552,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 123.0.6312.11",
+        "description": "Run with ash-chrome version 123.0.6312.18",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16567,8 +16567,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v123.0.6312.11",
-              "revision": "version:123.0.6312.11"
+              "location": "lacros_version_skew_tests_v123.0.6312.18",
+              "revision": "version:123.0.6312.18"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 046e08a..a3e90d086 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -577,128 +577,6 @@
         "test_id_prefix": "ninja://courgette:courgette_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "ci_only": true,
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_browser_tests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Windows-10-19045"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 20
-        },
-        "test": "browser_tests",
-        "test_id_prefix": "ninja://chrome/test:browser_tests/"
-      },
-      {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "ci_only": true,
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_interactive_ui_tests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Windows-10-19045"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "interactive_ui_tests",
-        "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
-      },
-      {
-        "args": [
-          "--browser-ui-tests-verify-pixels",
-          "--enable-pixel-output-in-tests",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter",
-          "--test-launcher-jobs=1",
-          "--git-revision=${got_revision}",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_pixel_browser_tests",
-        "precommit_args": [
-          "--gerrit-issue=${patch_issue}",
-          "--gerrit-patchset=${patch_set}",
-          "--buildbucket-id=${buildbucket_build_id}"
-        ],
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Windows-10-19045"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 3
-        },
-        "test": "browser_tests",
-        "test_id_prefix": "ninja://chrome/test:browser_tests/"
-      },
-      {
-        "args": [
-          "--browser-ui-tests-verify-pixels",
-          "--enable-pixel-output-in-tests",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter",
-          "--git-revision=${got_revision}",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_pixel_interactive_ui_tests",
-        "precommit_args": [
-          "--gerrit-issue=${patch_issue}",
-          "--gerrit-patchset=${patch_set}",
-          "--buildbucket-id=${buildbucket_build_id}"
-        ],
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Windows-10-19045"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "interactive_ui_tests",
-        "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
-      },
-      {
-        "args": [
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "ci_only": true,
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_views_unittests",
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Windows-10-19045"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "views_unittests",
-        "test_id_prefix": "ninja://ui/views:views_unittests/"
-      },
-      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4364,34 +4242,6 @@
         "test_id_prefix": "ninja://courgette:courgette_unittests/"
       },
       {
-        "args": [
-          "--browser-ui-tests-verify-pixels",
-          "--enable-pixel-output-in-tests",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter",
-          "--git-revision=${got_revision}",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_pixel_interactive_ui_tests",
-        "precommit_args": [
-          "--gerrit-issue=${patch_issue}",
-          "--gerrit-patchset=${patch_set}",
-          "--buildbucket-id=${buildbucket_build_id}"
-        ],
-        "swarming": {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Windows-11-22000"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "interactive_ui_tests",
-        "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
-      },
-      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -8041,34 +7891,6 @@
         "test_id_prefix": "ninja://courgette:courgette_unittests/"
       },
       {
-        "args": [
-          "--browser-ui-tests-verify-pixels",
-          "--enable-pixel-output-in-tests",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter",
-          "--git-revision=${got_revision}",
-          "--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh"
-        ],
-        "merge": {
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "cr23_pixel_interactive_ui_tests",
-        "precommit_args": [
-          "--gerrit-issue=${patch_issue}",
-          "--gerrit-patchset=${patch_set}",
-          "--buildbucket-id=${buildbucket_build_id}"
-        ],
-        "swarming": {
-          "dimensions": {
-            "cpu": "arm64",
-            "os": "Windows-11",
-            "screen_scaling_percent": "100"
-          },
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "interactive_ui_tests",
-        "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
-      },
-      {
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index 1df98acb..b723b35 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -56,12 +56,6 @@
   data = [ "//testing/buildbot/filters/cft.blink_web_tests.filter" ]
 }
 
-source_set("cr23_pixel_browser_tests_filters") {
-  testonly = true
-
-  data = [ "//testing/buildbot/filters/win.win-rel-cft.cr23_pixel_browser_tests.filter" ]
-}
-
 source_set("browser_tests_filters") {
   testonly = true
 
@@ -71,9 +65,6 @@
     "//testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter",
     "//testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter",
     "//testing/buildbot/filters/code_coverage.browser_tests.filter",
-    "//testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter",
-    "//testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter",
-    "//testing/buildbot/filters/cr23.win.cr23_browser_tests.filter",
     "//testing/buildbot/filters/fuchsia.browser_tests.filter",
     "//testing/buildbot/filters/linux-chromeos.browser_tests.pixel_tests.filter",
     "//testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter",
@@ -349,9 +340,6 @@
 
   data = [
     "//testing/buildbot/filters/accessibility-linux.interactive_ui_tests.filter",
-    "//testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter",
-    "//testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter",
-    "//testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter",
     "//testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
     "//testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
     "//testing/buildbot/filters/linux.linux-rel-cft.interactive_ui_tests.filter",
diff --git a/testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter b/testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter
deleted file mode 100644
index 0009af06..0000000
--- a/testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter
+++ /dev/null
@@ -1 +0,0 @@
-# cr23_browser_tests that are expected to fail on linux bots:
diff --git a/testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter b/testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter
deleted file mode 100644
index 89b6c43..0000000
--- a/testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter
+++ /dev/null
@@ -1,5 +0,0 @@
-# cr23_interactive_ui_tests that are expected to fail on linux bots:
--PermissionsFlowInteractiveUITest.CameraActivityIndicatorTest
--PermissionsFlowInteractiveUITest.CameraAndMicrophoneActivityIndicatorTest
--PermissionsFlowInteractiveUITest.MicrophoneActivityIndicatorTest
--PriceTrackingIconViewInteractiveTest.EnablePriceTrackOnPress
diff --git a/testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter b/testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter
deleted file mode 100644
index 9951351..0000000
--- a/testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter
+++ /dev/null
@@ -1 +0,0 @@
-# cr23_browser_tests that are expected to fail on mac bots:
diff --git a/testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter b/testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter
deleted file mode 100644
index 765cb5f..0000000
--- a/testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter
+++ /dev/null
@@ -1,8 +0,0 @@
-# cr23_interactive_ui_tests that are expected to fail on mac bots:
--PermissionsFlowInteractiveUITest.CameraActivityIndicatorTest
--PermissionsFlowInteractiveUITest.CameraAndMicrophoneActivityIndicatorTest
--PermissionsFlowInteractiveUITest.MicrophoneActivityIndicatorTest
--PriceTrackingIconViewInteractiveTest.EnablePriceTrackOnPress
-
-# This may be a flaky failure unrelated to the cr23 code paths.
--SitePerProcessInteractivePDFTest.ContextMenuPositionForEmbeddedPDFInCrossOriginFrame
diff --git a/testing/buildbot/filters/cr23.win.cr23_browser_tests.filter b/testing/buildbot/filters/cr23.win.cr23_browser_tests.filter
deleted file mode 100644
index 4607693..0000000
--- a/testing/buildbot/filters/cr23.win.cr23_browser_tests.filter
+++ /dev/null
@@ -1 +0,0 @@
-# cr23_browser_tests that are expected to fail on win bots:
diff --git a/testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter b/testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter
deleted file mode 100644
index 4a9ea9d..0000000
--- a/testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter
+++ /dev/null
@@ -1,5 +0,0 @@
-# cr2023_interactive_ui_tests that are expected to fail on win bots:
--PermissionsFlowInteractiveUITest.CameraActivityIndicatorTest
--PermissionsFlowInteractiveUITest.CameraAndMicrophoneActivityIndicatorTest
--PermissionsFlowInteractiveUITest.MicrophoneActivityIndicatorTest
--PriceTrackingIconViewInteractiveTest.EnablePriceTrackOnPress
diff --git a/testing/buildbot/filters/win.win-rel-cft.cr23_pixel_browser_tests.filter b/testing/buildbot/filters/win.win-rel-cft.cr23_pixel_browser_tests.filter
deleted file mode 100644
index 7685f8f..0000000
--- a/testing/buildbot/filters/win.win-rel-cft.cr23_pixel_browser_tests.filter
+++ /dev/null
@@ -1,9 +0,0 @@
-# https://ci.chromium.org/ui/p/chromium/builders/try/win-rel-cft/185
--All/PasswordGenerationPopupViewBrowsertest.*
--All/PopupViewViewsBrowsertest*
--InfoBarUiTest.*
--InteractionTestUtilBrowserTest.CompareScreenshot_WebPage
-
-# https://ci.chromium.org/ui/p/chromium/builders/ci/win-rel-cft/3427/
--PageInfoBubbleViewCookiesSubpageBrowserTest.*
--PageInfoBubbleViewDialogBrowserTest.*
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 5c1b91b..220ad86 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -247,11 +247,6 @@
       },
     },
   },
-  'chrome-refresh-2023': {
-    'args': [
-      '--enable-features=ChromeRefresh2023,ChromeRefreshSecondary2023,ChromeWebuiRefresh2023,Cr2023ActionChips,Cr2023ActionChipsIcons,kOmniboxCR23SteadyStateIcons,OmniboxExpandedLayout,OmniboxExpandedStateColors,OmniboxExpandedStateHeight,OmniboxExpandedStateShape,OmniboxExpandedStateSuggestIcons,OmniboxSteadyStateBackgroundColor,OmniboxSteadyStateHeight,OmniboxSteadyStateTextColor,OmniboxSuggestionHoverFillShape,IPH_DesktopCustomizeChromeRefresh',
-    ],
-  },
   'chrome-swarming-pool': {
     'swarming': {
       'dimensions': {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 281d0c6..622e241 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -2366,25 +2366,6 @@
       'Android FYI Release (Pixel 2)',
     ],
   },
-  'cr23_pixel_browser_tests': {
-    # This target should be removed from any CI only builders. Developers can
-    # intentionally make UI changes. Without running pixel tests on CQ, those
-    # cls will get wrongly reverted by sheriffs.
-    # When we switch CQ builders(e.g. use Win11 to replace Win10), we also
-    # need to update this field.
-    'remove_from': [
-      'Win11 Tests x64',
-      'win-rel-cft',
-      'win11-arm64-rel-tests',
-    ],
-    'modifications': {
-      'win-rel-cft': {
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/win.win-rel-cft.cr23_pixel_browser_tests.filter',
-        ],
-      },
-    },
-  },
   'crashpad_tests': {
     'remove_from': [
       'linux-win_cross-rel', # https://crbug.com/762167
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 1856283..60cf421 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -621,7 +621,7 @@
       'chromeos_js_code_coverage_browser_tests': {
         'test': 'browser_tests',
         'swarming': {
-          'shards': 20,
+          'shards': 32,
         },
       },
     },
@@ -1718,145 +1718,6 @@
       },
     },
 
-    'cr23_linux_gtests': {
-      'cr23_browser_tests': {
-        'test': 'browser_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 20,
-        },
-      },
-      'cr23_interactive_ui_tests': {
-        'test': 'interactive_ui_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 10,
-        },
-      },
-      'cr23_views_unittests': {
-        'test': 'views_unittests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'ci_only': True,
-      },
-    },
-
-    'cr23_mac_gtests': {
-      'cr23_browser_tests': {
-        'test': 'browser_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 20,
-        },
-      },
-      'cr23_interactive_ui_tests': {
-        'test': 'interactive_ui_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 10,
-        },
-      },
-      'cr23_views_unittests': {
-        'test': 'views_unittests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'ci_only': True,
-      },
-    },
-
-    'cr23_pixel_browser_tests_gtests': {
-      'cr23_pixel_browser_tests': {
-        'test': 'browser_tests',
-        'mixins': [
-          'skia_gold_test',
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--browser-ui-tests-verify-pixels',
-          '--enable-pixel-output-in-tests',
-          '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter',
-          '--test-launcher-jobs=1',
-        ],
-        'swarming': {
-          'shards': 3,
-        },
-      },
-      'cr23_pixel_interactive_ui_tests': {
-        'test': 'interactive_ui_tests',
-        'mixins': [
-          'skia_gold_test',
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--browser-ui-tests-verify-pixels',
-          '--enable-pixel-output-in-tests',
-          '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter',
-        ],
-      },
-    },
-
-    'cr23_win_gtests': {
-      'cr23_browser_tests': {
-        'test': 'browser_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 20,
-        },
-      },
-      'cr23_interactive_ui_tests': {
-        'test': 'interactive_ui_tests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter',
-        ],
-        'ci_only': True,
-        'swarming': {
-          'shards': 10,
-        },
-      },
-      'cr23_views_unittests': {
-        'test': 'views_unittests',
-        'mixins': [
-          'chrome-refresh-2023',
-        ],
-        'ci_only': True,
-      },
-    },
-
     'cronet_gtests': {
       'cronet_sample_test_apk': {},
       'cronet_smoketests_apk': {},
@@ -6051,22 +5912,6 @@
       'vr_platform_specific_chromium_gtests',
     ],
 
-    'chromium_linux_gtests_once': [
-      'aura_gtests',
-      'chromium_gtests',
-      'chromium_gtests_for_devices_with_graphical_output',
-      'chromium_gtests_for_linux_and_chromeos_only',
-      'chromium_gtests_for_linux_and_mac_only',
-      'chromium_gtests_for_linux_only',
-      'chromium_gtests_for_win_and_linux_only',
-      'cr23_linux_gtests',
-      'linux_flavor_specific_chromium_gtests',
-      'linux_specific_xr_gtests',
-      'non_android_and_cast_and_chromeos_chromium_gtests',
-      'non_android_chromium_gtests_no_nacl',
-      'vr_platform_specific_chromium_gtests',
-    ],
-
     'chromium_linux_rel_isolated_scripts': [
       'chromedriver_py_tests_isolated_scripts',
       'chromium_web_tests_high_dpi_isolated_scripts',
@@ -6121,15 +5966,6 @@
       'non_android_chromium_gtests_no_nacl',
     ],
 
-    'chromium_mac_gtests_no_nacl_once': [
-      'chromium_gtests',
-      'chromium_gtests_for_devices_with_graphical_output',
-      'cr23_mac_gtests',
-      'mac_specific_chromium_gtests',
-      'non_android_and_cast_and_chromeos_chromium_gtests',
-      'non_android_chromium_gtests_no_nacl',
-    ],
-
     'chromium_mac_rel_isolated_scripts': [
       'chromedriver_py_tests_isolated_scripts',
       'components_perftests_isolated_scripts',
@@ -6167,7 +6003,6 @@
       'chromium_gtests',
       'chromium_gtests_for_devices_with_graphical_output',
       'chromium_gtests_for_win_and_linux_only',
-      'cr23_pixel_browser_tests_gtests',
       'fieldtrial_browser_tests',
       'non_android_and_cast_and_chromeos_chromium_gtests',
       'non_android_chromium_gtests_no_nacl',
@@ -6181,22 +6016,6 @@
       'chromium_gtests_for_windows_multiscreen',
     ],
 
-    'chromium_win10_gtests_once': [
-      'aura_gtests',
-      'chromium_gtests',
-      'chromium_gtests_for_devices_with_graphical_output',
-      'chromium_gtests_for_win_and_linux_only',
-      'cr23_pixel_browser_tests_gtests',
-      'cr23_win_gtests',
-      'fieldtrial_browser_tests',
-      'non_android_and_cast_and_chromeos_chromium_gtests',
-      'non_android_chromium_gtests_no_nacl',
-      'non_android_chromium_gtests_skia_gold',
-      'pixel_browser_tests_gtests',
-      'vr_platform_specific_chromium_gtests',
-      'win_specific_chromium_gtests',
-    ],
-
     'chromium_win_dbg_isolated_scripts': [
       'chromedriver_py_tests_isolated_scripts',
       'components_perftests_isolated_scripts',
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index b216ae7..8f96eb02 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -323,16 +323,16 @@
   },
   'LACROS_VERSION_SKEW_DEV': {
     'identifier': 'Lacros version skew testing ash dev',
-    'description': 'Run with ash-chrome version 123.0.6312.11',
+    'description': 'Run with ash-chrome version 123.0.6312.18',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.11/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6312.18/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v123.0.6312.11',
-          'revision': 'version:123.0.6312.11',
+          'location': 'lacros_version_skew_tests_v123.0.6312.18',
+          'revision': 'version:123.0.6312.18',
         },
       ],
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 3b5a303..c0d2f53 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -4754,10 +4754,7 @@
           'linux-jammy',
         ],
         'test_suites': {
-          # TODO(crbug.com/1444855): Switch this back to
-          # 'chromium_linux_gtests' after the ChromeRefresh2023
-          # is fully rolled out.
-          'gtest_tests': 'chromium_linux_gtests_once',
+          'gtest_tests': 'chromium_linux_gtests',
           'isolated_scripts': 'chromium_linux_rel_isolated_scripts_once',
         },
       },
@@ -4877,10 +4874,7 @@
             'isolate_profile_data',
         ],
         'test_suites': {
-          # TODO(crbug.com/1444855): Switch this back to
-          # 'chromium_mac_gtests_no_nacl' after the ChromeRefresh2023 is fully
-          # rolled out.
-          'gtest_tests': 'chromium_mac_gtests_no_nacl_once',
+          'gtest_tests': 'chromium_mac_gtests_no_nacl',
           'isolated_scripts': 'chromium_mac_rel_isolated_scripts_once',
         },
       },
@@ -6127,10 +6121,7 @@
           'isolate_profile_data',
         ],
         'test_suites': {
-          # TODO(crbug.com/1444855): Switch this back to
-          # 'chromium_win10_gtests' after the
-          # ChromeRefresh2023 is fully rolled out.
-          'gtest_tests': 'chromium_win10_gtests_once',
+          'gtest_tests': 'chromium_win10_gtests',
           'isolated_scripts': 'chromium_win_rel_isolated_scripts_once',
         },
       },
diff --git a/testing/libfuzzer/reproducing.md b/testing/libfuzzer/reproducing.md
index c9bc1e4..34436ea 100644
--- a/testing/libfuzzer/reproducing.md
+++ b/testing/libfuzzer/reproducing.md
@@ -46,7 +46,7 @@
    ClusterFuzz:
 
 ```
-export ASAN_OPTIONS=redzone=256:print_summary=1:handle_sigill=1:allocator_release_to_os_interval_ms=500:print_suppressions=0:strict_memcmp=1:allow_user_segv_handler=0:use_sigaltstack=1:handle_sigfpe=1:handle_sigbus=1:detect_stack_use_after_return=0:alloc_dealloc_mismatch=0:detect_leaks=0:print_scariness=1:allocator_may_return_null=1:handle_abort=1:check_malloc_usable_size=0:detect_container_overflow=0:quarantine_size_mb=256:detect_odr_violation=0:symbolize=1:handle_segv=1:fast_unwind_on_fatal=1
+export ASAN_OPTIONS=redzone=256:print_summary=1:handle_sigill=1:allocator_release_to_os_interval_ms=500:print_suppressions=0:strict_memcmp=1:allow_user_segv_handler=0:use_sigaltstack=1:handle_sigfpe=1:handle_sigbus=1:detect_stack_use_after_return=0:alloc_dealloc_mismatch=0:detect_leaks=0:print_scariness=1:allocator_may_return_null=1:handle_abort=1:check_malloc_usable_size=0:detect_container_overflow=0:quarantine_size_mb=256:detect_odr_violation=0:symbolize=1:handle_segv=1:fast_unwind_on_fatal=0
 ```
 
 5. Run the fuzz target:
diff --git a/third_party/angle b/third_party/angle
index 69f5e9ca..1ceddbf 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit 69f5e9ca60cd6adfecd9eb8c969beeec30a4813d
+Subproject commit 1ceddbf6977926d674c0c5a78b398f684d0052b1
diff --git a/third_party/blink/perf_tests/accessibility/location-changes-css-animation.html b/third_party/blink/perf_tests/accessibility/location-changes-css-animation.html
new file mode 100644
index 0000000..1797f4e
--- /dev/null
+++ b/third_party/blink/perf_tests/accessibility/location-changes-css-animation.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../resources/runner.js"></script>
+
+<style>
+  .root {
+      width: 100%;
+      padding: 5px;
+      position: absolute;
+      transform: translate(0,0);
+      transition: transform 2s;
+  }
+  .child {
+      border: 1px solid black;
+      height: 10px;
+      width: 10px;
+      margin: -1px;
+      display: inline-block;
+  }
+
+  #root1.end {
+    transform: translateX(500px);
+  }
+
+  #root2.end {
+    transform: translateY(500px);
+  }
+</style>
+
+<div id="container"></div>
+
+<script>
+let isDone = false;
+let startTime;
+
+function runTest() {
+  if (startTime) {
+    PerfTestRunner.measureValueAsync(PerfTestRunner.now() - startTime);
+    PerfTestRunner.addRunTestEndMarker();
+  }
+
+  if (!document.querySelector('#root1')) {
+    generateAllContent();
+  }
+
+  if (!isDone) {
+    PerfTestRunner.addRunTestStartMarker();
+    startTime = PerfTestRunner.now();
+
+    setTimeout(animateRoots, 0);
+    setTimeout(runTest, 2500);
+  }
+}
+
+function animateRoots() {
+  document.querySelector('#root1').classList.toggle('end');
+  document.querySelector('#root2').classList.toggle('end');
+}
+
+function generateAllContent() {
+  const root1 = container.appendChild(document.createElement('div'));
+  root1.id = 'root1';
+  root1.className = 'root';
+
+  const root2 = container.appendChild(document.createElement('div'));
+  root2.id = 'root2';
+  root2.className = 'root';
+
+  for (let i = 0; i < 17; i++) {
+    const child1 = generateNodes(100, "blue");
+    root1.appendChild(child1);
+    const child2 = generateNodes(100, "green");
+    root2.appendChild(child2);
+  }
+}
+
+// Recursively add layers of descendants.
+function generateNodes(depth, color) {
+  if (depth === 0)
+    return;
+
+  const node = document.createElement("div");
+  node.className = "child";
+  node.style.backgroundColor = color;
+  node.setAttribute("tabindex", 0);
+  depth--;
+  const child = generateNodes(depth, color);
+  if(child) {
+    node.appendChild(child);
+  }
+  return node;
+}
+
+PerfTestRunner.startMeasureValuesAsync({
+    description: 'Test accessibility performance when animating many nodes',
+    unit: 'ms',
+    done: function () {
+        isDone = true;
+    },
+    run: function() {
+        runTest();
+    },
+    iterationCount: 6,
+    tracingCategories: 'accessibility',
+    traceEventsToMeasure: [
+        'BrowserAccessibilityManager::OnAccessibilityEvents',
+        'ProcessDeferredAccessibilityEvents',
+        'RenderAccessibilityImpl::SendPendingAccessibilityEvents',
+    ]
+});
+</script>
+
+</html>
diff --git a/third_party/blink/perf_tests/accessibility/location-changes-js-animation.html b/third_party/blink/perf_tests/accessibility/location-changes-js-animation.html
new file mode 100644
index 0000000..b972719
--- /dev/null
+++ b/third_party/blink/perf_tests/accessibility/location-changes-js-animation.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../resources/runner.js"></script>
+
+<style>
+  .root {
+      width: 100%;
+      padding: 5px;
+      position: absolute;
+  }
+  .child {
+      border: 1px solid black;
+      height: 10px;
+      width: 10px;
+      margin: -1px;
+      display: inline-block;
+  }
+</style>
+
+<div id="container"></div>
+
+<script>
+let isDone = false;
+let startTime;
+let animateTimes;
+
+function runTest() {
+  if (startTime) {
+    PerfTestRunner.measureValueAsync(PerfTestRunner.now() - startTime);
+    PerfTestRunner.addRunTestEndMarker();
+  }
+  if (!isDone) {
+    PerfTestRunner.addRunTestStartMarker();
+    startTime = PerfTestRunner.now();
+
+    container.innerHTML = '';
+
+    generateAllContent();
+
+    animateTimes = 0;
+    animateRoots();
+    setTimeout(runTest, 2500);
+  }
+}
+
+function animateRoots() {
+  if (++ animateTimes < 500) {
+    document.querySelector('#root1').style.top = animateTimes +'px';
+    document.querySelector('#root2').style.left = animateTimes +'px';
+    requestAnimationFrame(animateRoots);
+  }
+}
+
+function generateAllContent() {
+  const root1 = container.appendChild(document.createElement('div'));
+  root1.id = 'root1';
+  root1.className = 'root';
+
+  const root2 = container.appendChild(document.createElement('div'));
+  root2.id = 'root2';
+  root2.className = 'root';
+
+  for (let i = 0; i < 17; i++) {
+    const child1 = generateNodes(100, "blue");
+    root1.appendChild(child1);
+    const child2 = generateNodes(100, "green");
+    root2.appendChild(child2);
+  }
+}
+
+// Recursively add layers of descendants.
+function generateNodes(depth, color) {
+  if (depth === 0)
+    return;
+
+  const node = document.createElement("div");
+  node.className = "child";
+  node.style.backgroundColor = color;
+  node.setAttribute("tabindex", 0);
+  depth--;
+  const child = generateNodes(depth, color);
+  if(child) {
+    node.appendChild(child);
+  }
+  return node;
+}
+
+PerfTestRunner.startMeasureValuesAsync({
+    description: 'Test accessibility performance when animating many nodes',
+    unit: 'ms',
+    done: function () {
+        isDone = true;
+    },
+    run: function() {
+        runTest();
+    },
+    iterationCount: 6,
+    tracingCategories: 'accessibility',
+    traceEventsToMeasure: [
+        'BrowserAccessibilityManager::OnAccessibilityEvents',
+        'ProcessDeferredAccessibilityEvents',
+        'RenderAccessibilityImpl::SendPendingAccessibilityEvents',
+    ]
+});
+</script>
+
+</html>
diff --git a/third_party/blink/perf_tests/accessibility/location-changes-scrolling.html b/third_party/blink/perf_tests/accessibility/location-changes-scrolling.html
new file mode 100644
index 0000000..b2005498
--- /dev/null
+++ b/third_party/blink/perf_tests/accessibility/location-changes-scrolling.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../resources/runner.js"></script>
+
+<table id="testElement">
+  <tr>
+    <th>Sender</th>
+    <td>Message</td>
+  </tr>
+</table>
+
+<script>
+var isDone = false;
+var startTime;
+
+// Before the test starts, add 2000 rows to the table, something like a
+// message board with lots of replies on a long thread.
+
+let table = document.getElementById('testElement');
+for (let i = 0; i < 2000; i++) {
+    let tr = document.createElement('tr');
+    table.appendChild(tr);
+    let sender = document.createElement('td');
+    sender.innerHTML = 'user' + Math.floor(10000*Math.random());
+    tr.appendChild(sender);
+    let message = document.createElement('td');
+    message.innerHTML = '<div>Message content ' +
+        Math.floor(10000*Math.random()) + '</div>';
+    let link = document.createElement('a');
+    link.href = '#';
+    link.id = 'link' + i;
+    link.innerHTML = 'Reply';
+    message.appendChild(link);
+    tr.appendChild(message);
+}
+
+function runTest() {
+    if (startTime) {
+        PerfTestRunner.measureValueAsync(PerfTestRunner.now() - startTime);
+        PerfTestRunner.addRunTestEndMarker();
+    }
+    if (!isDone) {
+        PerfTestRunner.addRunTestStartMarker();
+        startTime = PerfTestRunner.now();
+
+        let scrollTimes = 0;
+
+        let scrollInProcess = false;
+        let scroll = () => {
+          if(scrollInProcess) return;
+          scrollInProcess = true;
+
+          if(scrollTimes == 5) {
+            return runTest();
+          }
+
+          requestAnimationFrame(() => {
+            scrollTimes ++;
+            window.scrollBy({
+              top: 600,
+              behavior: 'smooth'
+            });
+            document.addEventListener("scrollend", () => {
+              console.log("scrolling again!");
+              scrollInProcess = false;
+              setTimeout(scroll, 500);
+            }, { once: true });
+          });
+        };
+
+        scroll();
+      }
+    }
+
+PerfTestRunner.startMeasureValuesAsync({
+    description: 'Test accessibility performance when scrolling some divs',
+    unit: 'ms',
+    done: function () {
+        isDone = true;
+    },
+    run: function() {
+        runTest();
+    },
+    iterationCount: 6,
+    tracingCategories: 'accessibility',
+    traceEventsToMeasure: [
+        'BrowserAccessibilityManager::OnAccessibilityEvents',
+        'ProcessDeferredAccessibilityEvents',
+        'RenderAccessibilityImpl::SendPendingAccessibilityEvents',
+    ]
+});
+</script>
+
+</html>
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom
index 1653899..8dd981e7 100644
--- a/third_party/blink/public/mojom/frame/frame.mojom
+++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -1088,17 +1088,17 @@
   // Requests a one-time snapshot of the document state for a ViewTransition.
   // See https://drafts.csswg.org/css-view-transitions-1/ for details.
   SnapshotDocumentForViewTransition(
-    PageConcealEventParams page_conceal_event_params) => (
+    PageSwapEventParams page_swap_event_params) => (
       blink.mojom.ViewTransitionState view_transition_state);
 
-  // Dispatches a `pageconceal` event on the previous Document before the
+  // Dispatches a `pageswap` event on the previous Document before the
   // navigation is committed. This API is used for navigations which don't have
   // a ViewTransition.
   // For ViewTransition the event must be dispatched before snapshotting the old
   // Document with a `ViewTransition` object passed to script. So the dispatch
   // is done as a part of the `SnapshotDocumentForViewTransition` API above.
-  DispatchPageConceal(
-    PageConcealEventParams? page_conceal_event_params);
+  DispatchPageSwap(
+    PageSwapEventParams? page_swap_event_params);
 
   // Allows the browser to add a resource timing entry for a subframe
   // navigation that has failed before committing - a non-ok object navigation
diff --git a/third_party/blink/public/mojom/navigation/navigation_params.mojom b/third_party/blink/public/mojom/navigation/navigation_params.mojom
index d817b65f..cc0e0f81 100644
--- a/third_party/blink/public/mojom/navigation/navigation_params.mojom
+++ b/third_party/blink/public/mojom/navigation/navigation_params.mojom
@@ -625,9 +625,9 @@
   string? cookie_deprecation_label;
 };
 
-// Parameters used to dispatch the `pageconceal` event on the old Document for
+// Parameters used to dispatch the `pageswap` event on the old Document for
 // a navigation. Only generated for same-origin navigations.
-struct PageConcealEventParams {
+struct PageSwapEventParams {
   // The URL of the destination page.
   url.mojom.Url url;
 
diff --git a/third_party/blink/public/mojom/printing/web_printing.mojom b/third_party/blink/public/mojom/printing/web_printing.mojom
index 57ee518c..5a1b193 100644
--- a/third_party/blink/public/mojom/printing/web_printing.mojom
+++ b/third_party/blink/public/mojom/printing/web_printing.mojom
@@ -92,11 +92,47 @@
   uint32 to;
 };
 
+union WebPrintingMediaSizeDimension {
+  WebPrintingRange range;
+  uint32 value;
+};
+
+// Each media size dimension can be either a fixed value or a range.
+// Examples from the IPP spec:
+//
+// /* ISO A4 transparency only from manual feed */
+// media-size={
+//  x-dimension=21000
+//  y-dimension=29700
+// }
+//
+// /* Custom sizes from 3x5 to 8.5x14 inches */
+// media-size={
+//  x-dimension=7620-21590
+//  y-dimension=12700-35560
+// }
+//
+// Dimensions are specified in PWG units (hundredths of millimeters).
+struct WebPrintingMediaSize {
+  WebPrintingMediaSizeDimension x_dimension;
+  WebPrintingMediaSizeDimension y_dimension;
+};
+
+// Represents the media-col entry of printer attributes. See §6.3.1 in
+// in https://ftp.pwg.org/pub/pwg/candidates/cs-ippjobext21-20230210-5100.7.pdf
+struct WebPrintingMediaCollection {
+  WebPrintingMediaSize media_size;
+  string media_size_name;
+};
+
 // Detailed description of a single printer.
 struct WebPrinterAttributes {
   uint32 copies_default;
   WebPrintingRange copies_supported;
 
+  WebPrintingMediaCollection media_col_default;
+  array<WebPrintingMediaCollection> media_col_database;
+
   WebPrintingMultipleDocumentHandling multiple_document_handling_default;
   array<WebPrintingMultipleDocumentHandling> multiple_document_handling_supported;
 
@@ -117,10 +153,20 @@
   array<WebPrintingSides> sides_supported;
 };
 
+// Represents the requested media-col entry for a print job. Note that this
+// struct slightly differs from WebPrintingMediaCollection and thus is defined
+// separately:
+//   * `media_size` dimensions are defined as values instead of ranges;
+//   * `media_size_name` is omitted (callers are supposed to pass `media_size`).
+struct WebPrintingMediaCollectionRequested {
+  gfx.mojom.Size media_size;
+};
+
 struct WebPrintJobTemplateAttributes {
   string job_name;
 
   uint32 copies;
+  WebPrintingMediaCollectionRequested? media_col;
   WebPrintingMultipleDocumentHandling? multiple_document_handling;
   WebPrintingOrientationRequested? orientation_requested;
   gfx.mojom.Size? printer_resolution;
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni
index fd197ad5..0b7defe0 100644
--- a/third_party/blink/renderer/bindings/generated_in_core.gni
+++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -1289,8 +1289,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_readable_stream_default_controller.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_readable_stream_default_reader.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_readable_stream_default_reader.h",
-  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_page_conceal_event.cc",
-  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_page_conceal_event.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_page_swap_event.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_page_swap_event.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_page_reveal_event.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_page_reveal_event.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_report.cc",
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index e9aea78c..be03fb1 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -3147,7 +3147,19 @@
 # current_os = "linux" and target_os = "android". Using target_os is necessary as
 # we need to compile in the same way as would happen when current_os = "android".
 if (target_os != "android") {
+  generated_union_sources_in_modules += [
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_unsignedlong_webprintingrange.cc",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_unsignedlong_webprintingrange.h",
+  ]
   generated_dictionary_sources_in_modules += [
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_size.cc",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_size.h",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_size_requested.cc",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_size_requested.h",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_collection.cc",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_collection.h",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_collection_requested.cc",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_collection_requested.h",
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_printing_range.cc",
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_printing_range.h",
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_web_printing_resolution.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni
index b479355..af2c87a8 100644
--- a/third_party/blink/renderer/bindings/idl_in_core.gni
+++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -739,7 +739,7 @@
   "//third_party/blink/renderer/core/url_pattern/url_pattern_init.idl",
   "//third_party/blink/renderer/core/url_pattern/url_pattern_options.idl",
   "//third_party/blink/renderer/core/url_pattern/url_pattern_result.idl",
-  "//third_party/blink/renderer/core/view_transition/page_conceal_event.idl",
+  "//third_party/blink/renderer/core/view_transition/page_swap_event.idl",
   "//third_party/blink/renderer/core/view_transition/page_reveal_event.idl",
   "//third_party/blink/renderer/core/view_transition/view_transition.idl",
   "//third_party/blink/renderer/core/view_transition/view_transition_callback.idl",
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
index cbf461412..85c3331 100644
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
@@ -17,6 +17,13 @@
   {% if property.style_builder_declare %}
     {% if property.style_builder_generate_inherit %}
 void {{class_name}}::ApplyInherit(StyleResolverState& state) const {
+      {% if property.affected_by_zoom %}
+  if (RuntimeEnabledFeatures::StandardizedBrowserZoomEnabled()) {
+    if (ApplyParentValueIfZoomChanged(state)) {
+      return;
+    }
+  }
+      {% endif %}
 {{(caller(property) ~ '}')}}
     {% endif %}
   {% endif %}
diff --git a/third_party/blink/renderer/core/accessibility/ax_object_cache.h b/third_party/blink/renderer/core/accessibility/ax_object_cache.h
index 61e95857..b1f2b60a 100644
--- a/third_party/blink/renderer/core/accessibility/ax_object_cache.h
+++ b/third_party/blink/renderer/core/accessibility/ax_object_cache.h
@@ -48,6 +48,7 @@
 namespace blink {
 
 class AbstractInlineTextBox;
+class AriaNotification;
 class AriaNotificationOptions;
 class AXObject;
 class AccessibleNode;
@@ -164,11 +165,16 @@
   virtual void HandleAttributeChanged(const QualifiedName& attr_name,
                                       AccessibleNode*) = 0;
 
-  // Handle notifications from the `ariaNotify` API.
+  // Handles a notification from the `ariaNotify` API.
   virtual void HandleAriaNotification(const Node*,
                                       const String&,
                                       const AriaNotificationOptions*) = 0;
 
+  // Retrieves the `AriaNotification` (if any) for a given `AXObject`.
+  // Note that ownership of such notification will be removed from this object.
+  virtual std::unique_ptr<AriaNotification> RetrieveAriaNotification(
+      const AXObject*) = 0;
+
   // Called when a HTMLFrameOwnerElement (such as an iframe element) changes the
   // embedding token of its child frame.
   virtual void EmbeddingTokenChanged(HTMLFrameOwnerElement*) = 0;
diff --git a/third_party/blink/renderer/core/css/build.gni b/third_party/blink/renderer/core/css/build.gni
index 81688f1..0b5a0e1 100644
--- a/third_party/blink/renderer/core/css/build.gni
+++ b/third_party/blink/renderer/core/css/build.gni
@@ -589,6 +589,7 @@
   "properties/css_property_ref.h",
   "properties/css_unresolved_property.cc",
   "properties/css_unresolved_property.h",
+  "properties/longhand.cc",
   "properties/longhand.h",
   "properties/longhands/custom_property.cc",
   "properties/longhands/custom_property.h",
@@ -816,6 +817,7 @@
   "media_query_set_test.cc",
   "media_values_test.cc",
   "mock_css_paint_image_generator.h",
+  "page_rule_collector_test.cc",
   "parser/at_rule_descriptor_parser_test.cc",
   "parser/container_query_parser_test.cc",
   "parser/css_lazy_parsing_test.cc",
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index 609c800..cba24adf 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -744,6 +744,21 @@
       default: false,
       valid_type: "bool",
     },
+
+    // - affected_by_zoom: true
+    //
+    // Whether or not the computed value of this property is affected by
+    // the effective zoom factor. Generally, all computed values that contain
+    // a blink::Length are affected by zoom.
+    //
+    // Setting this flag to 'true' will change the inheritance behavior
+    // (Longhand::ApplyInherit) to effectively "rezoom" the inherited value.
+    //
+    // https://github.com/w3c/csswg-drafts/issues/9397
+    affected_by_zoom: {
+      default: false,
+      valid_type: "bool",
+    },
   },
 
   // Members in the data objects should appear in the same order as in the
@@ -3342,6 +3357,7 @@
       valid_for_first_line: true,
       valid_for_cue: true,
       valid_for_marker: true,
+      affected_by_zoom: true,
     },
     {
       name: "list-style-image",
@@ -6387,6 +6403,7 @@
       supports_incremental_style: true,
       valid_for_formatted_text: true,
       valid_for_position_fallback: true,
+      affected_by_zoom: true,
     },
     {
       name: "will-change",
diff --git a/third_party/blink/renderer/core/css/css_test_helpers.cc b/third_party/blink/renderer/core/css/css_test_helpers.cc
index a3911827..d336b32 100644
--- a/third_party/blink/renderer/core/css/css_test_helpers.cc
+++ b/third_party/blink/renderer/core/css/css_test_helpers.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/css/css_test_helpers.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_css_style_sheet_init.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_property_definition.h"
 #include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
 #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
@@ -72,6 +73,16 @@
       document, NullURL(), TextPosition::MinimumPosition(), UTF8Encoding());
 }
 
+RuleSet* CreateRuleSet(Document& document, String text) {
+  DummyExceptionStateForTesting exception_state;
+  auto* init = CSSStyleSheetInit::Create();
+  auto* media_query_evaluator =
+      MakeGarbageCollected<MediaQueryEvaluator>(document.GetFrame());
+  auto* sheet = CSSStyleSheet::Create(document, init, exception_state);
+  sheet->replaceSync(text, exception_state);
+  return &sheet->Contents()->EnsureRuleSet(*media_query_evaluator);
+}
+
 PropertyRegistration* CreatePropertyRegistration(const String& name,
                                                  String syntax,
                                                  const CSSValue* initial_value,
diff --git a/third_party/blink/renderer/core/css/css_test_helpers.h b/third_party/blink/renderer/core/css/css_test_helpers.h
index 5681358..f65e8a0 100644
--- a/third_party/blink/renderer/core/css/css_test_helpers.h
+++ b/third_party/blink/renderer/core/css/css_test_helpers.h
@@ -51,6 +51,7 @@
 };
 
 CSSStyleSheet* CreateStyleSheet(Document& document);
+RuleSet* CreateRuleSet(Document& document, String text);
 
 // Create a PropertyRegistration with the given name. An initial value must
 // be provided when the syntax is not "*".
diff --git a/third_party/blink/renderer/core/css/element_rule_collector_test.cc b/third_party/blink/renderer/core/css/element_rule_collector_test.cc
index 93958eda..f5c5b87 100644
--- a/third_party/blink/renderer/core/css/element_rule_collector_test.cc
+++ b/third_party/blink/renderer/core/css/element_rule_collector_test.cc
@@ -78,7 +78,7 @@
     MatchRequest request(rule_set, scope);
 
     collector.CollectMatchingRules(request);
-    collector.SortAndTransferMatchedRules(CascadeOrigin::kNone,
+    collector.SortAndTransferMatchedRules(CascadeOrigin::kAuthor,
                                           /*is_vtt_embedded_style=*/false,
                                           /*tracker=*/nullptr);
 
diff --git a/third_party/blink/renderer/core/css/page_rule_collector.cc b/third_party/blink/renderer/core/css/page_rule_collector.cc
index 5ecb46b..76c9049 100644
--- a/third_party/blink/renderer/core/css/page_rule_collector.cc
+++ b/third_party/blink/renderer/core/css/page_rule_collector.cc
@@ -66,6 +66,8 @@
       result_(match_result) {}
 
 void PageRuleCollector::MatchPageRules(RuleSet* rules,
+                                       CascadeOrigin origin,
+                                       TreeScope* tree_scope,
                                        const CascadeLayerMap* layer_map) {
   if (!rules) {
     return;
@@ -89,9 +91,13 @@
         return r1->Selector()->Specificity() < r2->Selector()->Specificity();
       });
 
+  if (origin == CascadeOrigin::kAuthor) {
+    CHECK(tree_scope);
+    result_.BeginAddingAuthorRulesForTreeScope(*tree_scope);
+  }
+
   for (unsigned i = 0; i < matched_page_rules.size(); i++) {
-    result_.AddMatchedProperties(&matched_page_rules[i]->Properties(),
-                                 CascadeOrigin::kNone);
+    result_.AddMatchedProperties(&matched_page_rules[i]->Properties(), origin);
   }
 }
 
diff --git a/third_party/blink/renderer/core/css/page_rule_collector.h b/third_party/blink/renderer/core/css/page_rule_collector.h
index 0464c69..84073b5f 100644
--- a/third_party/blink/renderer/core/css/page_rule_collector.h
+++ b/third_party/blink/renderer/core/css/page_rule_collector.h
@@ -23,6 +23,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PAGE_RULE_COLLECTOR_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PAGE_RULE_COLLECTOR_H_
 
+#include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/css/resolver/match_result.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
@@ -31,7 +32,7 @@
 class CascadeLayerMap;
 class StyleRulePage;
 
-class PageRuleCollector {
+class CORE_EXPORT PageRuleCollector {
   STACK_ALLOCATED();
 
  public:
@@ -40,7 +41,12 @@
                     const AtomicString& page_name,
                     MatchResult&);
 
-  void MatchPageRules(RuleSet* rules, const CascadeLayerMap* layer_map);
+  // TreeScope is required for CascadeOrigin::kAuthor,
+  // and ignored for other origins.
+  void MatchPageRules(RuleSet* rules,
+                      CascadeOrigin,
+                      TreeScope*,
+                      const CascadeLayerMap* layer_map);
   const MatchResult& MatchedResult() { return result_; }
 
  private:
diff --git a/third_party/blink/renderer/core/css/page_rule_collector_test.cc b/third_party/blink/renderer/core/css/page_rule_collector_test.cc
new file mode 100644
index 0000000..2e3785fe
--- /dev/null
+++ b/third_party/blink/renderer/core/css/page_rule_collector_test.cc
@@ -0,0 +1,76 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/page_rule_collector.h"
+
+#include <optional>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/css_test_helpers.h"
+#include "third_party/blink/renderer/core/css/media_query_evaluator.h"
+#include "third_party/blink/renderer/core/css/resolver/style_cascade.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+
+namespace blink {
+
+class PageRuleCollectorTest : public PageTestBase {
+ public:
+  const ComputedStyle* ComputePageStyle(String ua_sheet_string,
+                                        String author_sheet_string) {
+    RuleSet* ua_ruleset =
+        css_test_helpers::CreateRuleSet(GetDocument(), ua_sheet_string);
+    RuleSet* author_ruleset =
+        css_test_helpers::CreateRuleSet(GetDocument(), author_sheet_string);
+
+    const ComputedStyle& initial_style =
+        GetDocument().GetStyleResolver().InitialStyle();
+    Element* root_element = GetDocument().documentElement();
+
+    StyleResolverState state(GetDocument(), *root_element);
+    state.CreateNewStyle(initial_style, initial_style);
+
+    STACK_UNINITIALIZED StyleCascade cascade(state);
+
+    PageRuleCollector collector(&initial_style, /* page_index */ 0,
+                                /* page_name */ AtomicString("page"),
+                                cascade.MutableMatchResult());
+
+    collector.MatchPageRules(ua_ruleset, CascadeOrigin::kUserAgent,
+                             nullptr /* tree_scope */, nullptr /* layer_map */);
+
+    collector.MatchPageRules(author_ruleset, CascadeOrigin::kAuthor,
+                             &GetDocument() /* tree_scope */,
+                             nullptr /* layer_map */);
+
+    cascade.Apply();
+
+    return state.TakeStyle();
+  }
+};
+
+TEST_F(PageRuleCollectorTest, UserAgent) {
+  String ua_sheet_string = "@page { margin: 1px; }";
+  String author_sheet_string = "@page { margin: 2px; }";
+
+  const ComputedStyle* style =
+      ComputePageStyle(ua_sheet_string, author_sheet_string);
+
+  EXPECT_EQ(Length::Fixed(2), style->MarginLeft());
+}
+
+TEST_F(PageRuleCollectorTest, UserAgentImportant) {
+  String ua_sheet_string = "@page { margin: 1px !important; }";
+  String author_sheet_string = "@page { margin: 2px; }";
+
+  const ComputedStyle* style =
+      ComputePageStyle(ua_sheet_string, author_sheet_string);
+
+  EXPECT_EQ(Length::Fixed(1), style->MarginLeft());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/css/properties/longhand.cc b/third_party/blink/renderer/core/css/properties/longhand.cc
new file mode 100644
index 0000000..432a0ed
--- /dev/null
+++ b/third_party/blink/renderer/core/css/properties/longhand.cc
@@ -0,0 +1,30 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/properties/longhand.h"
+
+#include "third_party/blink/renderer/core/css/properties/computed_style_utils.h"
+
+namespace blink {
+
+void Longhand::ApplyParentValue(StyleResolverState& state) const {
+  // Creating the (computed) CSSValue involves unzooming using the parent's
+  // effective zoom.
+  const CSSValue* parent_computed_value =
+      ComputedStyleUtils::ComputedPropertyValue(*this, *state.ParentStyle());
+  CHECK(parent_computed_value);
+  // Applying the CSSValue involves zooming using our effective zoom.
+  ApplyValue(state, *parent_computed_value, ValueMode::kNormal);
+}
+
+bool Longhand::ApplyParentValueIfZoomChanged(StyleResolverState& state) const {
+  if (state.ParentStyle()->EffectiveZoom() !=
+      state.StyleBuilder().EffectiveZoom()) {
+    ApplyParentValue(state);
+    return true;
+  }
+  return false;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/css/properties/longhand.h b/third_party/blink/renderer/core/css/properties/longhand.h
index 79e12be..08c1846 100644
--- a/third_party/blink/renderer/core/css/properties/longhand.h
+++ b/third_party/blink/renderer/core/css/properties/longhand.h
@@ -57,6 +57,15 @@
  protected:
   constexpr Longhand(CSSPropertyID id, Flags flags, char repetition_separator)
       : CSSProperty(id, flags | kLonghand, repetition_separator) {}
+  // Applies the computed CSSValue of the parent style using ApplyValue.
+  // This generally achieves the same as ApplyInherit, but effectively
+  // "rezooms" the value.
+  //
+  // https://github.com/w3c/csswg-drafts/issues/9397
+  void ApplyParentValue(StyleResolverState&) const;
+  // If our zoom is different from the parent zoom, calls ApplyParentValue
+  // and returns true. Otherwise does nothing and returns false.
+  bool ApplyParentValueIfZoomChanged(StyleResolverState&) const;
 };
 
 template <>
diff --git a/third_party/blink/renderer/core/css/resolver/cascade_expansion_test.cc b/third_party/blink/renderer/core/css/resolver/cascade_expansion_test.cc
index cbf9b3a..1fb94a9c 100644
--- a/third_party/blink/renderer/core/css/resolver/cascade_expansion_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/cascade_expansion_test.cc
@@ -653,8 +653,9 @@
   auto* set = ParseDeclarationBlock("left:1px");
 
   MatchResult result;
+  result.BeginAddingAuthorRulesForTreeScope(GetDocument());
   for (wtf_size_t i = 0; i < max + 3; ++i) {
-    result.AddMatchedProperties(set, CascadeOrigin::kNone);
+    result.AddMatchedProperties(set, CascadeOrigin::kAuthor);
   }
 
   ASSERT_EQ(max + 3u, result.GetMatchedProperties().size());
@@ -685,14 +686,15 @@
   }
 
   MatchResult result;
+  result.BeginAddingAuthorRulesForTreeScope(GetDocument());
   result.AddMatchedProperties(
       ImmutableCSSPropertyValueSet::Create(declarations.data(), max + 1,
                                            kHTMLStandardMode),
-      CascadeOrigin::kNone);
+      CascadeOrigin::kAuthor);
   result.AddMatchedProperties(
       ImmutableCSSPropertyValueSet::Create(declarations.data(), max + 2,
                                            kHTMLStandardMode),
-      CascadeOrigin::kNone);
+      CascadeOrigin::kAuthor);
 
   EXPECT_GT(ExpansionAt(result, 0).size(), 0u);
   EXPECT_EQ(ExpansionAt(result, 1).size(), 0u);
diff --git a/third_party/blink/renderer/core/css/resolver/match_result.cc b/third_party/blink/renderer/core/css/resolver/match_result.cc
index 5f536c1b..bb1d7fda 100644
--- a/third_party/blink/renderer/core/css/resolver/match_result.cc
+++ b/third_party/blink/renderer/core/css/resolver/match_result.cc
@@ -52,6 +52,7 @@
     const CSSPropertyValueSet* properties,
     CascadeOrigin origin,
     const AddMatchedPropertiesOptions& options) {
+  CHECK_NE(origin, CascadeOrigin::kNone);
   matched_properties_.Grow(matched_properties_.size() + 1);
   MatchedProperties& new_properties = matched_properties_.back();
   new_properties.properties = const_cast<CSSPropertyValueSet*>(properties);
diff --git a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
index 2251b1de..e58f319 100644
--- a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
@@ -314,7 +314,8 @@
   // Currently, only @page rules in the document scope apply.
   DCHECK(scope_->RootNode().IsDocumentNode());
   for (auto [sheet, rule_set] : active_style_sheets_) {
-    collector.MatchPageRules(rule_set.Get(), GetCascadeLayerMap());
+    collector.MatchPageRules(rule_set.Get(), CascadeOrigin::kAuthor, scope_,
+                             GetCascadeLayerMap());
   }
 }
 
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
index 5844b7e..3fa154d 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -331,10 +331,14 @@
   for (CSSPropertyID id : map_.NativeBitset()) {
     CSSPropertyName name(id);
     CascadePriority priority = map_.At(name);
-    DCHECK(priority.HasOrigin());
     if (IsInterpolation(priority)) {
       continue;
     }
+    if (!priority.HasOrigin()) {
+      // Declarations added for explicit defaults (AddExplicitDefaults)
+      // should not be observable.
+      continue;
+    }
     const CSSValue* cascaded = ValueAt(match_result_, priority.GetPosition());
     DCHECK(cascaded);
     result.Set(name, cascaded);
@@ -384,6 +388,8 @@
 }
 
 void StyleCascade::AnalyzeMatchResult() {
+  AddExplicitDefaults();
+
   int index = 0;
   for (const MatchedProperties& properties :
        match_result_.GetMatchedProperties()) {
@@ -452,6 +458,40 @@
   }
 }
 
+// The implicit defaulting behavior of inherited properties is to take
+// the value of the parent style [1]. However, we never reach
+// Longhand::ApplyInherit for implicit defaults, which is needed to adjust
+// Lengths with premultiplied zoom. Therefore, all inherited properties
+// are instead explicitly defaulted [2] when the effective zoom has changed
+// versus the parent zoom.
+//
+// [1] https://drafts.csswg.org/css-cascade/#defaulting
+// [2] https://drafts.csswg.org/css-cascade/#defaulting-keywords
+void StyleCascade::AddExplicitDefaults() {
+  if (RuntimeEnabledFeatures::StandardizedBrowserZoomEnabled() &&
+      effective_zoom_changed_) {
+    // TODO(crbug.com/40946858): Generate a list from json5.
+    //
+    // At a glance, these inherited properties can contain lengths:
+    //
+    //   -webkit-border-horizontal-spacing
+    //   -webkit-border-vertical-spacing
+    //   -webkit-text-stroke-width
+    //   letter-spacing
+    //   line-height
+    //   list-style-image
+    //   stroke-dashoffset
+    //   stroke-width
+    //   text-indent
+    //   text-shadow
+    //   text-underline-offset
+    //   word-spacing
+    //
+    // (And maybe more).
+    map_.Add(CSSPropertyID::kLineHeight, CascadePriority(CascadeOrigin::kNone));
+  }
+}
+
 void StyleCascade::Reanalyze() {
   map_.Reset();
   generation_ = 0;
@@ -471,6 +511,12 @@
   // values on ComputedStyle.
   auto direction = state_.StyleBuilder().Direction();
   auto writing_mode = state_.StyleBuilder().GetWritingMode();
+  // Similarly, we assume that the effective zoom of this element
+  // is the same as the parent's effective zoom. If it isn't,
+  // we re-cascade with explicit defaults inserted at CascadeOrigin::kNone.
+  //
+  // See also StyleCascade::AddExplicitDefaults.
+  float effective_zoom = state_.StyleBuilder().EffectiveZoom();
 
   if (map_.NativeBitset().Has(CSSPropertyID::kDirection)) {
     LookupAndApply(GetCSSPropertyDirection(), resolver);
@@ -478,13 +524,26 @@
   if (map_.NativeBitset().Has(CSSPropertyID::kWritingMode)) {
     LookupAndApply(GetCSSPropertyWritingMode(), resolver);
   }
+  if (map_.NativeBitset().Has(CSSPropertyID::kZoom)) {
+    LookupAndApply(GetCSSPropertyZoom(), resolver);
+  }
+
+  bool reanalyze = false;
 
   if (depends_on_cascade_affecting_property_) {
     if (direction != state_.StyleBuilder().Direction() ||
         writing_mode != state_.StyleBuilder().GetWritingMode()) {
-      Reanalyze();
+      reanalyze = true;
     }
   }
+  if (effective_zoom != state_.StyleBuilder().EffectiveZoom()) {
+    effective_zoom_changed_ = true;
+    reanalyze = true;
+  }
+
+  if (reanalyze) {
+    Reanalyze();
+  }
 }
 
 void StyleCascade::ApplyHighPriority(CascadeResolver& resolver) {
@@ -741,9 +800,13 @@
   *priority = CascadePriority(*priority, resolver.generation_);
   DCHECK(!property.IsSurrogate());
   DCHECK(priority->GetOrigin() < CascadeOrigin::kAnimation);
-  const CSSValue* value = ValueAt(match_result_, priority->GetPosition());
-  DCHECK(value);
   CascadeOrigin origin = priority->GetOrigin();
+  // Values at CascadeOrigin::kNone are used for explicit defaulting,
+  // see StyleCascade::AddExplicitDefaults.
+  const CSSValue* value = (origin == CascadeOrigin::kNone)
+                              ? cssvalue::CSSUnsetValue::Create()
+                              : ValueAt(match_result_, priority->GetPosition());
+  DCHECK(value);
   value = Resolve(property, *value, *priority, origin, resolver);
   DCHECK(IsA<CustomProperty>(property) || !value->IsUnparsedDeclaration());
   DCHECK(!value->IsPendingSubstitutionValue());
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.h b/third_party/blink/renderer/core/css/resolver/style_cascade.h
index 8b91255..f7889b6 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade.h
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade.h
@@ -178,6 +178,7 @@
   void AnalyzeIfNeeded();
   void AnalyzeMatchResult();
   void AnalyzeInterpolations();
+  void AddExplicitDefaults();
 
   // Clears the CascadeMap and other state, and analyzes the MatchResult/
   // interpolations again.
@@ -541,6 +542,8 @@
   // computed value of the property affects how e.g. margin-inline-start
   // (and other css-logical properties) cascade.
   bool depends_on_cascade_affecting_property_ = false;
+  // See comment in StyleCascade::AddExplicitDefaults (.cc file).
+  bool effective_zoom_changed_ = false;
   // If true, invisible rules will be added to the cascade, setting
   // `has_invisible_rules_` to true whenever such rules are actually seen.
   // Otherwise, invisible rules are silently ignored.
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
index 687df3f..1421284d 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
@@ -197,8 +197,12 @@
         *CSSPropertyName::From(GetDocument().GetExecutionContext(), name));
   }
 
+  CascadePriority* FindPriority(CSSPropertyName name) {
+    return cascade_.map_.Find(name);
+  }
+
   CascadePriority GetPriority(CSSPropertyName name) {
-    CascadePriority* c = cascade_.map_.Find(name);
+    CascadePriority* c = FindPriority(name);
     return c ? *c : CascadePriority();
   }
 
@@ -2713,6 +2717,33 @@
   EXPECT_EQ(2.0f, cascade.TakeStyle()->EffectiveZoom());
 }
 
+TEST_F(StyleCascadeTest, ZoomExplicitDefault) {
+  ScopedStandardizedBrowserZoomForTest scoped_feature(true);
+
+  TestCascade cascade(GetDocument());
+  cascade.Add("zoom:200%");
+  cascade.Apply();
+
+  // Since the zoom changed, there should be an explicit entry
+  // in the cascade map with CascadeOrigin::kNone.
+  CascadePriority* priority =
+      cascade.FindPriority(CSSPropertyName(CSSPropertyID::kLineHeight));
+  ASSERT_TRUE(priority);
+  EXPECT_EQ(CascadeOrigin::kNone, priority->GetOrigin());
+}
+
+TEST_F(StyleCascadeTest, ZoomNoExplicitDefault) {
+  ScopedStandardizedBrowserZoomForTest scoped_feature(true);
+
+  TestCascade cascade(GetDocument());
+  cascade.Apply();
+
+  // Since the zoom did not change, there should not be an entry in the map.
+  CascadePriority* priority =
+      cascade.FindPriority(CSSPropertyName(CSSPropertyID::kLineHeight));
+  EXPECT_FALSE(priority);
+}
+
 TEST_F(StyleCascadeTest, WritingModeCascadeOrder) {
   TestCascade cascade(GetDocument());
   cascade.Add("writing-mode", "vertical-lr");
@@ -3693,6 +3724,24 @@
   EXPECT_EQ("-5s", CssTextAt(map, "animation-delay"));
 }
 
+TEST_F(StyleCascadeTest, GetCascadedValuesWithExplicitDefaults) {
+  ScopedStandardizedBrowserZoomForTest scoped_feature(true);
+
+  TestCascade cascade(GetDocument());
+  cascade.Add("top:100px");
+  cascade.Add("zoom:200%");  // Causes explicit defaults.
+  cascade.Apply();
+
+  // Any explicit defaults (StyleCascade::AddExplicitDefaults) should not
+  // be visible via GetCascadedValues.
+
+  auto map = cascade.GetCascadedValues();
+  EXPECT_EQ(2u, map.size());
+
+  EXPECT_EQ("100px", CssTextAt(map, "top"));
+  EXPECT_EQ("200%", CssTextAt(map, "zoom"));
+}
+
 TEST_F(StyleCascadeTest, StaticResolveNoVar) {
   // We don't need this object, but it's an easy way of setting
   // up a StyleResolverState.
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index a0ab107..3f8760b 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -1784,6 +1784,7 @@
 
   collector.MatchPageRules(
       CSSDefaultStyleSheets::Instance().DefaultPrintStyle(),
+      CascadeOrigin::kUserAgent, nullptr /* tree_scope */,
       nullptr /* layer_map */);
 
   if (ScopedStyleResolver* scoped_resolver =
@@ -3064,8 +3065,11 @@
 
   // Use StyleCascade to apply inheritance in the correct order.
   STACK_UNINITIALIZED StyleCascade cascade(state);
-  cascade.MutableMatchResult().AddMatchedProperties(
-      css_property_value_set, CascadeOrigin::kNone, {.is_inline_style = true});
+  cascade.MutableMatchResult().BeginAddingAuthorRulesForTreeScope(
+      GetDocument());
+  cascade.MutableMatchResult().AddMatchedProperties(css_property_value_set,
+                                                    CascadeOrigin::kAuthor,
+                                                    {.is_inline_style = true});
   cascade.Apply();
 
   StyleAdjuster::AdjustComputedStyle(state, nullptr);
diff --git a/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc b/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc
index 38d1617..20e47e95 100644
--- a/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc
@@ -318,13 +318,17 @@
     if (end_style->ShouldPreserveBreaks() && start == end &&
         end.OffsetInContainerNode() <
             static_cast<int>(To<Text>(end.ComputeContainerNode())->length())) {
-      int end_offset = end.OffsetInContainerNode();
-      // TODO(yosin) We should use |PositionMoveType::CodePoint| for
-      // |previousPositionOf()|.
-      if (!IsNewLineAtPosition(
-              PreviousPositionOf(end, PositionMoveType::kCodeUnit)) &&
-          IsNewLineAtPosition(end))
-        end = Position(end.ComputeContainerNode(), end_offset + 1);
+      if (!RuntimeEnabledFeatures::
+              NoIncreasingEndOffsetOnSplittingTextNodesEnabled()) {
+        int end_offset = end.OffsetInContainerNode();
+        // TODO(yosin) We should use |PositionMoveType::CodePoint| for
+        // |previousPositionOf()|.
+        if (!IsNewLineAtPosition(
+                PreviousPositionOf(end, PositionMoveType::kCodeUnit)) &&
+            IsNewLineAtPosition(end)) {
+          end = Position(end.ComputeContainerNode(), end_offset + 1);
+        }
+      }
       if (is_end_and_end_of_last_paragraph_on_same_node &&
           end.OffsetInContainerNode() >=
               end_of_last_paragraph.OffsetInContainerNode())
diff --git a/third_party/blink/renderer/core/events/event_type_names.json5 b/third_party/blink/renderer/core/events/event_type_names.json5
index 5af1129..c9eaf4c 100644
--- a/third_party/blink/renderer/core/events/event_type_names.json5
+++ b/third_party/blink/renderer/core/events/event_type_names.json5
@@ -257,8 +257,8 @@
     "reading",
     "readingerror",
     "readystatechange",
-    "pageconceal",
     "pagereveal",
+    "pageswap",
     "reflectionchange",
     "rejectionhandled",
     "release",
diff --git a/third_party/blink/renderer/core/fileapi/public_url_manager.cc b/third_party/blink/renderer/core/fileapi/public_url_manager.cc
index db633aa5..7f7ed2a8 100644
--- a/third_party/blink/renderer/core/fileapi/public_url_manager.cc
+++ b/third_party/blink/renderer/core/fileapi/public_url_manager.cc
@@ -27,9 +27,7 @@
 #include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
 
 #include "base/feature_list.h"
-#include "base/metrics/histogram_functions.h"
 #include "base/notreached.h"
-#include "base/strings/strcat.h"
 #include "base/types/pass_key.h"
 #include "base/unguessable_token.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -67,16 +65,6 @@
 
 }  // namespace
 
-// Execution context names corresponding to the entries from
-// `ExecutionContextIdForHistogram` in public_url_manager.h.
-const char* const kExecutionContextNamesForHistograms[]{
-    "Frame",
-    "Worker",
-};
-static_assert(std::size(kExecutionContextNamesForHistograms) ==
-              static_cast<size_t>(ExecutionContextIdForHistogram::kMaxValue) +
-                  1);
-
 PublicURLManager::PublicURLManager(ExecutionContext* execution_context)
     : ExecutionContextLifecycleObserver(execution_context),
       frame_url_store_(execution_context),
@@ -89,7 +77,6 @@
         return;
       }
 
-      execution_context_type_ = ExecutionContextIdForHistogram::kFrame;
       frame->GetRemoteNavigationAssociatedInterfaces()->GetInterface(
           frame_url_store_.BindNewEndpointAndPassReceiver(
               execution_context->GetTaskRunner(TaskType::kFileReading)));
@@ -101,7 +88,6 @@
         return;
       }
 
-      execution_context_type_ = ExecutionContextIdForHistogram::kWorker;
       worker_global_scope->GetBrowserInterfaceBroker().GetInterface(
           worker_url_store_.BindNewPipeAndPassReceiver(
               execution_context->GetTaskRunner(TaskType::kFileReading)));
@@ -153,9 +139,6 @@
     : ExecutionContextLifecycleObserver(execution_context),
       frame_url_store_(execution_context),
       worker_url_store_(execution_context) {
-  if (base::FeatureList::IsEnabled(net::features::kSupportPartitionedBlobUrl)) {
-    execution_context_type_ = ExecutionContextIdForHistogram::kFrame;
-  }
   frame_url_store_.Bind(
       std::move(frame_url_store_remote),
       execution_context->GetTaskRunner(TaskType::kFileReading));
@@ -200,31 +183,9 @@
       }
     }
 
-    base::ElapsedTimer register_timer;
     GetBlobURLStore().Register(std::move(blob_remote), url,
                                GetExecutionContext()->GetAgentClusterID(),
                                top_level_site);
-    const base::TimeDelta register_url_time = register_timer.Elapsed();
-
-    if (base::FeatureList::IsEnabled(
-            net::features::kSupportPartitionedBlobUrl)) {
-      // This holds because `execution_context_type_` will always be set for
-      // Window, SharedWorker, and DedicatedWorker contexts, which are the only
-      // ones where URL.CreateObjectURL is exposed (per the IDL).
-      CHECK(execution_context_type_.has_value());
-
-      const char* context_type_ =
-          kExecutionContextNamesForHistograms[static_cast<int>(
-              *execution_context_type_)];
-      base::UmaHistogramCustomTimes(
-          base::StrCat({"Storage.Blob.RegisterURLTimeWithPartitioningSupport.",
-                        context_type_}),
-          register_url_time, base::Milliseconds(1), base::Seconds(60), 50);
-    } else {
-      base::UmaHistogramCustomTimes(
-          "Storage.Blob.RegisterURLTimeWithoutPartitioningSupport",
-          register_url_time, base::Milliseconds(1), base::Seconds(60), 50);
-    }
 
     mojo_urls_.insert(url_string);
     registrable->CloneMojoBlob(std::move(blob_receiver));
diff --git a/third_party/blink/renderer/core/fileapi/public_url_manager.h b/third_party/blink/renderer/core/fileapi/public_url_manager.h
index d4c80fdf..153a303 100644
--- a/third_party/blink/renderer/core/fileapi/public_url_manager.h
+++ b/third_party/blink/renderer/core/fileapi/public_url_manager.h
@@ -48,17 +48,6 @@
 class URLRegistry;
 class URLRegistrable;
 
-// Execution context ids for usage in metrics. Entries should not be renumbered
-// and numeric values should never be reused. Please keep in sync with
-// "BlobURLExecutionContextId" in
-// src/tools/metrics/histograms/metadata/histogram_suffixes_list.xml and with
-// `kExecutionContextNamesForHistograms` in public_url_manager.cc.
-enum class ExecutionContextIdForHistogram {
-  kFrame = 0,
-  kWorker = 1,
-  kMaxValue = kWorker
-};
-
 class CORE_EXPORT PublicURLManager final
     : public GarbageCollected<PublicURLManager>,
       public ExecutionContextLifecycleObserver {
@@ -106,11 +95,6 @@
   URLToRegistryMap url_to_registry_;
   HashSet<URLString> mojo_urls_;
 
-  // Records which execution context type instantiated this PublicURLManager,
-  // for collecting metrics. This is only set when the SupportPartitionedBlobUrl
-  // feature is enabled, and is only set for frame or worker execution contexts.
-  std::optional<ExecutionContextIdForHistogram> execution_context_type_;
-
   bool is_stopped_ = false;
 
   // For a frame context or from a main thread worklet context, a
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
index 8fc0c52..54401bc6 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -373,7 +373,7 @@
 
   DEFINE_ATTRIBUTE_EVENT_LISTENER(orientationchange, kOrientationchange)
 
-  DEFINE_ATTRIBUTE_EVENT_LISTENER(pageconceal, kPageconceal)
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(pageswap, kPageswap)
 
   DEFINE_ATTRIBUTE_EVENT_LISTENER(pagereveal, kPagereveal)
 
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
index 44fb3b3..3d57ede 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -69,7 +69,7 @@
 #include "third_party/blink/renderer/core/paint/timing/paint_timing.h"
 #include "third_party/blink/renderer/core/script/classic_script.h"
 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
-#include "third_party/blink/renderer/core/view_transition/page_conceal_event.h"
+#include "third_party/blink/renderer/core/view_transition/page_swap_event.h"
 #include "third_party/blink/renderer/core/view_transition/view_transition_supplement.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h"
 #include "third_party/blink/renderer/platform/widget/frame_widget.h"
@@ -1348,17 +1348,17 @@
 }
 
 void LocalFrameMojoHandler::SnapshotDocumentForViewTransition(
-    mojom::blink::PageConcealEventParamsPtr params,
+    mojom::blink::PageSwapEventParamsPtr params,
     SnapshotDocumentForViewTransitionCallback callback) {
   ViewTransitionSupplement::SnapshotDocumentForNavigation(
       *frame_->GetDocument(), std::move(params), std::move(callback));
 }
 
-void LocalFrameMojoHandler::DispatchPageConceal(
-    mojom::blink::PageConcealEventParamsPtr params) {
-  auto* page_conceal_event = MakeGarbageCollected<PageConcealEvent>(
+void LocalFrameMojoHandler::DispatchPageSwap(
+    mojom::blink::PageSwapEventParamsPtr params) {
+  auto* page_swap_event = MakeGarbageCollected<PageSwapEvent>(
       *frame_->GetDocument(), std::move(params), nullptr);
-  frame_->GetDocument()->domWindow()->DispatchEvent(*page_conceal_event);
+  frame_->GetDocument()->domWindow()->DispatchEvent(*page_swap_event);
 }
 
 void LocalFrameMojoHandler::DispatchBeforeUnload(
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
index 5d38d56..ab3748f 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
@@ -211,9 +211,9 @@
       const std::string& page_state,
       bool is_browser_initiated) final;
   void SnapshotDocumentForViewTransition(
-      mojom::blink::PageConcealEventParamsPtr,
+      mojom::blink::PageSwapEventParamsPtr,
       SnapshotDocumentForViewTransitionCallback callback) final;
-  void DispatchPageConceal(mojom::blink::PageConcealEventParamsPtr) final;
+  void DispatchPageSwap(mojom::blink::PageSwapEventParamsPtr) final;
 
   void AddResourceTimingEntryForFailedSubframeNavigation(
       const FrameToken& subframe_token,
diff --git a/third_party/blink/renderer/core/frame/window.idl b/third_party/blink/renderer/core/frame/window.idl
index 1bdff0e..4e342b9 100644
--- a/third_party/blink/renderer/core/frame/window.idl
+++ b/third_party/blink/renderer/core/frame/window.idl
@@ -172,8 +172,8 @@
     //  90 is when rotated counter clockwise.
     [HighEntropy=Direct, MeasureAs=WindowOrientation, RuntimeEnabled=OrientationEvent] readonly attribute long orientation;
 
-    // Event handler attribute for the pageconceal event.
-    [RuntimeEnabled=PageConcealEvent] attribute EventHandler onpageconceal;
+    // Event handler attribute for the pageswap event.
+    [RuntimeEnabled=PageSwapEvent] attribute EventHandler onpageswap;
 
     // Event handler attribute for the pagereveal event.
     // https://drafts.csswg.org/css-view-transitions-2/#reveal-event
diff --git a/third_party/blink/renderer/core/style/computed_style_test.cc b/third_party/blink/renderer/core/style/computed_style_test.cc
index 58fe300..5db666f 100644
--- a/third_party/blink/renderer/core/style/computed_style_test.cc
+++ b/third_party/blink/renderer/core/style/computed_style_test.cc
@@ -880,19 +880,21 @@
   auto* light_declaration = ParseDeclarationBlock("color-scheme:light");
 
   StyleCascade cascade1(state);
+  cascade1.MutableMatchResult().BeginAddingAuthorRulesForTreeScope(document);
   cascade1.MutableMatchResult().AddMatchedProperties(color_declaration,
-                                                     CascadeOrigin::kNone);
+                                                     CascadeOrigin::kAuthor);
   cascade1.MutableMatchResult().AddMatchedProperties(dark_declaration,
-                                                     CascadeOrigin::kNone);
+                                                     CascadeOrigin::kAuthor);
   cascade1.Apply();
   const ComputedStyle* style = state.StyleBuilder().CloneStyle();
   EXPECT_EQ(Color::kWhite, style->VisitedDependentColor(GetCSSPropertyColor()));
 
   StyleCascade cascade2(state);
+  cascade2.MutableMatchResult().BeginAddingAuthorRulesForTreeScope(document);
   cascade2.MutableMatchResult().AddMatchedProperties(color_declaration,
-                                                     CascadeOrigin::kNone);
+                                                     CascadeOrigin::kAuthor);
   cascade2.MutableMatchResult().AddMatchedProperties(light_declaration,
-                                                     CascadeOrigin::kNone);
+                                                     CascadeOrigin::kAuthor);
   cascade2.Apply();
   style = state.StyleBuilder().CloneStyle();
   EXPECT_EQ(Color::kBlack, style->VisitedDependentColor(GetCSSPropertyColor()));
@@ -922,20 +924,22 @@
   auto* light_declaration = ParseDeclarationBlock("color-scheme:light");
 
   StyleCascade cascade1(state);
+  cascade1.MutableMatchResult().BeginAddingAuthorRulesForTreeScope(document);
   cascade1.MutableMatchResult().AddMatchedProperties(bgimage_declaration,
-                                                     CascadeOrigin::kNone);
+                                                     CascadeOrigin::kAuthor);
   cascade1.MutableMatchResult().AddMatchedProperties(dark_declaration,
-                                                     CascadeOrigin::kNone);
+                                                     CascadeOrigin::kAuthor);
   cascade1.Apply();
   EXPECT_TRUE(state.TakeStyle()->HasBackgroundImage());
 
   state.SetStyle(*initial);
 
   StyleCascade cascade2(state);
+  cascade2.MutableMatchResult().BeginAddingAuthorRulesForTreeScope(document);
   cascade2.MutableMatchResult().AddMatchedProperties(bgimage_declaration,
-                                                     CascadeOrigin::kNone);
+                                                     CascadeOrigin::kAuthor);
   cascade2.MutableMatchResult().AddMatchedProperties(light_declaration,
-                                                     CascadeOrigin::kNone);
+                                                     CascadeOrigin::kAuthor);
   cascade2.Apply();
   EXPECT_FALSE(state.TakeStyle()->HasBackgroundImage());
 }
diff --git a/third_party/blink/renderer/core/view_transition/build.gni b/third_party/blink/renderer/core/view_transition/build.gni
index f7073f6..e7f4bcc 100644
--- a/third_party/blink/renderer/core/view_transition/build.gni
+++ b/third_party/blink/renderer/core/view_transition/build.gni
@@ -5,10 +5,10 @@
 blink_core_sources_view_transition = [
   "dom_view_transition.cc",
   "dom_view_transition.h",
-  "page_conceal_event.cc",
-  "page_conceal_event.h",
   "page_reveal_event.cc",
   "page_reveal_event.h",
+  "page_swap_event.cc",
+  "page_swap_event.h",
   "view_transition.cc",
   "view_transition.h",
   "view_transition_content_element.cc",
diff --git a/third_party/blink/renderer/core/view_transition/page_conceal_event.cc b/third_party/blink/renderer/core/view_transition/page_swap_event.cc
similarity index 76%
rename from third_party/blink/renderer/core/view_transition/page_conceal_event.cc
rename to third_party/blink/renderer/core/view_transition/page_swap_event.cc
index dfcc1e0..9df3b41f 100644
--- a/third_party/blink/renderer/core/view_transition/page_conceal_event.cc
+++ b/third_party/blink/renderer/core/view_transition/page_swap_event.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/view_transition/page_conceal_event.h"
+#include "third_party/blink/renderer/core/view_transition/page_swap_event.h"
 
 #include "third_party/blink/public/common/page_state/page_state.h"
 #include "third_party/blink/renderer/core/event_interface_names.h"
@@ -38,25 +38,25 @@
 
 }  // namespace
 
-PageConcealEvent::PageConcealEvent(
+PageSwapEvent::PageSwapEvent(
     Document& document,
-    mojom::blink::PageConcealEventParamsPtr page_conceal_event_params,
+    mojom::blink::PageSwapEventParamsPtr page_swap_event_params,
     DOMViewTransition* view_transition)
-    : Event(event_type_names::kPageconceal, Bubbles::kNo, Cancelable::kNo),
+    : Event(event_type_names::kPageswap, Bubbles::kNo, Cancelable::kNo),
       dom_view_transition_(view_transition) {
-  CHECK(RuntimeEnabledFeatures::PageConcealEventEnabled());
+  CHECK(RuntimeEnabledFeatures::PageSwapEventEnabled());
   CHECK(!view_transition ||
         RuntimeEnabledFeatures::ViewTransitionOnNavigationEnabled());
-  CHECK(!view_transition || page_conceal_event_params);
+  CHECK(!view_transition || page_swap_event_params);
 
-  if (page_conceal_event_params) {
+  if (page_swap_event_params) {
     NavigationApi* navigation = document.domWindow()->navigation();
 
     // The current entry could be null for the initial about:blank Document, a
     // detached window, or an opaque origin. We shouldn't be creating the
     // activation info for the first 2 cases:
-    // 1. We don't fire `pageconceal` on the initial about:blank Document.
-    // 2. We shouldn't be firing `pageconceal` for detached windows. The event
+    // 1. We don't fire `pageswap` on the initial about:blank Document.
+    // 2. We shouldn't be firing `pageswap` for detached windows. The event
     //    only fires when navigating away from a Document and there shouldn't be
     //    navigations in a detached window, i.e., a disconnected iframe.
     // 3. The activation info is only provided for same-origin navigations. An
@@ -65,7 +65,7 @@
     CHECK(from);
 
     NavigationHistoryEntry* entry = nullptr;
-    switch (page_conceal_event_params->navigation_type) {
+    switch (page_swap_event_params->navigation_type) {
       case mojom::blink::NavigationTypeForNavigationApi::kReload:
         entry = from;
         break;
@@ -74,7 +74,7 @@
         // rare race conditions.
         Member<HistoryItem> destination_item =
             HistoryItem::Create(PageState::CreateFromEncodedData(
-                page_conceal_event_params->page_state));
+                page_swap_event_params->page_state));
         entry = navigation->GetExistingEntryFor(
             destination_item->GetNavigationApiKey(),
             destination_item->GetNavigationApiId());
@@ -85,34 +85,34 @@
             document.domWindow(),
             /*key=*/WTF::CreateCanonicalUUIDString(),
             /*id=*/WTF::CreateCanonicalUUIDString(),
-            /*url=*/page_conceal_event_params->url,
+            /*url=*/page_swap_event_params->url,
             /*document_sequence_number=*/0,
             /*state=*/nullptr);
     }
 
     activation_ = MakeGarbageCollected<NavigationActivation>();
     activation_->Update(
-        entry, from, TypeToString(page_conceal_event_params->navigation_type));
+        entry, from, TypeToString(page_swap_event_params->navigation_type));
   }
 }
 
-PageConcealEvent::~PageConcealEvent() = default;
+PageSwapEvent::~PageSwapEvent() = default;
 
-const AtomicString& PageConcealEvent::InterfaceName() const {
-  return event_interface_names::kPageConcealEvent;
+const AtomicString& PageSwapEvent::InterfaceName() const {
+  return event_interface_names::kPageSwapEvent;
 }
 
-void PageConcealEvent::Trace(Visitor* visitor) const {
+void PageSwapEvent::Trace(Visitor* visitor) const {
   visitor->Trace(activation_);
   visitor->Trace(dom_view_transition_);
   Event::Trace(visitor);
 }
 
-DOMViewTransition* PageConcealEvent::viewTransition() const {
+DOMViewTransition* PageSwapEvent::viewTransition() const {
   return dom_view_transition_.Get();
 }
 
-NavigationActivation* PageConcealEvent::activation() const {
+NavigationActivation* PageSwapEvent::activation() const {
   return activation_.Get();
 }
 
diff --git a/third_party/blink/renderer/core/view_transition/page_conceal_event.h b/third_party/blink/renderer/core/view_transition/page_swap_event.h
similarity index 69%
rename from third_party/blink/renderer/core/view_transition/page_conceal_event.h
rename to third_party/blink/renderer/core/view_transition/page_swap_event.h
index c0b785cb..77f4ec68 100644
--- a/third_party/blink/renderer/core/view_transition/page_conceal_event.h
+++ b/third_party/blink/renderer/core/view_transition/page_swap_event.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_VIEW_TRANSITION_PAGE_CONCEAL_EVENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_VIEW_TRANSITION_PAGE_CONCEAL_EVENT_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_VIEW_TRANSITION_PAGE_SWAP_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_VIEW_TRANSITION_PAGE_SWAP_EVENT_H_
 
 #include "third_party/blink/public/mojom/navigation/navigation_params.mojom-blink.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
@@ -16,17 +16,17 @@
 class DOMViewTransition;
 class NavigationActivation;
 
-// Implementation for the pageconceal event. Fired before the Document is hidden
+// Implementation for the pageswap event. Fired before the Document is hidden
 // and unloaded or placed in the BFCache.
 // TODO(khushalsagar): Update spec link once it's settled.
-class PageConcealEvent final : public Event {
+class PageSwapEvent final : public Event {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  PageConcealEvent(Document&,
-                   mojom::blink::PageConcealEventParamsPtr,
+  PageSwapEvent(Document&,
+                   mojom::blink::PageSwapEventParamsPtr,
                    DOMViewTransition*);
-  ~PageConcealEvent() override;
+  ~PageSwapEvent() override;
 
   const AtomicString& InterfaceName() const override;
 
@@ -41,12 +41,12 @@
 };
 
 template <>
-struct DowncastTraits<PageConcealEvent> {
+struct DowncastTraits<PageSwapEvent> {
   static bool AllowFrom(const Event& event) {
-    return event.type() == event_type_names::kPageconceal;
+    return event.type() == event_type_names::kPageswap;
   }
 };
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_VIEW_TRANSITION_PAGE_CONCEAL_EVENT_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_VIEW_TRANSITION_PAGE_SWAP_EVENT_H_
diff --git a/third_party/blink/renderer/core/view_transition/page_conceal_event.idl b/third_party/blink/renderer/core/view_transition/page_swap_event.idl
similarity index 81%
rename from third_party/blink/renderer/core/view_transition/page_conceal_event.idl
rename to third_party/blink/renderer/core/view_transition/page_swap_event.idl
index 3f484f9..b4e21a9 100644
--- a/third_party/blink/renderer/core/view_transition/page_conceal_event.idl
+++ b/third_party/blink/renderer/core/view_transition/page_swap_event.idl
@@ -4,8 +4,8 @@
 
 [
   Exposed=Window,
-  RuntimeEnabled=PageConcealEvent
-] interface PageConcealEvent : Event {
+  RuntimeEnabled=PageSwapEvent
+] interface PageSwapEvent : Event {
   [RuntimeEnabled=ViewTransitionOnNavigation] readonly attribute ViewTransition? viewTransition;
   readonly attribute NavigationActivation? activation;
 };
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_supplement.cc b/third_party/blink/renderer/core/view_transition/view_transition_supplement.cc
index 153f545..2dc25499 100644
--- a/third_party/blink/renderer/core/view_transition/view_transition_supplement.cc
+++ b/third_party/blink/renderer/core/view_transition/view_transition_supplement.cc
@@ -15,7 +15,7 @@
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/view_transition/dom_view_transition.h"
-#include "third_party/blink/renderer/core/view_transition/page_conceal_event.h"
+#include "third_party/blink/renderer/core/view_transition/page_swap_event.h"
 #include "third_party/blink/renderer/core/view_transition/view_transition.h"
 #include "third_party/blink/renderer/core/view_transition/view_transition_utils.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -209,7 +209,7 @@
 // static
 void ViewTransitionSupplement::SnapshotDocumentForNavigation(
     Document& document,
-    mojom::blink::PageConcealEventParamsPtr params,
+    mojom::blink::PageSwapEventParamsPtr params,
     ViewTransition::ViewTransitionStateCallback callback) {
   DCHECK(RuntimeEnabledFeatures::ViewTransitionOnNavigationEnabled());
   auto* supplement = From(document);
@@ -218,7 +218,7 @@
 
 void ViewTransitionSupplement::StartTransition(
     Document& document,
-    mojom::blink::PageConcealEventParamsPtr params,
+    mojom::blink::PageSwapEventParamsPtr params,
     ViewTransition::ViewTransitionStateCallback callback) {
   if (transition_) {
     // We should skip a transition if one exists, regardless of how it was
@@ -230,9 +230,9 @@
   transition_ = ViewTransition::CreateForSnapshotForNavigation(
       &document, std::move(callback), this);
 
-  auto* page_conceal_event = MakeGarbageCollected<PageConcealEvent>(
+  auto* page_swap_event = MakeGarbageCollected<PageSwapEvent>(
       document, std::move(params), transition_->GetScriptDelegate());
-  document.domWindow()->DispatchEvent(*page_conceal_event);
+  document.domWindow()->DispatchEvent(*page_swap_event);
 }
 
 // static
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_supplement.h b/third_party/blink/renderer/core/view_transition/view_transition_supplement.h
index 88aabafa..a94319d 100644
--- a/third_party/blink/renderer/core/view_transition/view_transition_supplement.h
+++ b/third_party/blink/renderer/core/view_transition/view_transition_supplement.h
@@ -53,7 +53,7 @@
   // |ViewTransitionStateCallback|.
   static void SnapshotDocumentForNavigation(
       Document&,
-      mojom::blink::PageConcealEventParamsPtr,
+      mojom::blink::PageSwapEventParamsPtr,
       ViewTransition::ViewTransitionStateCallback);
 
   // Creates a ViewTransition using cached state from the previous Document
@@ -123,7 +123,7 @@
                                      const std::optional<Vector<String>>& types,
                                      ExceptionState& exception_state);
   void StartTransition(Document& document,
-                       mojom::blink::PageConcealEventParamsPtr,
+                       mojom::blink::PageSwapEventParamsPtr,
                        ViewTransition::ViewTransitionStateCallback callback);
   void StartTransition(Document& document,
                        ViewTransitionState transition_state);
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_test.cc b/third_party/blink/renderer/core/view_transition/view_transition_test.cc
index ff77149d..e26fb3c 100644
--- a/third_party/blink/renderer/core/view_transition/view_transition_test.cc
+++ b/third_party/blink/renderer/core/view_transition/view_transition_test.cc
@@ -1312,12 +1312,12 @@
   ScriptState* script_state = v8_scope.GetScriptState();
   ExceptionState& exception_state = v8_scope.GetExceptionState();
 
-  auto page_conceal_params = mojom::blink::PageConcealEventParams::New();
-  page_conceal_params->url = KURL("http://test.com");
-  page_conceal_params->navigation_type =
+  auto page_swap_params = mojom::blink::PageSwapEventParams::New();
+  page_swap_params->url = KURL("http://test.com");
+  page_swap_params->navigation_type =
       mojom::blink::NavigationTypeForNavigationApi::kPush;
   ViewTransitionSupplement::SnapshotDocumentForNavigation(
-      GetDocument(), std::move(page_conceal_params),
+      GetDocument(), std::move(page_swap_params),
       base::BindOnce([](const ViewTransitionState&) {}));
 
   ASSERT_TRUE(ViewTransitionSupplement::From(GetDocument())->GetTransition());
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index 8d23f1a..e92f115 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -104,9 +104,8 @@
 #include "third_party/blink/renderer/core/svg/svg_element.h"
 #include "third_party/blink/renderer/core/svg/svg_g_element.h"
 #include "third_party/blink/renderer/core/svg/svg_style_element.h"
+#include "third_party/blink/renderer/modules/accessibility/aria_notification.h"
 #include "third_party/blink/renderer/modules/accessibility/ax_enums.h"
-#include "ui/accessibility/ax_tree_id.h"
-#include "ui/accessibility/ax_tree_source.h"
 #if DCHECK_IS_ON()
 #include "third_party/blink/renderer/modules/accessibility/ax_debug_utils.h"
 #endif
@@ -133,6 +132,8 @@
 #include "ui/accessibility/ax_enums.mojom-blink-forward.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_tree_id.h"
+#include "ui/accessibility/ax_tree_source.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
 #include "ui/gfx/geometry/transform.h"
@@ -1304,6 +1305,32 @@
   return element->ExistingAccessibleNode();
 }
 
+namespace {
+
+void SerializeAriaNotificationAttributes(const AriaNotification& notification,
+                                         ui::AXNodeData* node_data) {
+  DCHECK(node_data);
+
+  TruncateAndAddStringAttribute(
+      node_data,
+      ax::mojom::blink::StringAttribute::kAriaNotificationAnnouncement,
+      notification.Announcement());
+
+  TruncateAndAddStringAttribute(
+      node_data, ax::mojom::blink::StringAttribute::kAriaNotificationId,
+      notification.NotificationId());
+
+  node_data->AddIntAttribute(
+      ax::mojom::blink::IntAttribute::kAriaNotificationInterrupt,
+      static_cast<int32_t>(notification.Interrupt()));
+
+  node_data->AddIntAttribute(
+      ax::mojom::blink::IntAttribute::kAriaNotificationPriority,
+      static_cast<int32_t>(notification.Priority()));
+}
+
+}  // namespace
+
 void AXObject::Serialize(ui::AXNodeData* node_data,
                          ui::AXMode accessibility_mode) {
   // Reduce redundant ancestor chain walking for display lock computations.
@@ -1403,6 +1430,10 @@
 
   SerializeOtherScreenReaderAttributes(node_data);
 
+  if (auto notification = AXObjectCache().RetrieveAriaNotification(this)) {
+    SerializeAriaNotificationAttributes(*notification, node_data);
+  }
+
   // Return early. The following attributes are unnecessary for ignored nodes.
   // Exception: focusable ignored nodes are fully serialized, so that reasonable
   // verbalizations can be made if they actually receive focus.
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index 0772305..7a0a056c 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -97,6 +97,7 @@
 #include "third_party/blink/renderer/core/style/content_data.h"
 #include "third_party/blink/renderer/core/svg/svg_graphics_element.h"
 #include "third_party/blink/renderer/core/svg/svg_style_element.h"
+#include "third_party/blink/renderer/modules/accessibility/aria_notification.h"
 #include "third_party/blink/renderer/modules/accessibility/ax_image_map_link.h"
 #include "third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h"
 #include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h"
@@ -3931,6 +3932,12 @@
   }
 }
 
+std::unique_ptr<AriaNotification> AXObjectCacheImpl::RetrieveAriaNotification(
+    const AXObject* obj) {
+  DCHECK(obj);
+  return aria_notifications_.Take(obj->AXObjectID());
+}
+
 void AXObjectCacheImpl::UpdateTableRoleWithCleanLayout(Node* table) {
   if (AXObject* ax_table = Get(table)) {
     if (ax_table->RoleValue() == ax::mojom::blink::Role::kLayoutTable &&
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
index 478956d..35ca6e1 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
@@ -39,14 +39,12 @@
 #include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink.h"
 #include "third_party/blink/public/mojom/render_accessibility.mojom-blink.h"
 #include "third_party/blink/public/web/web_ax_enums.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_aria_notification_options.h"
 #include "third_party/blink/renderer/core/accessibility/ax_object_cache_base.h"
 #include "third_party/blink/renderer/core/accessibility/blink_ax_event_intent.h"
 #include "third_party/blink/renderer/core/aom/computed_accessible_node.h"
 #include "third_party/blink/renderer/core/editing/commands/selection_for_undo_step.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/modules/accessibility/aria_notification.h"
 #include "third_party/blink/renderer/modules/accessibility/ax_object.h"
 #include "third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.h"
 #include "third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.h"
@@ -287,6 +285,9 @@
                               const String&,
                               const AriaNotificationOptions*) override;
 
+  std::unique_ptr<AriaNotification> RetrieveAriaNotification(
+      const AXObject*) override;
+
   void SetCanvasObjectBounds(HTMLCanvasElement*,
                              Element*,
                              const PhysicalRect&) override;
diff --git a/third_party/blink/renderer/modules/ml/ml_context.idl b/third_party/blink/renderer/modules/ml/ml_context.idl
index 4dbdeb8..9fa5cb84 100644
--- a/third_party/blink/renderer/modules/ml/ml_context.idl
+++ b/third_party/blink/renderer/modules/ml/ml_context.idl
@@ -27,8 +27,7 @@
   [
     RuntimeEnabled=MachineLearningNeuralNetwork,
     CallWith=ScriptState,
-    RaisesException,
-    Exposed=(Window, DedicatedWorker)
+    RaisesException
   ] Promise<MLComputeResult> compute(
       MLGraph graph, MLNamedArrayBufferViews inputs, MLNamedArrayBufferViews outputs);
 };
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl
index 72ef2d2..6528c46 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl
@@ -318,7 +318,6 @@
 
   [
     CallWith=ScriptState,
-    RaisesException,
-    Exposed=(Window, DedicatedWorker)
+    RaisesException
   ] Promise<MLGraph> build(MLNamedOperands outputs);
 };
diff --git a/third_party/blink/renderer/modules/printing/web_printer.cc b/third_party/blink/renderer/modules/printing/web_printer.cc
index 3704ed1..8c02c72 100644
--- a/third_party/blink/renderer/modules/printing/web_printer.cc
+++ b/third_party/blink/renderer/modules/printing/web_printer.cc
@@ -3,12 +3,15 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/modules/printing/web_printer.h"
+#include <limits>
 
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_web_print_document_description.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_web_print_job_template_attributes.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_web_printer_attributes.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_collection_requested.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_size_requested.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_web_printing_resolution.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/fileapi/blob.h"
@@ -25,6 +28,10 @@
 
 constexpr char kPrinterUnreachableError[] = "Unable to connect to the printer.";
 
+bool IsPositiveInt32(uint32_t value) {
+  return value > 0 && value <= std::numeric_limits<int32_t>::max();
+}
+
 bool ValidatePrintJobTemplateAttributes(
     const WebPrintJobTemplateAttributes* pjt_attributes,
     ExceptionState& exception_state) {
@@ -49,8 +56,20 @@
       return false;
     }
   }
+  if (pjt_attributes->hasMediaCol()) {
+    const auto& media_col = *pjt_attributes->mediaCol();
+    const auto& media_size = *media_col.mediaSize();
+    if (!IsPositiveInt32(media_size.yDimension()) ||
+        !IsPositiveInt32(media_size.xDimension())) {
+      exception_state.ThrowTypeError(
+          "Both `xDimension` and `yDimension` must be positive integer "
+          "values.");
+      return false;
+    }
+  }
   return true;
 }
+
 }  // namespace
 
 WebPrinter::WebPrinter(ExecutionContext* execution_context,
diff --git a/third_party/blink/renderer/modules/printing/web_printer_attributes.idl b/third_party/blink/renderer/modules/printing/web_printer_attributes.idl
index e41291e7..3093d7391e 100644
--- a/third_party/blink/renderer/modules/printing/web_printer_attributes.idl
+++ b/third_party/blink/renderer/modules/printing/web_printer_attributes.idl
@@ -17,9 +17,31 @@
   required Blob data;
 };
 
+typedef (WebPrintingRange or unsigned long) WebPrintingMediaSizeDimension;
+
+dictionary WebPrintingMediaSize {
+  WebPrintingMediaSizeDimension yDimension;
+  WebPrintingMediaSizeDimension xDimension;
+};
+
+dictionary WebPrintingMediaCollection {
+  DOMString mediaSizeName;
+  WebPrintingMediaSize mediaSize;
+};
+
+dictionary WebPrintingMediaSizeRequested {
+  required unsigned long yDimension;
+  required unsigned long xDimension;
+};
+
+dictionary WebPrintingMediaCollectionRequested {
+  required WebPrintingMediaSizeRequested mediaSize;
+};
+
 dictionary WebPrintJobTemplateAttributes {
   unsigned long copies;
 
+  WebPrintingMediaCollectionRequested mediaCol;
   WebPrintingMultipleDocumentHandling multipleDocumentHandling;
   WebPrintingOrientationRequested orientationRequested;
   WebPrintingResolution printerResolution;
@@ -34,6 +56,9 @@
   unsigned long copiesDefault;
   WebPrintingRange copiesSupported;
 
+  WebPrintingMediaCollection mediaColDefault;
+  sequence<WebPrintingMediaCollection> mediaColDatabase;
+
   WebPrintingMimeMediaType documentFormatDefault;
   sequence<WebPrintingMimeMediaType> documentFormatSupported;
 
diff --git a/third_party/blink/renderer/modules/printing/web_printing_type_converters.cc b/third_party/blink/renderer/modules/printing/web_printing_type_converters.cc
index 80ebff4..9536894 100644
--- a/third_party/blink/renderer/modules/printing/web_printing_type_converters.cc
+++ b/third_party/blink/renderer/modules/printing/web_printing_type_converters.cc
@@ -5,10 +5,15 @@
 #include "third_party/blink/renderer/modules/printing/web_printing_type_converters.h"
 
 #include "third_party/blink/public/mojom/printing/web_printing.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_unsignedlong_webprintingrange.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_web_print_color_mode.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_web_print_job_template_attributes.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_web_printer_attributes.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_web_printer_state.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_collection.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_collection_requested.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_size.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_web_printing_media_size_requested.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_web_printing_mime_media_type.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_web_printing_multiple_document_handling.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_web_printing_orientation_requested.h"
@@ -20,10 +25,27 @@
 #include "third_party/blink/renderer/platform/resolution_units.h"
 
 namespace {
+// copies:
+using BlinkRange = blink::WebPrintingRange;
+using MojomRangePtr = blink::mojom::blink::WebPrintingRangePtr;
+
 // sides:
 using V8Sides = blink::V8WebPrintingSides;
 using MojomSides = blink::mojom::blink::WebPrintingSides;
 
+// media-col:
+using BlinkMediaCollection = blink::WebPrintingMediaCollection;
+using BlinkMediaCollectionRequested =
+    blink::WebPrintingMediaCollectionRequested;
+using V8MediaSizeDimension = blink::V8UnionUnsignedLongOrWebPrintingRange;
+using MojomMediaCollection = blink::mojom::blink::WebPrintingMediaCollection;
+using MojomMediaCollectionRequested =
+    blink::mojom::blink::WebPrintingMediaCollectionRequested;
+using MojomMediaCollectionRequestedPtr =
+    blink::mojom::blink::WebPrintingMediaCollectionRequestedPtr;
+using MojomMediaSizeDimensionPtr =
+    blink::mojom::blink::WebPrintingMediaSizeDimensionPtr;
+
 // multiple-document-handling:
 using V8MultipleDocumentHandling = blink::V8WebPrintingMultipleDocumentHandling;
 using MojomMultipleDocumentHandling =
@@ -140,6 +162,58 @@
 };
 
 template <>
+struct TypeConverter<BlinkRange*, MojomRangePtr> {
+  static BlinkRange* Convert(const MojomRangePtr& range_in) {
+    auto* range = blink::MakeGarbageCollected<BlinkRange>();
+    range->setFrom(range_in->from);
+    range->setTo(range_in->to);
+    return range;
+  }
+};
+
+template <>
+struct TypeConverter<V8MediaSizeDimension*, MojomMediaSizeDimensionPtr> {
+  static V8MediaSizeDimension* Convert(
+      const MojomMediaSizeDimensionPtr& dimension) {
+    return dimension->is_range()
+               ? blink::MakeGarbageCollected<V8MediaSizeDimension>(
+                     mojo::ConvertTo<BlinkRange*>(dimension->get_range()))
+               : blink::MakeGarbageCollected<V8MediaSizeDimension>(
+                     dimension->get_value());
+  }
+};
+
+template <>
+struct TypeConverter<BlinkMediaCollection*, MojomMediaCollection*> {
+  static BlinkMediaCollection* Convert(
+      const MojomMediaCollection* media_col_in) {
+    auto* media_col = blink::MakeGarbageCollected<BlinkMediaCollection>();
+    media_col->setMediaSizeName(media_col_in->media_size_name);
+    auto* media_size =
+        blink::MakeGarbageCollected<blink::WebPrintingMediaSize>();
+    media_size->setYDimension(mojo::ConvertTo<V8MediaSizeDimension*>(
+        media_col_in->media_size->y_dimension));
+    media_size->setXDimension(mojo::ConvertTo<V8MediaSizeDimension*>(
+        media_col_in->media_size->x_dimension));
+    media_col->setMediaSize(media_size);
+    return media_col;
+  }
+};
+
+template <>
+struct TypeConverter<MojomMediaCollectionRequestedPtr,
+                     BlinkMediaCollectionRequested*> {
+  static MojomMediaCollectionRequestedPtr Convert(
+      const BlinkMediaCollectionRequested* media_col_in) {
+    auto media_col = MojomMediaCollectionRequested::New();
+    media_col->media_size = {
+        base::checked_cast<int32_t>(media_col_in->mediaSize()->xDimension()),
+        base::checked_cast<int32_t>(media_col_in->mediaSize()->yDimension())};
+    return media_col;
+  }
+};
+
+template <>
 struct TypeConverter<gfx::Size, blink::WebPrintingResolution*> {
   static gfx::Size Convert(
       const blink::WebPrintingResolution* printer_resolution) {
@@ -313,10 +387,8 @@
 void ProcessCopies(const mojom::blink::WebPrinterAttributes& new_attributes,
                    WebPrinterAttributes* current_attributes) {
   current_attributes->setCopiesDefault(new_attributes.copies_default);
-  auto* copies_range = WebPrintingRange::Create();
-  copies_range->setFrom(new_attributes.copies_supported->from);
-  copies_range->setTo(new_attributes.copies_supported->to);
-  current_attributes->setCopiesSupported(copies_range);
+  current_attributes->setCopiesSupported(
+      mojo::ConvertTo<BlinkRange*>(new_attributes.copies_supported));
 }
 
 void ProcessDocumentFormat(
@@ -328,6 +400,16 @@
       V8WebPrintingMimeMediaType::Enum::kApplicationPdf)});
 }
 
+void ProcessMediaCollection(
+    const mojom::blink::WebPrinterAttributes& new_attributes,
+    WebPrinterAttributes* current_attributes) {
+  current_attributes->setMediaColDefault(
+      mojo::ConvertTo<BlinkMediaCollection*>(new_attributes.media_col_default));
+  current_attributes->setMediaColDatabase(
+      mojo::ConvertTo<HeapVector<Member<BlinkMediaCollection>>>(
+          new_attributes.media_col_database));
+}
+
 void ProcessMultipleDocumentHandling(
     const mojom::blink::WebPrinterAttributes& new_attributes,
     WebPrinterAttributes* current_attributes) {
@@ -398,6 +480,7 @@
 
   blink::ProcessCopies(*printer_attributes, attributes);
   blink::ProcessDocumentFormat(*printer_attributes, attributes);
+  blink::ProcessMediaCollection(*printer_attributes, attributes);
   blink::ProcessMultipleDocumentHandling(*printer_attributes, attributes);
   blink::ProcessOrientationRequested(*printer_attributes, attributes);
   blink::ProcessPrinterResolution(*printer_attributes, attributes);
@@ -421,6 +504,10 @@
   auto attributes = blink::mojom::blink::WebPrintJobTemplateAttributes::New();
 
   attributes->copies = pjt_attributes->getCopiesOr(1);
+  if (pjt_attributes->hasMediaCol()) {
+    attributes->media_col = mojo::ConvertTo<MojomMediaCollectionRequestedPtr>(
+        pjt_attributes->mediaCol());
+  }
   if (pjt_attributes->hasMultipleDocumentHandling()) {
     attributes->multiple_document_handling =
         mojo::ConvertTo<MojomMultipleDocumentHandling>(
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 24538e4..582a01d9a 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -2467,6 +2467,12 @@
       name: "NoIdleEncodingForWebTests",
       status: "test",
     },
+    // Doesn't increase the end offset on getting the range for a new line
+    // character. See https://crbug.com/326888905
+    {
+      name: "NoIncreasingEndOffsetOnSplittingTextNodes",
+      status: "stable",
+    },
     // Makes enter/leave Mouse and Pointer Events non-composed as per
     // corresponding specifications.
     {
@@ -2716,11 +2722,6 @@
       name: "OverscrollCustomization",
       status: "experimental",
     },
-    {
-      name: "PageConcealEvent",
-      status: "experimental",
-      implied_by: ["ViewTransitionOnNavigation"],
-    },
     // The following are developer opt-outs and opt-ins for page freezing. If
     // neither is specified then heuristics will be applied to determine whether
     // the page is eligible.
@@ -2750,6 +2751,11 @@
       implied_by: ["ViewTransitionOnNavigation"],
     },
     {
+      name: "PageSwapEvent",
+      status: "experimental",
+      implied_by: ["ViewTransitionOnNavigation"],
+    },
+    {
       name: "PaintUnderInvalidationChecking",
       settable_from_internals: true,
     },
diff --git a/third_party/blink/tools/blinkpy/tool/blink_tool.py b/third_party/blink/tools/blinkpy/tool/blink_tool.py
index e0ed7f9..e28be99 100644
--- a/third_party/blink/tools/blinkpy/tool/blink_tool.py
+++ b/third_party/blink/tools/blinkpy/tool/blink_tool.py
@@ -41,7 +41,6 @@
 from blinkpy.common.host import Host
 from blinkpy.tool.commands.analyze_baselines import AnalyzeBaselines
 from blinkpy.tool.commands.command import HelpPrintingOptionParser
-from blinkpy.tool.commands.flaky_tests import FlakyTests
 from blinkpy.tool.commands.help_command import HelpCommand
 from blinkpy.tool.commands.optimize_baselines import OptimizeBaselines
 from blinkpy.tool.commands.pretty_diff import PrettyDiff
@@ -75,7 +74,6 @@
         self.commands = [
             AnalyzeBaselines(),
             CrashLog(),
-            FlakyTests(),
             OptimizeBaselines(),
             PrettyDiff(),
             PrintBaselines(),
diff --git a/third_party/blink/tools/blinkpy/tool/commands/flaky_tests.py b/third_party/blink/tools/blinkpy/tool/commands/flaky_tests.py
deleted file mode 100644
index 0670d88..0000000
--- a/third_party/blink/tools/blinkpy/tool/commands/flaky_tests.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# Copyright (c) 2011 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-from __future__ import print_function
-
-import logging
-
-from blinkpy.web_tests.layout_package.bot_test_expectations import BotTestExpectationsFactory
-from blinkpy.web_tests.models.typ_types import Expectation
-from blinkpy.web_tests.port.base import Port
-from blinkpy.tool.commands.command import Command
-
-_log = logging.getLogger(__name__)
-
-
-class FlakyTests(Command):
-    name = 'print-flaky-tests'
-    help_text = 'Print out flaky tests based on results from the flakiness dashboard'
-    show_in_main_help = True
-
-    FLAKINESS_DASHBOARD_URL = (
-        'https://test-results.appspot.com/dashboards/flakiness_dashboard.html'
-        '#testType=blink_web_tests&tests=%s')
-
-    BUG_TEMPLATE = (
-        'https://code.google.com/p/chromium/issues/entry?owner=FILL_ME_IN&status=Assigned&'
-        'labels=Pri-1,Cr-Blink,FlakyLayoutTest&summary=XXXXXXX%20is%20flaky&'
-        'comment=XXXXXXX%20is%20flaky.%0A%0AIt%20failed%20twice%20and%20then'
-        '%20passed%20on%20the%203rd%20or%204th%20retry.%20This%20is%20too%20'
-        'flaky.%20The%20test%20will%20be%20skipped%20until%20it%27s%20fixed.'
-        '%20If%20not%20fixed%20in%203%20months,%20it%20will%20be%20deleted%20'
-        'or%20perma-skipped.%0A%0AIn%20the%20flakiness%20dashboard,%20the%20'
-        'turquoise%20boxes%20are%20runs%20where%20the%20test%20failed%20and%20'
-        'then%20passed%20on%20retry.%0A%0Ahttps://test-results.appspot.com'
-        '/dashboards/flakiness_dashboard.html%23tests=XXXXXXX')
-
-    HEADER = (
-        'Manually add bug numbers for these and then put the lines in web_tests/TestExpectations.\n'
-        'Look up the test in the flakiness dashboard first to see if the the platform\n'
-        'specifiers should be made more general.\n\n'
-        'Bug template:\n%s\n') % BUG_TEMPLATE
-
-    OUTPUT = '%s\n%s\n\nFlakiness dashboard: %s\n'
-
-    def __init__(self):
-        super(FlakyTests, self).__init__()
-        # This is sorta silly, but allows for unit testing:
-        self.expectations_factory = BotTestExpectationsFactory
-
-    def _filter_build_type_specifiers(self, specifiers):
-        filtered = []
-        for specifier in specifiers:
-            if specifier.lower() not in Port.ALL_BUILD_TYPES:
-                filtered.append(specifier)
-        return filtered
-
-    def _collect_expectation_lines(self, builder_names, factory):
-        exps = []
-        for builder_name in builder_names:
-
-            expectations = factory.expectations_for_builder(builder_name)
-
-            # TODO(ojan): We should also skip bots that haven't uploaded recently,
-            # e.g. if they're >24h stale.
-            if not expectations:
-                _log.error("Can't load flakiness data for builder: %s",
-                           builder_name)
-                continue
-
-            for line in expectations.expectation_lines(
-                    only_consider_very_flaky=True):
-                # TODO(ojan): Find a way to merge specifiers instead of removing build types.
-                # We can't just union because some specifiers will change the meaning of others.
-                # For example, it's not clear how to merge [ Mac Release ] with [ Linux Debug ].
-                # But, in theory we should be able to merge [ Mac Release ] and [ Mac Debug ].
-                tags = self._filter_build_type_specifiers(line.tags)
-                exps.append(
-                    Expectation(
-                        tags=tags, results=line.results, test=line.test))
-        return exps
-
-    def execute(self, options, args, tool):
-        factory = self.expectations_factory(tool.builders)
-        lines = self._collect_expectation_lines(
-            tool.builders.all_continuous_builder_names(), factory)
-        lines.sort(key=lambda line: line.test)
-
-        port = tool.port_factory.get()
-        # Skip any tests which are mentioned in the dashboard but not in our checkout:
-        fs = tool.filesystem
-        lines = [
-            line for line in lines
-            if fs.exists(fs.join(port.web_tests_dir(), line.test))
-        ]
-
-        test_names = [line.test for line in lines]
-        flakiness_dashboard_url = self.FLAKINESS_DASHBOARD_URL % \
-            ','.join(test_names)
-        expectations_string = '\n'.join(line.to_string() for line in lines)
-
-        print(self.OUTPUT %
-              (self.HEADER, expectations_string, flakiness_dashboard_url))
diff --git a/third_party/blink/tools/blinkpy/tool/commands/flaky_tests_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/flaky_tests_unittest.py
deleted file mode 100644
index c81ef56..0000000
--- a/third_party/blink/tools/blinkpy/tool/commands/flaky_tests_unittest.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# Copyright 2014 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import optparse
-
-from blinkpy.tool.commands import flaky_tests
-from blinkpy.tool.commands.command_test import CommandsTest
-from blinkpy.tool.mock_tool import MockBlinkTool
-from blinkpy.web_tests.builder_list import BuilderList
-from blinkpy.web_tests.layout_package import bot_test_expectations
-
-
-class FakeBotTestExpectations(object):
-    def expectation_lines(self):
-        return []
-
-
-class FakeBotTestExpectationsFactory(object):
-    FAILURE_MAP = {
-        'C': 'CRASH',
-        'F': 'FAIL',
-        'N': 'NO DATA',
-        'P': 'PASS',
-        'T': 'TIMEOUT',
-        'Y': 'NOTRUN',
-        'X': 'SKIP',
-        'K': 'LEAK'
-    }
-
-    def __init__(self, builders):
-        self.builders = builders
-
-    def _expectations_from_test_data(self, builder, test_data):
-        test_data[bot_test_expectations.ResultsJSON.
-                  FAILURE_MAP_KEY] = self.FAILURE_MAP
-        json_dict = {
-            builder: test_data,
-        }
-        results = bot_test_expectations.ResultsJSON(builder, json_dict)
-        return bot_test_expectations.BotTestExpectations(
-            results, self.builders,
-            self.builders.specifiers_for_builder(builder))
-
-    def expectations_for_builder(self, builder):
-        if builder == 'foo-builder':
-            return self._expectations_from_test_data(
-                builder, {
-                    'tests': {
-                        'pass.html': {
-                            'results': [[2, 'FFFP']],
-                            'expected': 'PASS'
-                        },
-                    }
-                })
-
-        if builder == 'bar-builder':
-            return self._expectations_from_test_data(
-                builder, {
-                    'tests': {
-                        'pass.html': {
-                            'results': [[2, 'TTTP']],
-                            'expected': 'PASS'
-                        },
-                    }
-                })
-
-        return FakeBotTestExpectations()
-
-
-class FlakyTestsTest(CommandsTest):
-    @staticmethod
-    def fake_builders_list():
-        return BuilderList({
-            'foo-builder': {
-                'port_name': 'dummy-port',
-                'specifiers': ['Linux', 'Release']
-            },
-            'bar-builder': {
-                'port_name': 'dummy-port',
-                'specifiers': ['Mac', 'Debug']
-            },
-        })
-
-    def test_merge_lines(self):
-        command = flaky_tests.FlakyTests()
-        factory = FakeBotTestExpectationsFactory(self.fake_builders_list())
-
-        lines = command._collect_expectation_lines(
-            ['foo-builder', 'bar-builder'], factory)
-        self.assertEqual(len(lines), 2)
-        self.assertEqual(lines[0].results, set(['FAIL', 'PASS']))
-        self.assertEqual(set(lines[0].tags), set(['Linux']))
-        self.assertEqual(lines[1].results, set(['TIMEOUT', 'PASS']))
-        self.assertEqual(set(lines[1].tags), set(['Mac']))
-
-    def test_integration(self):
-        command = flaky_tests.FlakyTests()
-        tool = MockBlinkTool()
-        tool.builders = self.fake_builders_list()
-        command.expectations_factory = FakeBotTestExpectationsFactory
-        options = optparse.Values({'upload': True})
-        expected_stdout = flaky_tests.FlakyTests.OUTPUT % (
-            flaky_tests.FlakyTests.HEADER, '',
-            flaky_tests.FlakyTests.FLAKINESS_DASHBOARD_URL % '') + '\n'
-
-        self.assert_execute_outputs(
-            command,
-            options=options,
-            tool=tool,
-            expected_stdout=expected_stdout)
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite b/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite
index 9583acb..e0daee2 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite
+++ b/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite
@@ -31,6 +31,10 @@
 crbug.com/1518086 external/wpt/html/semantics/embedded-content/media-elements/ready-states/autoplay-hidden.optional.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 virtual/view-transition-mpa-serialization/external/wpt/css/css-view-transitions/pseudo-with-classes-entry.html [ Failure ]
+crbug.com/626703 virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/new-and-old-sizes-match.html [ Failure ]
+crbug.com/626703 virtual/view-transition/external/wpt/css/css-view-transitions/new-content-container-writing-modes.html [ Failure ]
+crbug.com/626703 virtual/view-transition/external/wpt/css/css-view-transitions/pseudo-with-classes-multiple-vt-classes.html [ Failure ]
 crbug.com/626703 virtual/view-transition-mpa-serialization/external/wpt/css/css-view-transitions/content-with-clip-root.html [ Failure ]
 crbug.com/626703 virtual/view-transition-mpa-serialization/external/wpt/css/css-view-transitions/pseudo-with-classes-match-multiple-wildcard.html [ Failure ]
 crbug.com/626703 virtual/view-transition-mpa-serialization/external/wpt/css/css-view-transitions/massive-element-left-of-viewport-partially-onscreen-new.html [ Failure ]
diff --git a/third_party/blink/web_tests/MSANExpectations b/third_party/blink/web_tests/MSANExpectations
index 2f7b31c..63d3279 100644
--- a/third_party/blink/web_tests/MSANExpectations
+++ b/third_party/blink/web_tests/MSANExpectations
@@ -114,5 +114,3 @@
 
 crbug.com/1457275 [ Linux ] external/wpt/dom/ranges/Range-surroundContents.html [ Skip ]
 
-# Sheriff 2024-02-28
-crbug.com/326356909 [ Linux ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/* [ Crash ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index 5cc81f2..91a3a457 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -2117,7 +2117,7 @@
 crbug.com/1517744 external/wpt/wai-aria/role/tree-roles.html [ Skip ]
 
 # WebNN GPU backend is supported on Win11 by default.
-crbug.com/1500120 [ Win10.20h2 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/* [ Skip ]
+crbug.com/1500120 [ Win10.20h2 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/* [ Skip ]
 
 ######## Unload Deprecation
 # This is for tests in the "unload-allowed" virtual suite that
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 2dcc653c..61665e4122 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2633,24 +2633,24 @@
 
 # ====== New tests from wpt-importer added here ======
 crbug.com/626703 external/wpt/css/css-text-decor/text-shadow/svg-stroke.html [ Failure ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any.worker.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.worker.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.html [ Crash ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.worker.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/gemm.https.any.html [ Crash ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/gemm.https.any.worker.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any.worker.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any.worker.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker.html [ Crash ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker.html [ Crash Timeout ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/reduction.https.any.html [ Crash ]
-crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/reduction.https.any.worker.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any.worker.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.worker.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.html [ Crash ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.worker.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/gemm.https.any.html [ Crash ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/gemm.https.any.worker.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any.worker.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any.worker.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker.html [ Crash ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker.html [ Crash Timeout ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/reduction.https.any.html [ Crash ]
+crbug.com/626703 [ Win11-arm64 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/reduction.https.any.worker.html [ Crash Timeout ]
 crbug.com/626703 [ Mac12-arm64 ] external/wpt/css/css-pseudo/text-selection.html [ Timeout ]
 crbug.com/626703 external/wpt/quirks/line-height-preserved-segment-break.html [ Failure ]
 crbug.com/626703 [ Win11-arm64 ] virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event.html [ Failure Timeout ]
@@ -2697,8 +2697,8 @@
 crbug.com/626703 external/wpt/html/rendering/widgets/button-layout/input-type-button-clip.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/text-justify/text-justify-word-separators.html [ Failure ]
 crbug.com/626703 external/wpt/svg/pservers/reftests/gradient-color-interpolation.svg [ Failure ]
-crbug.com/626703 virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any.html [ Skip Timeout ]
-crbug.com/626703 virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any.worker.html [ Crash ]
+crbug.com/626703 virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any.html [ Skip Timeout ]
+crbug.com/626703 virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any.worker.html [ Crash ]
 crbug.com/626703 external/wpt/css/css-page/page-orientation-on-landscape-001-print.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-page/page-orientation-on-portrait-001-print.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-page/page-orientation-on-square-001-print.html [ Failure ]
@@ -2707,7 +2707,7 @@
 crbug.com/626703 virtual/backface-visibility-interop/external/wpt/css/css-transforms/transform-box/svgbox-stroke-box-003.html [ Failure ]
 crbug.com/626703 virtual/backface-visibility-interop/external/wpt/css/css-transforms/transform-box/svgbox-stroke-box-004.html [ Failure ]
 crbug.com/626703 external/wpt/webnn/conformance_tests/elementwise_logical.https.any.worker.html [ Skip Timeout ]
-crbug.com/626703 virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elementwise_logical.https.any.worker.html [ Skip Timeout ]
+crbug.com/626703 virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_logical.https.any.worker.html [ Skip Timeout ]
 crbug.com/626703 [ Mac ] external/wpt/pointerevents/pointerevent_after_target_appended.html?mouse [ Timeout ]
 crbug.com/626703 external/wpt/css/css-nesting/has-nesting.html [ Failure ]
 crbug.com/626703 [ Release Win11-arm64 ] external/wpt/png/apng/fcTL-blend-source-nearly-transparent.html [ Timeout ]
@@ -6879,8 +6879,8 @@
 crbug.com/326478175 wpt_internal/dom/about_srcdoc/grandparent_location_aboutsrcdoc.sub.window.html [ Failure Pass Timeout ]
 
 # Test infra bug
-crbug.com/326459000 virtual/view-transition-on-navigation/wpt_internal/view-transition-on-navigation/pageconceal-push-from-click.html [ Timeout ]
-crbug.com/326459000 virtual/pageconceal/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-from-click.html [ Timeout ]
+crbug.com/326459000 virtual/view-transition-on-navigation/wpt_internal/view-transition-on-navigation/pageswap-push-from-click.html [ Timeout ]
+crbug.com/326459000 virtual/pageswap/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-from-click.html [ Timeout ]
 
 crbug.com/1467464 http/tests/devtools/network/network-columns-visible.js [ Failure Pass Timeout ]
 crbug.com/1467464 http/tests/devtools/security/origin-view-ct-compliance.js [ Failure Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 30cf3f9..edec759 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1401,7 +1401,7 @@
     "owners": ["view-transitions-api@chromium.org"],
     "bases": ["wpt_internal/view-transition-on-navigation"],
     "exclusive_tests": "ALL",
-    "args": ["--enable-features=ViewTransitionOnNavigation,PageConcealEvent",
+    "args": ["--enable-features=ViewTransitionOnNavigation,PageSwapEvent",
              "--enable-threaded-compositing"],
     "expires": "May 1, 2024"
   },
@@ -2566,9 +2566,12 @@
     "args": ["--enable-features=GenericSensorExtraClasses"],
     "expires": "never"
   },
+  "Run the WebNN WPTs with the WebNN service enabled. These are confusingly ",
+  "named 'gpu' tests however this really means that the WebNN Mojo service ",
+  "is used instead of the renderer-only implementation built using XNNPACK.",
   {
-    "prefix": "webnn-service-enabled",
-    "platforms": ["Linux", "Win"],
+    "prefix": "webnn-service-with-gpu",
+    "platforms": ["Win"],
     "bases": [
       "external/wpt/webnn/conformance_tests/gpu"
     ],
@@ -2577,6 +2580,19 @@
     "expires": "Jun 1, 2024",
     "owners": ["rafael.cintron@microsoft.com", "ningxin.hu@intel.com", "kbr@chromium.org"]
   },
+  "The WebNN service on Linux doesn't use the GPU (for now) and can't run ",
+  "under MSan so a separate flag configuration is defined here.",
+  {
+    "prefix": "webnn-service-without-gpu",
+    "platforms": ["Linux"],
+    "bases": [
+      "external/wpt/webnn/conformance_tests/gpu"
+    ],
+    "exclusive_tests": "ALL",
+    "args": ["--enable-features=WebMachineLearningNeuralNetwork"],
+    "expires": "Jun 1, 2024",
+    "owners": ["rafael.cintron@microsoft.com", "ningxin.hu@intel.com", "kbr@chromium.org"]
+  },
   {
     "prefix": "unload-allowed",
     "platforms": ["Linux", "Mac", "Win"],
@@ -2734,11 +2750,11 @@
     "owners": ["evelynn.kaplan@microsoft.com", "almaher@microsoft.com"]
   },
   {
-    "prefix": "pageconceal",
+    "prefix": "pageswap",
     "platforms": ["Linux", "Mac", "Win"],
     "exclusive_tests": "ALL",
-    "bases": ["external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal"],
-    "args": ["--enable-features=PageConcealEvent"],
+    "bases": ["external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap"],
+    "args": ["--enable-features=PageSwapEvent"],
     "expires": "June 1, 2024",
     "owners": ["khushalsagar@chromium.org", "vmpstr@chromium.org"]
   },
diff --git a/third_party/blink/web_tests/editing/execCommand/indent/indent_pre_with_new_lines.html b/third_party/blink/web_tests/editing/execCommand/indent/indent_pre_with_new_lines.html
new file mode 100644
index 0000000..77a9300
--- /dev/null
+++ b/third_party/blink/web_tests/editing/execCommand/indent/indent_pre_with_new_lines.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../assert_selection.js"></script>
+<div id="log"></div>
+<script>
+test(() => {
+  assert_selection(
+    '<div contenteditable style="white-space: pre">^\nHello|</div>',
+    'indent',
+    '<div contenteditable style="white-space: pre"><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">^\nHello|</blockquote></div>');
+}, 'Indent a block that preserves white spaces. The block has texts started with a new line.');
+test(() => {
+  assert_selection(
+    '<div contenteditable style="white-space: pre">^\n<div>Hello|</div></div>',
+    'indent',
+    '<div contenteditable style="white-space: pre"><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">^\n<div>Hello|</div></blockquote></div>');
+}, 'Indent a block that preserves white spaces. The block has a new line text and a div.');
+</script>
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 64720ab..dc929ad 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
@@ -260306,7 +260306,7 @@
           ]
          ],
          "canvas-filter-object-turbulence.html": [
-          "b5b494825e7a714be3326cd052078c9b5c780a92",
+          "fe87d37930123e3e1113b14b620fdc5a0de08edf",
           [
            null,
            [
@@ -260315,7 +260315,23 @@
              "=="
             ]
            ],
-           {}
+           {
+            "fuzzy": [
+             [
+              null,
+              [
+               [
+                0,
+                16
+               ],
+               [
+                0,
+                1000
+               ]
+              ]
+             ]
+            ]
+           }
           ]
          ],
          "idl-conversions": {
@@ -276560,7 +276576,22 @@
       ],
       {}
      ]
-    ]
+    ],
+    "errors": {
+     "unknown-ancillary-error-recovery.html": [
+      "df37153fd76026be581c4da33f9df0fd60e2c05b",
+      [
+       null,
+       [
+        [
+         "/png/errors/unknown-ancillary-error-recovery-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ]
+    }
    },
    "preload": {
     "preload-in-data-doc.html": [
@@ -316750,7 +316781,7 @@
       []
      ],
      "highlight-pseudo-computed-expected.txt": [
-      "34d8abea11982a5784f3ebf4fb0b42d9b67537cd",
+      "a5f58429dcaebab1c37a653544fc478c052575a8",
       []
      ],
      "painting": {
@@ -338786,7 +338817,7 @@
       []
      ],
      "getComputedStyle-pseudo-with-argument-expected.txt": [
-      "8ca2b6411e71068844959637a3014128b868b431",
+      "07f3a7b88c141486ea6873c825a20dfbecfb8362",
       []
      ],
      "getComputedStyle-width-scroll.tentative-expected.txt": [
@@ -376692,6 +376723,22 @@
      "de7629453d91d09551fdfcbe51c90cda494e6fcf",
      []
     ],
+    "errors": {
+     "support": {
+      "invalid-unknown-ancillary.png": [
+       "21373a5a5aff91c2755cdc9a7f381da29658850c",
+       []
+      ],
+      "no-invalid-chunks.png": [
+       "6605d479854ba0d9e772b105f1b276b7c842a306",
+       []
+      ]
+     },
+     "unknown-ancillary-error-recovery-ref.html": [
+      "cfa2cbb6f14cc95cb5930dab38fa3fb11bda49bd",
+      []
+     ]
+    },
     "support": {
      "cICP-and-iCCP.png": [
       "71d88defc12b18b29d2c2dd4303e4bfb15d1a4c0",
@@ -442497,6 +442544,29 @@
        ]
       ]
      },
+     "reading-order": {
+      "reading-order-items-computed.html": [
+       "a8280337665d7779f59dac55d342d8224d262b94",
+       [
+        null,
+        {}
+       ]
+      ],
+      "reading-order-items-invalid.html": [
+       "eff5846e316cafce44f3c876c6a1ad9056a2d939",
+       [
+        null,
+        {}
+       ]
+      ],
+      "reading-order-items-valid.html": [
+       "d1ac7de64eb869dc585680f5bdde06839453c448",
+       [
+        null,
+        {}
+       ]
+      ]
+     },
      "textarea-display.html": [
       "44634e3c3bdb7187f14c24b922d098ee273f995d",
       [
@@ -603872,6 +603942,15 @@
     }
    },
    "private-aggregation": {
+    "protected-audience-auction-report-buyers-debug-mode-surface.https.html": [
+     "ddc2b6a3723071d7b0f21b0f17757a1f1c59e1c8",
+     [
+      null,
+      {
+       "timeout": "long"
+      }
+     ]
+    ],
     "protected-audience-surface-failure.https.html": [
      "b512afc25dbe99441a0c57638e7b11e2e0681f36",
      [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-viewport/line-height-ref.html b/third_party/blink/web_tests/external/wpt/css/css-viewport/line-height-ref.html
new file mode 100644
index 0000000..c755392
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-viewport/line-height-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<style>CSS zoom applies to line-height when specified and inherited</style>
+<link rel="author" title="Chris Harrelson" href="mailto:chrishtr@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-viewport/">
+<div style="line-height: 12px; font-size: 12px">
+  Double-spaced<br>12px font text
+</div>
+
+<hr>
+
+<div style="line-height: 24px; font-size: 24px;">
+  Double-spaced<br>12px font zoomed text
+</div>
+
+<hr>
+
+<div style="line-height: 12px; font-size: 12px">
+  <div style="line-height: 24px; font-size: 24px">
+    Double-spaced<br>12px font zoomed inherited text
+  </div>
+</div>
+
+<hr>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-viewport/line-height.html b/third_party/blink/web_tests/external/wpt/css/css-viewport/line-height.html
new file mode 100644
index 0000000..fa333be3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-viewport/line-height.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<style>CSS zoom applies to line-height when specified and inherited</style>
+<link rel="author" title="Chris Harrelson" href="mailto:chrishtr@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-viewport/">
+<link rel="match" href="line-height-ref.html">
+<div style="line-height: 12px; font-size: 12px">
+  Double-spaced<br>12px font text
+</div>
+
+<hr>
+
+<div style="line-height: 12px; font-size: 12px; zoom: 2">
+  Double-spaced<br>12px font zoomed text
+</div>
+
+<hr>
+
+<div style="line-height: 12px; font-size: 12px">
+  <div style="zoom:2">
+    Double-spaced<br>12px font zoomed inherited text
+  </div>
+</div>
+
+<hr>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-viewport/width-ref.html b/third_party/blink/web_tests/external/wpt/css/css-viewport/width-ref.html
new file mode 100644
index 0000000..5d2755f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-viewport/width-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<style>CSS zoom applies to width when specified and inherited</style>
+<link rel="author" title="Chris Harrelson" href="mailto:chrishtr@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-viewport/">
+<style>
+  #parent {
+    width: 100px;
+    background: red;
+  }
+  #child-zoomed {
+    width: inherit;
+    background: lime;
+    width: 200px;
+    height: 200px;
+  }
+  #child {
+    width: 200px;
+    height: 200px;
+    background: green;
+  }
+</style>
+<p>You should see two squares below. One lime, and one green.</p>
+<div id="parent">
+  <div id="child-zoomed"></div>
+  <div id="child"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-viewport/width.html b/third_party/blink/web_tests/external/wpt/css/css-viewport/width.html
new file mode 100644
index 0000000..b6d9753
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-viewport/width.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<style>CSS zoom applies to width when specified and inherited</style>
+<link rel="author" title="Chris Harrelson" href="mailto:chrishtr@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-viewport/">
+<link rel="match" href="width-ref.html">
+<style>
+  #parent {
+    width: 100px;
+    background: red;
+  }
+  #child-zoomed {
+    zoom: 2;
+    width: inherit;
+    background: lime;
+    height: 100px;
+  }
+  #child {
+    width: 200px;
+    height: 200px;
+    background: green;
+  }
+</style>
+<p>You should see two squares below. One lime, and one green.</p>
+<div id="parent">
+  <div id="child-zoomed"></div>
+  <div id="child"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-cross-origin.sub.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-cross-origin.sub.html
similarity index 83%
rename from third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-cross-origin.sub.html
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-cross-origin.sub.html
index bcc8a9f8..44479cf0 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-cross-origin.sub.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-cross-origin.sub.html
@@ -1,5 +1,5 @@
 <!DOCTYPE HTML>
-<title>Tests pageconceal for cross-origin navigations</title>
+<title>Tests pageswap for cross-origin navigations</title>
 <link rel="author" title="Khushal Sagar"  href="mailto:khushalsagar@chromium.org">
 <link rel="help" href="https://html.spec.whatwg.org/">
 <script src="/resources/testharness.js"></script>
@@ -7,7 +7,7 @@
 <script src="/resources/testdriver.js"></script>
 <script src="/resources/testdriver-vendor.js"></script>
 <script>
-const expectedUrl = "http://{{hosts[][www]}}:{{ports[http][0]}}/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-cross-origin.sub.html?new";
+const expectedUrl = "http://{{hosts[][www]}}:{{ports[http][0]}}/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-cross-origin.sub.html?new";
 
 const params = new URLSearchParams(location.search);
 // The page the popup navigates to.
@@ -21,7 +21,7 @@
 
 if (is_test_page) {
   const expectedUrl = location.href + "?new";
-  const expectedEvents = ["pageconceal", "pagehide"];
+  const expectedEvents = ["pageswap", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -40,15 +40,15 @@
           }
       }));
     });
-  }, `pageconceal on navigation from script`);
+  }, `pageswap on navigation from script`);
 } else if (is_popup_page) {
   onload = () => {
     requestAnimationFrame(() => requestAnimationFrame(() => {
       location.href = expectedUrl;
     }));
 
-    onpageconceal = (e) => {
-      window.opener.events.push("pageconceal");
+    onpageswap = (e) => {
+      window.opener.events.push("pageswap");
       if (e.activation != null)
         window.opener.events.push("activation");
       if (e.viewTransition != null)
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-iframe.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-iframe.html
similarity index 77%
rename from third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-iframe.html
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-iframe.html
index 4202cf0..05ca1a9 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-iframe.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-iframe.html
@@ -1,5 +1,5 @@
 <!DOCTYPE HTML>
-<title>Tests pageconceal dispatch on iframe Documents</title>
+<title>Tests pageswap dispatch on iframe Documents</title>
 <link rel="author" title="Khushal Sagar"  href="mailto:khushalsagar@chromium.org">
 <link rel="help" href="https://html.spec.whatwg.org/">
 <script src="/resources/testharness.js"></script>
@@ -12,18 +12,18 @@
 function runTest(frame) {
   let frameWindow = frame.contentWindow;
 
-  let pageconcealfired = false;
+  let pageswapfired = false;
   let expectedUrl = frameWindow.location.href + '?new';
-  frameWindow.onpageconceal = (e) => {
-      assert_equals(e.activation.entry.url, expectedUrl, 'activation url incorrect in pageconceal');
-      assert_equals(e.activation.navigationType, "push", 'navigation type incorrect in pageconceal');
-      assert_equals(e.activation.from, frameWindow.navigation.currentEntry, 'from entry incorrect in pageconceal');
+  frameWindow.onpageswap = (e) => {
+      assert_equals(e.activation.entry.url, expectedUrl, 'activation url incorrect in pageswap');
+      assert_equals(e.activation.navigationType, "push", 'navigation type incorrect in pageswap');
+      assert_equals(e.activation.from, frameWindow.navigation.currentEntry, 'from entry incorrect in pageswap');
       assert_false(e.activation.entry.sameDocument, 'new entry must be cross-document');
-      pageconcealfired = true;
+      pageswapfired = true;
   }
 
   frameWindow.onpagehide = (e) => {
-      assert_true(pageconcealfired, 'pageconceal not fired');
+      assert_true(pageswapfired, 'pageswap not fired');
       done();
   }
 
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-from-click.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-from-click.html
similarity index 85%
rename from third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-from-click.html
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-from-click.html
index a2a6eb9..936158c 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-from-click.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-from-click.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>pageconceal navigationactivation for push navigations from user click</title>
+<title>pageswap navigationactivation for push navigations from user click</title>
 <link rel="help" href="https://html.spec.whatwg.org/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -21,7 +21,7 @@
 
 if (is_test_page) {
   const expectedUrl = location.href + "?new";
-  const expectedEvents = ["pageconceal", expectedUrl, "push","from", "pagehide"];
+  const expectedEvents = ["pageswap", expectedUrl, "push","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -51,10 +51,10 @@
           }
       }));
     });
-  }, `pageconceal on navigation from user click`);
+  }, `pageswap on navigation from user click`);
 } else if (is_popup_page) {
-  onpageconceal = (e) => {
-    window.opener.events.push("pageconceal");
+  onpageswap = (e) => {
+    window.opener.events.push("pageswap");
     if (e.viewTransition != null)
       window.opener.events.push("transition");
     window.opener.events.push(e.activation.entry.url);
@@ -70,5 +70,5 @@
 }
 </script>
 <body>
-  <a id="nav_link" href='/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-from-click.html?new'>Click me</a>
+  <a id="nav_link" href='/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-from-click.html?new'>Click me</a>
  </body>
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-navigation-hidden-document.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation-hidden-document.html
similarity index 87%
rename from third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-navigation-hidden-document.html
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation-hidden-document.html
index fdff57c..0a69923 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-navigation-hidden-document.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation-hidden-document.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>Tests pageconceal dispatch on hidden Documents</title>
+<title>Tests pageswap dispatch on hidden Documents</title>
 <link rel="author" title="Khushal Sagar"  href="mailto:khushalsagar@chromium.org">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -21,7 +21,7 @@
 
 if (is_test_page) {
   const expectedUrl = location.href + "?new";
-  const expectedEvents = ["pageconceal", expectedUrl, "push","from", "pagehide"];
+  const expectedEvents = ["pageswap", expectedUrl, "push","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -40,7 +40,7 @@
           }
       }));
     });
-  }, `pageconceal on navigation from script`);
+  }, `pageswap on navigation from script`);
 } else if (is_popup_page) {
     onload = async () => {
       await test_driver.minimize_window();
@@ -50,8 +50,8 @@
       location.href = location.href.split('?')[0] + '?new';
     };
 
-    onpageconceal = (e) => {
-      window.opener.events.push("pageconceal");
+    onpageswap = (e) => {
+      window.opener.events.push("pageswap");
       if (e.viewTransition != null)
       window.opener.events.push("transition");
       window.opener.events.push(e.activation.entry.url);
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-navigation.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation.html
similarity index 86%
rename from third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-navigation.html
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation.html
index 57e12d9e..4542d7cae 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-navigation.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>pageconceal navigationactivation for push navigations</title>
+<title>pageswap navigationactivation for push navigations</title>
 <link rel="help" href="https://html.spec.whatwg.org/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -19,7 +19,7 @@
 
 if (is_test_page) {
   const expectedUrl = location.href + "?new";
-  const expectedEvents = ["pageconceal", expectedUrl, "push","from", "pagehide"];
+  const expectedEvents = ["pageswap", expectedUrl, "push","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -38,15 +38,15 @@
           }
       }));
     });
-  }, `pageconceal on navigation from script`);
+  }, `pageswap on navigation from script`);
 } else if (is_popup_page) {
   onload = () => {
     requestAnimationFrame(() => requestAnimationFrame(() => {
       location.href = location.href.split('?')[0] + '?new';
     }));
 
-    onpageconceal = (e) => {
-      window.opener.events.push("pageconceal");
+    onpageswap = (e) => {
+      window.opener.events.push("pageswap");
       if (e.viewTransition != null)
       window.opener.events.push("transition");
       window.opener.events.push(e.activation.entry.url);
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-with-redirect.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-redirect.html
similarity index 80%
rename from third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-with-redirect.html
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-redirect.html
index 9ad5ee7..8252fff8 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-with-redirect.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-redirect.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>pageconceal navigationactivation for push navigations with a same-origin redirect</title>
+<title>pageswap navigationactivation for push navigations with a same-origin redirect</title>
 <link rel="help" href="https://html.spec.whatwg.org/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -19,7 +19,7 @@
 
 if (is_test_page) {
   const expectedUrl = location.href + "?new";
-  const expectedEvents = ["pageconceal", expectedUrl, "push","from", "pagehide"];
+  const expectedEvents = ["pageswap", expectedUrl, "push","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -38,15 +38,15 @@
           }
       }));
     });
-  }, `pageconceal on navigation with same-origin redirect`);
+  }, `pageswap on navigation with same-origin redirect`);
 } else if (is_popup_page) {
   onload = () => {
     requestAnimationFrame(() => requestAnimationFrame(() => {
-      location.href = "/common/redirect.py?location=/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-push-with-redirect.html?new";
+      location.href = "/common/redirect.py?location=/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-redirect.html?new";
     }));
 
-    onpageconceal = (e) => {
-      window.opener.events.push("pageconceal");
+    onpageswap = (e) => {
+      window.opener.events.push("pageswap");
       if (e.viewTransition != null)
       window.opener.events.push("transition");
       window.opener.events.push(e.activation.entry.url);
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-reload-navigation.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-reload-navigation.html
similarity index 86%
rename from third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-reload-navigation.html
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-reload-navigation.html
index 0dd135c..f7539eb 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-reload-navigation.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-reload-navigation.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>pageconceal navigationactivation for replace navigations</title>
+<title>pageswap navigationactivation for replace navigations</title>
 <link rel="help" href="https://html.spec.whatwg.org/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -17,7 +17,7 @@
 
 if (is_test_page) {
   const expectedUrl = location.href.split('?')[0] + "?popup";
-  const expectedEvents = ["pageconceal", "entry", "reload","from", "pagehide"];
+  const expectedEvents = ["pageswap", "entry", "reload","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -37,7 +37,7 @@
           }
       }));
     });
-  }, `pageconceal on replace navigation from script`);
+  }, `pageswap on replace navigation from script`);
 } else if (is_popup_page) {
   onload = () => {
     requestAnimationFrame(() => requestAnimationFrame(() => {
@@ -45,8 +45,8 @@
       location.reload();
     }));
 
-    onpageconceal = (e) => {
-      window.opener.events.push("pageconceal");
+    onpageswap = (e) => {
+      window.opener.events.push("pageswap");
       if (e.viewTransition != null)
         window.opener.events.push("transition");
       if (e.activation.entry == navigation.currentEntry)
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-replace-navigation.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-replace-navigation.html
similarity index 85%
rename from third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-replace-navigation.html
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-replace-navigation.html
index 012439a..f6b3f74 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-replace-navigation.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-replace-navigation.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>pageconceal navigationactivation for replace navigations</title>
+<title>pageswap navigationactivation for replace navigations</title>
 <link rel="help" href="https://html.spec.whatwg.org/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -19,7 +19,7 @@
 
 if (is_test_page) {
   const expectedUrl = location.href.split('?')[0] + "?new";
-  const expectedEvents = ["pageconceal", expectedUrl, "replace","from", "pagehide"];
+  const expectedEvents = ["pageswap", expectedUrl, "replace","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -38,15 +38,15 @@
           }
       }));
     });
-  }, `pageconceal on replace navigation from script`);
+  }, `pageswap on replace navigation from script`);
 } else if (is_popup_page) {
   onload = () => {
     requestAnimationFrame(() => requestAnimationFrame(() => {
       location.replace(location.href.split('?')[0] + '?new');
     }));
 
-    onpageconceal = (e) => {
-      window.opener.events.push("pageconceal");
+    onpageswap = (e) => {
+      window.opener.events.push("pageswap");
       if (e.viewTransition != null)
         window.opener.events.push("transition");
       window.opener.events.push(e.activation.entry.url);
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-traverse-navigation-no-bfcache.https.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-traverse-navigation-no-bfcache.https.html
similarity index 88%
rename from third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-traverse-navigation-no-bfcache.https.html
rename to third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-traverse-navigation-no-bfcache.https.html
index c34c443b..9e8c0e1 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageconceal/pageconceal-traverse-navigation-no-bfcache.https.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-traverse-navigation-no-bfcache.https.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>pageconceal navigationactivation for traverse navigations</title>
+<title>pageswap navigationactivation for traverse navigations</title>
 <link rel="help" href="https://html.spec.whatwg.org/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -18,7 +18,7 @@
 // The test page which opens a popup for the navigation sequence.
 if (is_test_page) {
   const expectedUrl = location.href.split('?')[0] + "?popup";
-  const expectedEvents = ["pageconceal", expectedUrl, "traverse","from", "pagehide"];
+  const expectedEvents = ["pageswap", expectedUrl, "traverse","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -37,7 +37,7 @@
           }
       }));
     });
-  }, `pageconceal on traverse navigation from script`);
+  }, `pageswap on traverse navigation from script`);
 } else if (is_initial_page_first_navigation) {
   // The popup page which the user navigates back to.
   onload = async () => {
@@ -57,8 +57,8 @@
     }));
   };
 
-  onpageconceal = (e) => {
-    window.opener.events.push("pageconceal");
+  onpageswap = (e) => {
+    window.opener.events.push("pageswap");
     if (e.viewTransition != null)
       window.opener.events.push("transition");
     window.opener.events.push(e.activation.entry.url);
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html
index ff0eebe..ea5600b0 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html
@@ -1,28 +1,28 @@
 <body>
   <svg style="display:none">>
     <filter id="base">
-      <feTurbulence baseFrequency="0.025"/>
+      <feTurbulence baseFrequency="0.03125"/>
     </filter>
     <filter id="base2d">
-      <feTurbulence baseFrequency="0.025, 0.1"/>
+      <feTurbulence baseFrequency="0.03125, 0.125"/>
     </filter>
     <filter id="highFrequency">
-      <feTurbulence baseFrequency="0.05"/>
+      <feTurbulence baseFrequency="0.0625"/>
     </filter>
     <filter id="seed">
-      <feTurbulence baseFrequency="0.025" seed="100"/>
+      <feTurbulence baseFrequency="0.03125" seed="100"/>
     </filter>
     <filter id="numOctaves">
-      <feTurbulence baseFrequency="0.025" numOctaves="2"/>
+      <feTurbulence baseFrequency="0.03125" numOctaves="2"/>
     </filter>
     <filter id="empty">
       <feTurbulence/>
     </filter>
     <filter id="fractalNoise">
-      <feTurbulence baseFrequency="0.025" type="fractalNoise"/>
+      <feTurbulence baseFrequency="0.03125" type="fractalNoise"/>
     </filter>
     <filter id="stitchTiles">
-      <feTurbulence baseFrequency="0.025" stitchTiles="noStitch"/>
+      <feTurbulence baseFrequency="0.03125" stitchTiles="noStitch"/>
     </filter>
 </body>
 <script>
@@ -34,4 +34,4 @@
     ctx.filter = `url(#${tc.id})`;
     ctx.fillRect(0, 0, 1, 1);
   }
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html
index fe87d37..eb0803e4 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html
@@ -1,19 +1,18 @@
 <head>
     <link rel="match" href="canvas-filter-object-blur-expected.html">
-    <meta name=fuzzy content="maxDifference=0-16; totalPixels=0-1000">
 </head>
 <body>
 </body>
 <script>
   const testCases = [
-    {baseFrequency: 0.025},
-    {baseFrequency: [0.025, 0.1]},
-    {baseFrequency: 0.05},
-    {baseFrequency: 0.025, seed: 100},
-    {baseFrequency: 0.025, numOctaves: 2},
+    {baseFrequency: 0.03125},
+    {baseFrequency: [0.03125, 0.125]},
+    {baseFrequency: 0.0625},
+    {baseFrequency: 0.03125, seed: 100},
+    {baseFrequency: 0.03125, numOctaves: 2},
     {},
-    {baseFrequency: 0.025, type: "fractalNoise"},
-    {baseFrequency: 0.025, stitchTiles: "stitch"},
+    {baseFrequency: 0.03125, type: "fractalNoise"},
+    {baseFrequency: 0.03125, stitchTiles: "stitch"},
   ]
 
   for (tc of testCases) {
diff --git a/third_party/blink/web_tests/external/wpt/png/errors/support/invalid-unknown-ancillary.png b/third_party/blink/web_tests/external/wpt/png/errors/support/invalid-unknown-ancillary.png
new file mode 100644
index 0000000..21373a5a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/png/errors/support/invalid-unknown-ancillary.png
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/png/errors/support/no-invalid-chunks.png b/third_party/blink/web_tests/external/wpt/png/errors/support/no-invalid-chunks.png
new file mode 100644
index 0000000..6605d47
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/png/errors/support/no-invalid-chunks.png
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/png/errors/unknown-ancillary-error-recovery-ref.html b/third_party/blink/web_tests/external/wpt/png/errors/unknown-ancillary-error-recovery-ref.html
new file mode 100644
index 0000000..cfa2cbb6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/png/errors/unknown-ancillary-error-recovery-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<title>PNG Third Edition: Decoder error recovery, invalid ancillary</title>
+<link rel="author" title="Chris Lilley" href="mailto:chris@w3.org">
+<style>
+    .test {
+        width: 32px;
+        height: 32px;
+        background-color: green;
+    }
+</style>
+<body>
+    <p>Test passes if you see a rainbow square, and not a red one.</p>
+    <div class="test"><img src="support/no-invalid-chunks.png" alt=""></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/png/errors/unknown-ancillary-error-recovery.html b/third_party/blink/web_tests/external/wpt/png/errors/unknown-ancillary-error-recovery.html
new file mode 100644
index 0000000..df37153
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/png/errors/unknown-ancillary-error-recovery.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<title>PNG Third Edition: Decoder error recovery, invalid ancillary</title>
+<link rel="author" title="Chris Lilley" href="mailto:chris@w3.org">
+<link rel="help" href="https://www.w3.org/TR/png-3/#13Decoders.Errors">
+<link rel="help" href="https://github.com/w3c/PNG-spec/issues/320">
+<link rel="match" href="unknown-ancillary-error-recovery-ref.html">
+<meta name="assert" content="Encountering an unknown ancillary chunk is never an error. The chunk can simply be ignored.">
+<style>
+    .test {
+        width: 32px;
+        height: 32px;
+        background-color: red;
+    }
+</style>
+<body>
+    <p>Test passes if you see a rainbow square, and not a red one.</p>
+    <div class="test"><img src="support/invalid-unknown-ancillary.png" alt=""></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
index 4c92b68..147c50e 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -183,10 +183,10 @@
 PASS oldChildWindow.onoffline is newChildWindow.onoffline
 PASS oldChildWindow.ononline is newChildWindow.ononline
 PASS oldChildWindow.onoverscroll is newChildWindow.onoverscroll
-PASS oldChildWindow.onpageconceal is newChildWindow.onpageconceal
 PASS oldChildWindow.onpagehide is newChildWindow.onpagehide
 PASS oldChildWindow.onpagereveal is newChildWindow.onpagereveal
 PASS oldChildWindow.onpageshow is newChildWindow.onpageshow
+PASS oldChildWindow.onpageswap is newChildWindow.onpageswap
 PASS oldChildWindow.onpause is newChildWindow.onpause
 PASS oldChildWindow.onplay is newChildWindow.onplay
 PASS oldChildWindow.onplaying is newChildWindow.onplaying
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
index 4176fe4..79771b6 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
@@ -127,10 +127,10 @@
 PASS childWindow.onoffline is null
 PASS childWindow.ononline is null
 PASS childWindow.onoverscroll is null
-PASS childWindow.onpageconceal is null
 PASS childWindow.onpagehide is null
 PASS childWindow.onpagereveal is null
 PASS childWindow.onpageshow is null
+PASS childWindow.onpageswap is null
 PASS childWindow.onpause is null
 PASS childWindow.onplay is null
 PASS childWindow.onplaying is null
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
index c929a19c..51545f5e 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
@@ -127,10 +127,10 @@
 PASS childWindow.onoffline is null
 PASS childWindow.ononline is null
 PASS childWindow.onoverscroll is null
-PASS childWindow.onpageconceal is null
 PASS childWindow.onpagehide is null
 PASS childWindow.onpagereveal is null
 PASS childWindow.onpageshow is null
+PASS childWindow.onpageswap is null
 PASS childWindow.onpause is null
 PASS childWindow.onplay is null
 PASS childWindow.onplaying is null
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any.worker-expected.txt
copy to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/arg_min_max.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/batch_normalization.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/cast.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/cast.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/cast.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/cast.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/cast.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/cast.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/cast.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/cast.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/clamp.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/clamp.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/clamp.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/clamp.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/clamp.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/clamp.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/clamp.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/clamp.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/concat.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/concat.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/concat.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/concat.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/concat.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/concat.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/concat.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/concat.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/constant.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/constant.https.any-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/constant.https.any-expected.txt
copy to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/constant.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/constant.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/constant.https.any.worker-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/constant.https.any.worker-expected.txt
copy to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/constant.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elementwise_logical.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_logical.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elementwise_logical.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_logical.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elementwise_logical.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_logical.https.any.worker-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elementwise_logical.https.any-expected.txt
copy to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_logical.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elu.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elu.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elu.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elu.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elu.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elu.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elu.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/elu.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/expand.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/expand.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/expand.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/expand.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/expand.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/expand.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/expand.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/expand.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/gather.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/gather.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/gather.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/gather.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/gather.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/gather.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/gather.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/gather.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/gemm.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/gemm.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/gemm.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/gemm.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/gemm.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/gemm.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/gemm.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/gemm.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/hard_sigmoid.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/hard_sigmoid.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/hard_sigmoid.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/hard_sigmoid.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/hard_sigmoid.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/hard_sigmoid.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/hard_sigmoid.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/hard_sigmoid.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/hard_swish.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/hard_swish.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/hard_swish.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/hard_swish.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/hard_swish.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/hard_swish.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/hard_swish.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/hard_swish.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/instance_normalization.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/layer_normalization.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/leaky_relu.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/leaky_relu.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/leaky_relu.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/leaky_relu.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/leaky_relu.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/leaky_relu.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/leaky_relu.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/leaky_relu.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/linear.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/linear.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/linear.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/linear.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/linear.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/linear.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/linear.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/linear.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/matmul.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/matmul.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pad.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/pad.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pad.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/pad.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pad.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/pad.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pad.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/pad.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/prelu.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/prelu.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/prelu.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/prelu.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/prelu.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/prelu.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/prelu.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/prelu.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/reduction.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/reduction.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/reduction.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/reduction.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/reduction.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/reduction.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/reduction.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/reduction.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/relu.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/relu.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/relu.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/relu.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/relu.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/relu.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/relu.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/relu.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/reshape.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/reshape.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/reshape.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/reshape.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/reshape.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/reshape.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/reshape.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/reshape.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/sigmoid.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/sigmoid.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/sigmoid.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/sigmoid.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/sigmoid.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/sigmoid.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/sigmoid.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/sigmoid.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/slice.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/slice.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/slice.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/slice.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/slice.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/slice.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/slice.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/slice.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softmax.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softmax.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softmax.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softmax.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softmax.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softmax.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softmax.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softmax.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softplus.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softplus.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softplus.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softplus.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softplus.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softplus.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softplus.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softplus.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softsign.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softsign.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softsign.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softsign.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softsign.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softsign.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softsign.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/softsign.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/split.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/split.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/split.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/split.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/split.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/split.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/split.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/split.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/tanh.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/tanh.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/tanh.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/tanh.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/tanh.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/tanh.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/tanh.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/tanh.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/transpose.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/transpose.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/transpose.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/transpose.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/transpose.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/transpose.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/transpose.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/transpose.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/triangular.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/triangular.https.any-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/triangular.https.any-expected.txt
copy to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/triangular.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/triangular.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/triangular.https.any.worker-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/triangular.https.any.worker-expected.txt
copy to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/triangular.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/where.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/where.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/where.https.any-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/where.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/where.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/where.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/where.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/where.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/mac-mac12/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt b/third_party/blink/web_tests/platform/mac-mac12/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
new file mode 100644
index 0000000..2709251
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac12/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Smooth scroll in load event handler
+  assert_equals: Final value of scrollLeft expected 800 but got 0
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
new file mode 100644
index 0000000..2709251
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Smooth scroll in load event handler
+  assert_equals: Final value of scrollLeft expected 800 but got 0
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/cast.https.any-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/cast.https.any-expected.txt
copy to third_party/blink/web_tests/platform/mac/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/cast.https.any-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/cast.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/cast.https.any-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/cast.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/cast.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/cast.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/cast.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/cast.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/constant.https.any-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/constant.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/constant.https.any-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/constant.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/constant.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/constant.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/constant.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/constant.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/conv2d.https.any-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/conv2d.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/conv2d.https.any-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/conv2d.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/conv2d.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/conv2d.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/conv2d.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/conv2d.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/pooling.https.any-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/pooling.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/pooling.https.any-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/pooling.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/pooling.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/pooling.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/pooling.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/pooling.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/triangular.https.any-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/triangular.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/triangular.https.any-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/triangular.https.any-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/triangular.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/triangular.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-enabled/external/wpt/webnn/gpu/triangular.https.any.worker-expected.txt
rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/gpu/triangular.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/pageconceal/README.md b/third_party/blink/web_tests/virtual/pageconceal/README.md
deleted file mode 100644
index ccaa9522..0000000
--- a/third_party/blink/web_tests/virtual/pageconceal/README.md
+++ /dev/null
@@ -1 +0,0 @@
-This is a suite to run tests which dispatch a pageconceal event.
diff --git a/third_party/blink/web_tests/virtual/pageswap/README.md b/third_party/blink/web_tests/virtual/pageswap/README.md
new file mode 100644
index 0000000..d4119d5
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/pageswap/README.md
@@ -0,0 +1 @@
+This is a suite to run tests which dispatch a pageswap event.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/README.md b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/README.md
similarity index 75%
copy from third_party/blink/web_tests/virtual/webnn-service-enabled/README.md
copy to third_party/blink/web_tests/virtual/webnn-service-with-gpu/README.md
index 358a6dc..2d9b8af95 100644
--- a/third_party/blink/web_tests/virtual/webnn-service-enabled/README.md
+++ b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/README.md
@@ -1 +1,2 @@
 # This suite runs tests with --enable-features=WebMachineLearningNeuralNetwork
+# and --use-gpu-in-tests.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/cast.https.any-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/cast.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/cast.https.any-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/cast.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/cast.https.any.worker-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/cast.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/cast.https.any.worker-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/cast.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/constant.https.any-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/constant.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/constant.https.any-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/constant.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/constant.https.any.worker-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/constant.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/constant.https.any.worker-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/constant.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.worker-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.worker-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv2d.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.worker-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.worker-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/conv_transpose2d.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elu.https.any-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elu.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elu.https.any-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elu.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elu.https.any.worker-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elu.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/elu.https.any.worker-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elu.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/matmul.https.any-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/matmul.https.any-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/pooling.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softplus.https.any-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/softplus.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softplus.https.any-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/softplus.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softplus.https.any.worker-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/softplus.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/softplus.https.any.worker-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/softplus.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/squeeze.https.any-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/squeeze.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/squeeze.https.any-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/squeeze.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/squeeze.https.any.worker-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/squeeze.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/squeeze.https.any.worker-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/squeeze.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/triangular.https.any-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/triangular.https.any-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/triangular.https.any-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/triangular.https.any-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/triangular.https.any.worker-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/triangular.https.any.worker-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/external/wpt/webnn/conformance_tests/gpu/triangular.https.any.worker-expected.txt
rename to third_party/blink/web_tests/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/triangular.https.any.worker-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-enabled/README.md b/third_party/blink/web_tests/virtual/webnn-service-without-gpu/README.md
similarity index 79%
rename from third_party/blink/web_tests/virtual/webnn-service-enabled/README.md
rename to third_party/blink/web_tests/virtual/webnn-service-without-gpu/README.md
index 358a6dc..3daffa39 100644
--- a/third_party/blink/web_tests/virtual/webnn-service-enabled/README.md
+++ b/third_party/blink/web_tests/virtual/webnn-service-without-gpu/README.md
@@ -1 +1 @@
-# This suite runs tests with --enable-features=WebMachineLearningNeuralNetwork
+# This suite runs tests with --enable-features=WebMachineLearningNeuralNetwork.
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 3d1e05b1..1cbfa6dd 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -6974,13 +6974,13 @@
     getter deltaX
     getter deltaY
     method constructor
-interface PageConcealEvent : Event
-    attribute @@toStringTag
-    getter activation
-    method constructor
 interface PageRevealEvent : Event
     attribute @@toStringTag
     method constructor
+interface PageSwapEvent : Event
+    attribute @@toStringTag
+    getter activation
+    method constructor
 interface PageTransitionEvent : Event
     attribute @@toStringTag
     getter persisted
@@ -9418,6 +9418,7 @@
     method append
     method clear
     method constructor
+    method createWorklet
     method delete
     method run
     method selectURL
@@ -9426,6 +9427,8 @@
     attribute @@toStringTag
     method addModule
     method constructor
+    method run
+    method selectURL
 interface SharedWorker : EventTarget
     attribute @@toStringTag
     getter onerror
@@ -12722,10 +12725,10 @@
     getter onoffline
     getter ononline
     getter onoverscroll
-    getter onpageconceal
     getter onpagehide
     getter onpagereveal
     getter onpageshow
+    getter onpageswap
     getter onpause
     getter onplay
     getter onplaying
@@ -12954,10 +12957,10 @@
     setter onoffline
     setter ononline
     setter onoverscroll
-    setter onpageconceal
     setter onpagehide
     setter onpagereveal
     setter onpageshow
+    setter onpageswap
     setter onpause
     setter onplay
     setter onplaying
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-fired-before-old-state-capture-ref.html b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-fired-before-old-state-capture-ref.html
similarity index 80%
rename from third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-fired-before-old-state-capture-ref.html
rename to third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-fired-before-old-state-capture-ref.html
index 495fb6dd..bda3330 100644
--- a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-fired-before-old-state-capture-ref.html
+++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-fired-before-old-state-capture-ref.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>View transitions: Test pageconceal fires before document capture (ref)</title>
+<title>View transitions: Test pageswap fires before document capture (ref)</title>
 <link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <style>
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-fired-before-old-state-capture.html b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-fired-before-old-state-capture.html
similarity index 87%
rename from third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-fired-before-old-state-capture.html
rename to third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-fired-before-old-state-capture.html
index 3b3e5390..8ce791b 100644
--- a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-fired-before-old-state-capture.html
+++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-fired-before-old-state-capture.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <html class="reftest-wait">
-<title>View transitions: Test pageconceal fires before document capture</title>
+<title>View transitions: Test pageswap fires before document capture</title>
 <link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
-<link rel="match" href="pageconceal-fired-before-old-state-capture-ref.html">
+<link rel="match" href="pageswap-fired-before-old-state-capture-ref.html">
 <script src="/common/reftest-wait.js"></script>
 <script>
 const params = new URLSearchParams(location.search);
@@ -18,7 +18,7 @@
     });
   });
 } else {
-  addEventListener('pageconceal', e => {
+  addEventListener('pageswap', e => {
     document.documentElement.classList.add('oldPage');
   });
 
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-push-from-click.html b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-push-from-click.html
similarity index 85%
rename from third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-push-from-click.html
rename to third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-push-from-click.html
index f9abf559..3705039 100644
--- a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-push-from-click.html
+++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-push-from-click.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>View transitions: pageconceal navigationactivation for push navigations from user click</title>
+<title>View transitions: pageswap navigationactivation for push navigations from user click</title>
 <link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -27,7 +27,7 @@
 
 if (is_test_page) {
   const expectedUrl = location.href + "?new";
-  const expectedEvents = ["pageconceal", "transition", expectedUrl, "push","from", "pagehide"];
+  const expectedEvents = ["pageswap", "transition", expectedUrl, "push","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -57,10 +57,10 @@
           }
       }));
     });
-  }, `pageconceal on navigation from user click`);
+  }, `pageswap on navigation from user click`);
 } else if (is_popup_page) {
-  onpageconceal = (e) => {
-    window.opener.events.push("pageconceal");
+  onpageswap = (e) => {
+    window.opener.events.push("pageswap");
     if (e.viewTransition != null)
       window.opener.events.push("transition");
     window.opener.events.push(e.activation.entry.url);
@@ -76,5 +76,5 @@
 }
 </script>
 <body>
-  <a id="nav_link" href='/wpt_internal/view-transition-on-navigation/pageconceal-push-from-click.html?new'>Click me</a>
+  <a id="nav_link" href='/wpt_internal/view-transition-on-navigation/pageswap-push-from-click.html?new'>Click me</a>
  </body>
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-push-navigation.html b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-push-navigation.html
similarity index 85%
rename from third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-push-navigation.html
rename to third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-push-navigation.html
index 623b9ab..50a43e70 100644
--- a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-push-navigation.html
+++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-push-navigation.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>View transitions: pageconceal navigationactivation for push navigations</title>
+<title>View transitions: pageswap navigationactivation for push navigations</title>
 <link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -24,7 +24,7 @@
 
 if (is_test_page) {
   const expectedUrl = location.href + "?new";
-  const expectedEvents = ["pageconceal", "transition", expectedUrl, "push","from", "pagehide"];
+  const expectedEvents = ["pageswap", "transition", expectedUrl, "push","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -43,15 +43,15 @@
           }
       }));
     });
-  }, `pageconceal on navigation from script`);
+  }, `pageswap on navigation from script`);
 } else if (is_popup_page) {
   onload = () => {
     requestAnimationFrame(() => requestAnimationFrame(() => {
       location.href = location.href.split('?')[0] + '?new';
     }));
 
-    onpageconceal = (e) => {
-      window.opener.events.push("pageconceal");
+    onpageswap = (e) => {
+      window.opener.events.push("pageswap");
       if (e.viewTransition != null)
         window.opener.events.push("transition");
       window.opener.events.push(e.activation.entry.url);
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-push-with-redirect.html b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-push-with-redirect.html
similarity index 81%
rename from third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-push-with-redirect.html
rename to third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-push-with-redirect.html
index 54d39f1..bc14886 100644
--- a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-push-with-redirect.html
+++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-push-with-redirect.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>View transitions: pageconceal navigationactivation for push navigations with a same-origin redirect</title>
+<title>View transitions: pageswap navigationactivation for push navigations with a same-origin redirect</title>
 <link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -24,7 +24,7 @@
 
 if (is_test_page) {
   const expectedUrl = location.href + "?new";
-  const expectedEvents = ["pageconceal", "transition", expectedUrl, "push","from", "pagehide"];
+  const expectedEvents = ["pageswap", "transition", expectedUrl, "push","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -43,15 +43,15 @@
           }
       }));
     });
-  }, `pageconceal on navigation with same-origin redirect`);
+  }, `pageswap on navigation with same-origin redirect`);
 } else if (is_popup_page) {
   onload = () => {
     requestAnimationFrame(() => requestAnimationFrame(() => {
-      location.href = "/common/redirect.py?location=/wpt_internal/view-transition-on-navigation/pageconceal-push-with-redirect.html?new";
+      location.href = "/common/redirect.py?location=/wpt_internal/view-transition-on-navigation/pageswap-push-with-redirect.html?new";
     }));
 
-    onpageconceal = (e) => {
-      window.opener.events.push("pageconceal");
+    onpageswap = (e) => {
+      window.opener.events.push("pageswap");
       if (e.viewTransition != null)
         window.opener.events.push("transition");
       window.opener.events.push(e.activation.entry.url);
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-replace-navigation.html b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-replace-navigation.html
similarity index 85%
rename from third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-replace-navigation.html
rename to third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-replace-navigation.html
index 9d29140..18f63454 100644
--- a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-replace-navigation.html
+++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-replace-navigation.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>View transitions: pageconceal navigationactivation for replace navigations</title>
+<title>View transitions: pageswap navigationactivation for replace navigations</title>
 <link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -24,7 +24,7 @@
 
 if (is_test_page) {
   const expectedUrl = location.href.split('?')[0] + "?new";
-  const expectedEvents = ["pageconceal", "transition", expectedUrl, "replace","from", "pagehide"];
+  const expectedEvents = ["pageswap", "transition", expectedUrl, "replace","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -43,15 +43,15 @@
           }
       }));
     });
-  }, `pageconceal on replace navigation from script`);
+  }, `pageswap on replace navigation from script`);
 } else if (is_popup_page) {
   onload = () => {
     requestAnimationFrame(() => requestAnimationFrame(() => {
       location.replace(location.href.split('?')[0] + '?new');
     }));
 
-    onpageconceal = (e) => {
-      window.opener.events.push("pageconceal");
+    onpageswap = (e) => {
+      window.opener.events.push("pageswap");
       if (e.viewTransition != null)
         window.opener.events.push("transition");
       window.opener.events.push(e.activation.entry.url);
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-skip-transition.html b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-skip-transition.html
similarity index 90%
rename from third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-skip-transition.html
rename to third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-skip-transition.html
index 4ad4582..bfeee782 100644
--- a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-skip-transition.html
+++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-skip-transition.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>View transitions: skipTransition() in pageconceal aborts the transition</title>
+<title>View transitions: skipTransition() in pageswap aborts the transition</title>
 <link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -21,7 +21,7 @@
       location.replace(location.href + '?new');
     }));
   };
-  onpageconceal = (e) => {
+  onpageswap = (e) => {
     assert_not_equals(e.viewTransition, null);
     e.viewTransition.skipTransition();
   };
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-traverse-navigation-no-bfcache.https.html b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-traverse-navigation-no-bfcache.https.html
similarity index 88%
rename from third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-traverse-navigation-no-bfcache.https.html
rename to third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-traverse-navigation-no-bfcache.https.html
index 1d173b5..9137dc4 100644
--- a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageconceal-traverse-navigation-no-bfcache.https.html
+++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/pageswap-traverse-navigation-no-bfcache.https.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>View transitions: pageconceal navigationactivation for traverse navigations</title>
+<title>View transitions: pageswap navigationactivation for traverse navigations</title>
 <link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
 <link rel="author" href="mailto:khushalsagar@chromium.org">
 <script src="/resources/testharness.js"></script>
@@ -28,7 +28,7 @@
 // The test page which opens a popup for the navigation sequence.
 if (is_test_page) {
   const expectedUrl = location.href.split('?')[0] + "?popup";
-  const expectedEvents = ["pageconceal", "transition", expectedUrl, "traverse","from", "pagehide"];
+  const expectedEvents = ["pageswap", "transition", expectedUrl, "traverse","from", "pagehide"];
 
   promise_test(async t => {
     let popup;
@@ -47,7 +47,7 @@
           }
       }));
     });
-  }, `pageconceal on traverse navigation from script`);
+  }, `pageswap on traverse navigation from script`);
 } else if (is_initial_page_first_navigation) {
   // The popup page which the user navigates back to.
   onload = async () => {
@@ -67,8 +67,8 @@
     }));
   };
 
-  onpageconceal = (e) => {
-    window.opener.events.push("pageconceal");
+  onpageswap = (e) => {
+    window.opener.events.push("pageswap");
     if (e.viewTransition != null)
       window.opener.events.push("transition");
     window.opener.events.push(e.activation.entry.url);
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/prerender-removed-during-navigation.html b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/prerender-removed-during-navigation.html
index cd19213..d261b0d 100644
--- a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/prerender-removed-during-navigation.html
+++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/prerender-removed-during-navigation.html
@@ -71,7 +71,7 @@
 
   await ready_to_activate;
 
-  onpageconceal = () => {
+  onpageswap = () => {
     prerender_script.remove();
   }
 
diff --git a/third_party/chromium-variations b/third_party/chromium-variations
index 32e2e5c..2f49c50 160000
--- a/third_party/chromium-variations
+++ b/third_party/chromium-variations
@@ -1 +1 @@
-Subproject commit 32e2e5c8d0343434cf154f2b928775c2d95ad8c5
+Subproject commit 2f49c50b79ab7a6ee16f324656f0185a44fa50a6
diff --git a/third_party/depot_tools b/third_party/depot_tools
index 1ac3eb7..fbb0301 160000
--- a/third_party/depot_tools
+++ b/third_party/depot_tools
@@ -1 +1 @@
-Subproject commit 1ac3eb7b9844751478c7bdae4614f4d1e8b9b0f8
+Subproject commit fbb0301f1f70813fb62e1f64e05410b730c8417e
diff --git a/third_party/googletest/src b/third_party/googletest/src
index 76bb2af..dda72ef 160000
--- a/third_party/googletest/src
+++ b/third_party/googletest/src
@@ -1 +1 @@
-Subproject commit 76bb2afb8b522d24496ad1c757a49784fbfa2e42
+Subproject commit dda72ef32181edbfcd32a8c52b4740cd8061ab6f
diff --git a/third_party/openscreen/src b/third_party/openscreen/src
index ab2e341..614d391 160000
--- a/third_party/openscreen/src
+++ b/third_party/openscreen/src
@@ -1 +1 @@
-Subproject commit ab2e34151f1f147f3dd56f73cdf3ea5c6ad2d0a5
+Subproject commit 614d391f2236a5035b6e7be8d0278db63bddbce0
diff --git a/third_party/webrtc b/third_party/webrtc
index e5ac106..ede7529 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit e5ac106a357e2a1a088b732f0232d470de42f0cb
+Subproject commit ede75295d43032370f24bd4295693972ad27aaf0
diff --git a/tools/cast3p/runtime.version b/tools/cast3p/runtime.version
index f44b66d..be896b60 100644
--- a/tools/cast3p/runtime.version
+++ b/tools/cast3p/runtime.version
@@ -1 +1 @@
-400152
+404550
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
index cef7682..4571f88 100644
--- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -3737,6 +3737,8 @@
   <suffix name="Enterprise"
       label="Records metrics for enterprise real time URL lookup service."/>
   <affected-histogram name="SafeBrowsing.RT.BackoffState"/>
+  <affected-histogram
+      name="SafeBrowsing.RT.EventUrlReferrerChainFetchSucceeded"/>
   <affected-histogram name="SafeBrowsing.RT.GetCache.Time"/>
   <affected-histogram name="SafeBrowsing.RT.GetCacheResult"/>
   <affected-histogram name="SafeBrowsing.RT.HasTokenInRequest"/>
diff --git a/tools/metrics/histograms/metadata/history/OWNERS b/tools/metrics/histograms/metadata/history/OWNERS
index 8b39852..ec1d00ac 100644
--- a/tools/metrics/histograms/metadata/history/OWNERS
+++ b/tools/metrics/histograms/metadata/history/OWNERS
@@ -13,3 +13,7 @@
 
 # For History.* histograms
 sophiechang@chromium.org
+
+# For History.Embeddings.* histograms
+tommycli@chromium.org
+orinj@chromium.org
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml
index e3f0470..d75e33a 100644
--- a/tools/metrics/histograms/metadata/history/histograms.xml
+++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -1834,6 +1834,38 @@
   </summary>
 </histogram>
 
+<histogram name="History.Embeddings.Passages.ExtractionTime" units="ms"
+    expires_after="2024-12-31">
+  <owner>orinj@chromium.org</owner>
+  <owner>tommycli@chromium.org</owner>
+  <summary>
+    Round trip request and response time for a single passage extraction. The
+    clock starts just before the browser requests passages from a renderer, and
+    stops just after results are received. Logged each time passages are
+    successfully retrieved from a RenderFrameHost.
+  </summary>
+</histogram>
+
+<histogram name="History.Embeddings.Passages.PassageCount" units="passages"
+    expires_after="2024-12-31">
+  <owner>orinj@chromium.org</owner>
+  <owner>tommycli@chromium.org</owner>
+  <summary>
+    Number of passages retrieved from a single page passage extraction. Logged
+    each time passages are retrieved from a RenderFrameHost.
+  </summary>
+</histogram>
+
+<histogram name="History.Embeddings.Passages.TotalTextSize" units="bytes"
+    expires_after="2024-12-31">
+  <owner>orinj@chromium.org</owner>
+  <owner>tommycli@chromium.org</owner>
+  <summary>
+    The sum of passage text sizes for all passages retrieved from an extraction.
+    Logged each time passages are retrieved from a RenderFrameHost.
+  </summary>
+</histogram>
+
 <histogram name="History.FaviconDatabaseSizeMB" units="MB" expires_after="M130">
   <owner>rogerm@chromium.org</owner>
   <owner>sky@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
index 33dd7ff0..465a5b7 100644
--- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -2076,6 +2076,18 @@
   </summary>
 </histogram>
 
+<histogram name="SafeBrowsing.RT.EventUrlReferrerChainFetchSucceeded"
+    enum="BooleanSuccess" expires_after="2024-08-21">
+  <owner>thefrog@chromium.org</owner>
+  <owner>chrome-counter-abuse-alerts@google.com</owner>
+  <summary>
+    Logged when fetching the referrer chain for a pending event URL is not able
+    to find a matching navigation event, so the referrer chain is fetched for
+    non-pending event URLs instead as a fallback. Logs true if the fallback
+    fetch returns a non-empty chain.
+  </summary>
+</histogram>
+
 <histogram name="SafeBrowsing.RT.GetCache.FallbackThreatType"
     enum="SBThreatType" expires_after="2025-01-22">
   <owner>xinghuilu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/storage/histograms.xml b/tools/metrics/histograms/metadata/storage/histograms.xml
index 89cbe5d..1ec2e5b 100644
--- a/tools/metrics/histograms/metadata/storage/histograms.xml
+++ b/tools/metrics/histograms/metadata/storage/histograms.xml
@@ -335,35 +335,6 @@
   </summary>
 </histogram>
 
-<histogram name="Storage.Blob.RegisterURLTimeWithoutPartitioningSupport"
-    units="ms" expires_after="2024-02-20">
-  <owner>awillia@chromium.org</owner>
-  <owner>chrome-owp-storage@chromium.org</owner>
-  <summary>
-    Recorded when the PublicURLManager::RegisterURL method calls the per-process
-    BlobURLStore::Register mojo interface method. The value recorded is the time
-    taken for the call to complete. This histogram is only logged when the
-    SupportPartitionedBlobUrl feature is disabled.
-  </summary>
-</histogram>
-
-<histogram name="Storage.Blob.RegisterURLTimeWithPartitioningSupport.{Type}"
-    units="ms" expires_after="2024-06-30">
-  <owner>awillia@chromium.org</owner>
-  <owner>chrome-owp-storage@chromium.org</owner>
-  <summary>
-    Recorded when the PublicURLManager::RegisterURL method calls the
-    BlobURLStore::Register mojo interface method. The value recorded is the time
-    taken for the call to complete. This variation of the histogram records
-    results from {Type}. This histogram is only logged when the
-    SupportPartitionedBlobUrl feature is enabled.
-  </summary>
-  <token key="Type">
-    <variant name="Frame" summary="frame execution contexts"/>
-    <variant name="Worker" summary="worker execution contexts"/>
-  </token>
-</histogram>
-
 <histogram name="Storage.Buckets.BucketCount" units="buckets"
     expires_after="2024-04-01">
   <owner>estade@chromium.org</owner>
diff --git a/tools/metrics/structured/gen_validator.py b/tools/metrics/structured/gen_validator.py
index 35ca55450..4ef4445 100755
--- a/tools/metrics/structured/gen_validator.py
+++ b/tools/metrics/structured/gen_validator.py
@@ -28,7 +28,7 @@
   if args.cros_input is not None:
     cros_structured = model.Model(
         open(args.cros_input, encoding='utf-8').read(), 'cros')
-    structured = model.MergeModels(structured, cros_structured)
+    structured = model.merge_models(structured, cros_structured)
 
   codegen.ValidatorHeaderTemplate(
       args.output, 'structured_metrics_validator.h').write_file()
diff --git a/tools/metrics/structured/sync/model.py b/tools/metrics/structured/sync/model.py
index fae9f8b9..835303d9 100644
--- a/tools/metrics/structured/sync/model.py
+++ b/tools/metrics/structured/sync/model.py
@@ -107,7 +107,8 @@
 </structured-metrics>"""
 
 
-def MergeModels(primary: Model, other: Model) -> Model:
+def merge_models(primary: Model, other: Model) -> Model:
+  """Merges two models into one."""
   primary.projects += [
       p for p in other.projects if not re.match('Test', p.name)
   ]
diff --git a/tools/perf/contrib/shared_storage/shared_storage.py b/tools/perf/contrib/shared_storage/shared_storage.py
index 7420768..f657f120 100644
--- a/tools/perf/contrib/shared_storage/shared_storage.py
+++ b/tools/perf/contrib/shared_storage/shared_storage.py
@@ -14,8 +14,6 @@
 from telemetry.timeline import chrome_trace_category_filter
 from telemetry.web_perf import timeline_based_measurement
 
-from py_utils import xvfb
-
 # Features to enable via command line.
 _ENABLED_FEATURES = [
     'SharedStorageAPI:ExposeDebugMessageForSettingsStatus/true',
@@ -91,8 +89,8 @@
       logging.warning('The maximum allowed number of iterations is 10. ' +
                       'Increase pageset_repeat instead.')
       cls.iterations = _MAX_NUM_ITERATIONS
-    if args.xvfb and xvfb.ShouldStartXvfb():
-      cls.xvfb_process = xvfb.StartXvfb()
+    if args.xvfb and utils.ShouldStartXvfb():
+      cls.xvfb_process = utils.StartXvfb()
 
   def SetExtraBrowserOptions(self, options):
     # `options` is an instance of `browser_options.BrowserOptions`.
diff --git a/tools/perf/contrib/shared_storage/utils/__init__.py b/tools/perf/contrib/shared_storage/utils/__init__.py
index 823762d..6aef145 100644
--- a/tools/perf/contrib/shared_storage/utils/__init__.py
+++ b/tools/perf/contrib/shared_storage/utils/__init__.py
@@ -15,6 +15,8 @@
     'JsonDump',
     'MovePreviousExpectedHistogramsFile',
     'ProcessResults',
+    'ShouldStartXvfb',
+    'StartXvfb',
 ]
 
 from .file_util import (CleanUpRunPathFile, EnsureDataDir,
@@ -25,4 +27,5 @@
                              GetSharedStorageIteratorHistograms,
                              GetSharedStorageUmaHistograms)
 from .process_results import ProcessResults
+from .xvfb import ShouldStartXvfb, StartXvfb
 from .util import GetNonePlaceholder, JsonDump
diff --git a/tools/perf/contrib/shared_storage/utils/xvfb.py b/tools/perf/contrib/shared_storage/utils/xvfb.py
new file mode 100644
index 0000000..092c10ac
--- /dev/null
+++ b/tools/perf/contrib/shared_storage/utils/xvfb.py
@@ -0,0 +1,47 @@
+# Copyright 2024 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import logging
+import subprocess
+import platform
+import time
+
+
+def _GetLockFilePath(server_num):
+  return "/tmp/.X11-unix/X{}".format(server_num)
+
+
+def ShouldStartXvfb():
+  # TODO(crbug.com/973847): Note that you can locally change this to return
+  # False to diagnose timeouts for dev server tests.
+  return platform.system() == 'Linux'
+
+
+def StartXvfb():
+  # Get a number of an available server.
+  server_num = 99
+  while os.path.exists(_GetLockFilePath(server_num)):
+    server_num += 1
+
+  display = ':{}'.format(server_num)
+  xvfb_command = ['Xvfb', display, '-screen', '0', '1024x769x24', '-ac']
+  xvfb_process = subprocess.Popen(xvfb_command,
+                                  stdout=subprocess.PIPE,
+                                  stderr=subprocess.STDOUT)
+  time.sleep(0.2)
+  returncode = xvfb_process.poll()
+  if returncode is None:
+    os.environ['DISPLAY'] = display
+
+    # Use print instead of logging to ensure that the recommendation to remove
+    # the lock file is displayed regardless of verbosity settings.
+    print('Started Xvfb on display %s.' % display)
+    print('If test fails to exit cleanly, it is recommended that you manually'
+          ' remove the file "%s".\n' % _GetLockFilePath(server_num))
+  else:
+    logging.error('Xvfb did not start, returncode: %s, stdout:\n%s', returncode,
+                  xvfb_process.stdout.read())
+    xvfb_process = None
+  return xvfb_process
diff --git a/tools/perf/page_sets/rendering/motionmark.py b/tools/perf/page_sets/rendering/motionmark.py
index df88e5f..afdbfca 100644
--- a/tools/perf/page_sets/rendering/motionmark.py
+++ b/tools/perf/page_sets/rendering/motionmark.py
@@ -257,16 +257,12 @@
 
   def RunPageInteractions(self, action_runner):
     with action_runner.CreateInteraction('Filter'):
-      action_runner.Wait(2)
       action_runner.WaitForJavaScriptCondition(
           'window.benchmarkRunnerClient.results._results')
 
-    # Navigate to about:blank to stop rendering frames and let the device
-    # cool down while the trace data for the story is processed.
-    action_runner.Navigate('about:blank')
-
   @classmethod
-  def GetFixed2SecondsUrl(cls, suite_name, test_name, complexity):
+  def GetFixed2SecondsUrl(cls, suite_name, test_name, complexity,
+                          test_interval):
     # Strip unwanted characters from names
     for ch in [' ', '.', ',']:
       suite_name = suite_name.replace(ch, '')
@@ -278,65 +274,68 @@
         '?suite-name=%s'
         '&test-name=%s'
         '&complexity=%d'
-        '&test-interval=2'
-        '&warmup-length=100'
-        '&warmup-frame-count=10'
+        '&test-interval=%d'
+        '&warmup-length=0'
+        '&warmup-frame-count=0'
         '&first-frame-minimum-length=0'
         '&display=minimal'
         '&tiles=big'
         '&controller=fixed'
         '&system-frame-rate=60'
         '&frame-rate=60'
-        '&time-measurement=performance') % (suite_name, test_name, complexity)
+        '&time-measurement=performance') % (suite_name, test_name, complexity,
+                                            test_interval)
 
 
 #Numbers for complexity based on MotionMark score for chrome build without PGO
+#TODO(vmiura): Update names from fixed_2_seconds to match the new durations.
 class MotionMarkFixed2SecondsMultiply(MotionMarkFixed2SecondsPage):
   BASE_NAME = 'motionmark_fixed_2_seconds_multiply'
   URL = MotionMarkFixed2SecondsPage.GetFixed2SecondsUrl('MotionMark',
-                                                        'Multiply', 1396)
+                                                        'Multiply', 1396, 5)
 
 
 class MotionMarkFixed2SecondsCanvasArcs(MotionMarkFixed2SecondsPage):
   BASE_NAME = 'motionmark_fixed_2_seconds_canvas_arcs'
   URL = MotionMarkFixed2SecondsPage.GetFixed2SecondsUrl('MotionMark',
-                                                        'Canvas Arcs', 6194)
+                                                        'Canvas Arcs', 6194, 5)
 
 
 class MotionMarkFixed2SecondsLeaves(MotionMarkFixed2SecondsPage):
   BASE_NAME = 'motionmark_fixed_2_seconds_leaves'
   URL = MotionMarkFixed2SecondsPage.GetFixed2SecondsUrl('MotionMark', 'Leaves',
-                                                        1377)
+                                                        1377, 5)
 
 
 class MotionMarkFixed2SecondsPaths(MotionMarkFixed2SecondsPage):
   BASE_NAME = 'motionmark_fixed_2_seconds_paths'
   URL = MotionMarkFixed2SecondsPage.GetFixed2SecondsUrl('MotionMark', 'Paths',
-                                                        29172)
+                                                        29172, 5)
 
 
 class MotionMarkFixed2SecondsCanvasLines(MotionMarkFixed2SecondsPage):
   BASE_NAME = 'motionmark_fixed_2_seconds_canvas_lines'
   URL = MotionMarkFixed2SecondsPage.GetFixed2SecondsUrl('MotionMark',
-                                                        'Canvas Lines', 16520)
+                                                        'Canvas Lines', 16520,
+                                                        5)
 
 
 class MotionMarkFixed2SecondsImages(MotionMarkFixed2SecondsPage):
   BASE_NAME = 'motionmark_fixed_2_seconds_images'
   URL = MotionMarkFixed2SecondsPage.GetFixed2SecondsUrl('MotionMark', 'Images',
-                                                        200)
+                                                        200, 5)
 
 
 class MotionMarkFixed2SecondsDesign(MotionMarkFixed2SecondsPage):
   BASE_NAME = 'motionmark_fixed_2_seconds_design'
   URL = MotionMarkFixed2SecondsPage.GetFixed2SecondsUrl('MotionMark', 'Design',
-                                                        213)
+                                                        213, 5)
 
 
 class MotionMarkFixed2SecondsSuits(MotionMarkFixed2SecondsPage):
   BASE_NAME = 'motionmark_fixed_2_seconds_suits'
   URL = MotionMarkFixed2SecondsPage.GetFixed2SecondsUrl('MotionMark', 'Suits',
-                                                        1299)
+                                                        1299, 5)
 
 
 @benchmark.Info(emails=['chrome-skia-graphite@google.com'],
diff --git a/tools/perf/process_perf_results.pydeps b/tools/perf/process_perf_results.pydeps
index 1983fb12..a9906b7 100644
--- a/tools/perf/process_perf_results.pydeps
+++ b/tools/perf/process_perf_results.pydeps
@@ -39,7 +39,6 @@
 ../../third_party/catapult/common/py_utils/py_utils/tempfile_ext.py
 ../../third_party/catapult/common/py_utils/py_utils/ts_proxy_server.py
 ../../third_party/catapult/common/py_utils/py_utils/webpagereplay_go_server.py
-../../third_party/catapult/common/py_utils/py_utils/xvfb.py
 ../../third_party/catapult/common/py_vulcanize/py_vulcanize/__init__.py
 ../../third_party/catapult/common/py_vulcanize/py_vulcanize/generate.py
 ../../third_party/catapult/common/py_vulcanize/py_vulcanize/html_generation_controller.py
@@ -563,6 +562,7 @@
 contrib/shared_storage/utils/histogram_list.py
 contrib/shared_storage/utils/process_results.py
 contrib/shared_storage/utils/util.py
+contrib/shared_storage/utils/xvfb.py
 contrib/system_health_scroll_jank/__init__.py
 contrib/system_health_scroll_jank/janky_story_set.py
 contrib/system_health_scroll_jank/system_health_scroll_jank.py
diff --git a/tools/utr/recipe.py b/tools/utr/recipe.py
index df887ba..54d5872 100644
--- a/tools/utr/recipe.py
+++ b/tools/utr/recipe.py
@@ -75,7 +75,8 @@
     # Add UTR recipe props. Its schema is located at:
     # https://chromium.googlesource.com/chromium/tools/build/+/HEAD/recipes/recipes/chromium/universal_test_runner.proto
     input_props = builder_props.copy()
-    input_props['checkout_path'] = str(_SRC_DIR.parent)
+    input_props['checkout_path'] = str(_SRC_DIR)
+    input_props['$recipe_engine/path'] = {'cache_dir': str(_SRC_DIR.parent)}
     input_props['test_names'] = tests
     if build_dir:
       input_props['build_dir'] = build_dir
diff --git a/tools/utr/recipe_test.py b/tools/utr/recipe_test.py
index d363764..45c028a 100755
--- a/tools/utr/recipe_test.py
+++ b/tools/utr/recipe_test.py
@@ -27,14 +27,16 @@
 
   def testProps(self):
     runner = recipe.LegacyRunner(self.tmp_dir, {}, 'some-bucket',
-                                 'some-builder', [], False, False)
+                                 'some-builder', 'swarming-server', [], False,
+                                 False)
     self.assertEqual(
         runner._input_props['$recipe_engine/buildbucket']['build']['builder']
         ['builder'], 'some-builder')
 
   def testRun(self):
     runner = recipe.LegacyRunner(self.tmp_dir, {}, 'some-bucket',
-                                 'some-builder', [], False, False)
+                                 'some-builder', 'swarming-server', [], False,
+                                 False)
     self.subp_mock.returncode = 123
     with mock.patch('subprocess.Popen', return_value=self.subp_mock):
       exit_code, _ = runner.run_recipe()
@@ -42,7 +44,8 @@
 
   def testJson(self):
     runner = recipe.LegacyRunner(self.tmp_dir, {}, 'some-bucket',
-                                 'some-builder', [], False, False)
+                                 'some-builder', 'swarming-server', [], False,
+                                 False)
     with mock.patch('tempfile.TemporaryDirectory', return_value=self.tmp_dir):
       with mock.patch('subprocess.Popen', return_value=self.subp_mock):
         # Missing json file
diff --git a/ui/base/cocoa/text_services_context_menu.mm b/ui/base/cocoa/text_services_context_menu.mm
index edd094b..31b6ca6 100644
--- a/ui/base/cocoa/text_services_context_menu.mm
+++ b/ui/base/cocoa/text_services_context_menu.mm
@@ -70,19 +70,20 @@
 
 namespace ui {
 
-// When running on an OS release earlier than macOS 14, do this as well, for two
-// reasons:
+// When running on an OS release earlier than macOS 14, or running on macOS 14.4
+// and later, do this as well, for two reasons:
 //
 // 1. Interoperability with the other parts of the system that use this same
 //    speech synthesizer.
 //
 // 2. Working around a bug in `AVSpeechSynthesizer` which does not provide the
 //    correct voice when a specific voice is chosen in the system accessibility
-//    settings (see https://crbug.com/1484940#c9, FB13197951).
+//    settings (see https://crbug.com/40072850#comment10, FB13197951).
 //
-// However, for macOS 14, directly use the deprecated NSSpeechSynthesizer class,
-// as there is a bug with the NSApplication provided methods that causes
-// occasional hiccups in the audio (see https://crbug.com/1489906, FB13261400).
+// However, for macOS 14.0 through 14.3, directly use the deprecated
+// NSSpeechSynthesizer class, as there is a bug with the NSApplication provided
+// methods that causes occasional hiccups in the audio (see
+// https://crbug.com/40074199, FB13261400).
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -117,7 +118,8 @@
 #pragma clang diagnostic pop
 
 void TextServicesContextMenu::SpeakText(const std::u16string& text) {
-  if (base::mac::MacOSVersion() >= 14'00'00) {
+  int version = base::mac::MacOSVersion();
+  if (version >= 14'00'00 && version < 14'04'00) {
     FB13261400Workaround::SpeakText(text);
   } else {
     [NSApp speakString:base::SysUTF16ToNSString(text)];
@@ -125,7 +127,8 @@
 }
 
 void TextServicesContextMenu::StopSpeaking() {
-  if (base::mac::MacOSVersion() >= 14'00'00) {
+  int version = base::mac::MacOSVersion();
+  if (version >= 14'00'00 && version < 14'04'00) {
     FB13261400Workaround::StopSpeaking();
   } else {
     [NSApp stopSpeaking:nil];
@@ -133,7 +136,8 @@
 }
 
 bool TextServicesContextMenu::IsSpeaking() {
-  if (base::mac::MacOSVersion() >= 14'00'00) {
+  int version = base::mac::MacOSVersion();
+  if (version >= 14'00'00 && version < 14'04'00) {
     return FB13261400Workaround::IsSpeaking();
   } else {
     return [NSApp isSpeaking];
diff --git a/v8 b/v8
index 4089389..68087ab 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit 408938972fdca848d564d0bd80139df8a90e53a5
+Subproject commit 68087ab41a76501a5364273a52cd395f0e7033b3